From 1843ff222d281bf850172f0a69bfcc65421a66db Mon Sep 17 00:00:00 2001 From: Ibnu Maksum Date: Fri, 2 Aug 2024 16:34:18 +0700 Subject: [PATCH 001/841] tbl_customers_inbox --- install/phpnuxbill.sql | 12 ++++++++++++ system/updates.json | 3 +++ 2 files changed, 15 insertions(+) diff --git a/install/phpnuxbill.sql b/install/phpnuxbill.sql index 1e10fb22..73a3be1b 100644 --- a/install/phpnuxbill.sql +++ b/install/phpnuxbill.sql @@ -222,6 +222,18 @@ CREATE TABLE `rad_acct` ( `dateAdded` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; +CREATE TABLE IF NOT EXISTS `tbl_customers_inbox` ( + `id` int UNSIGNED NOT NULL AUTO_INCREMENT, + `customer_id` int NOT NULL, + `date_created` datetime NOT NULL, + `date_read` datetime DEFAULT NULL, + `subject` varchar(64) COLLATE utf8mb4_general_ci NOT NULL, + `body` varchar(512) COLLATE utf8mb4_general_ci NOT NULL, + `from` varchar(8) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT 'System' COMMENT 'System or Admin or Else', + `admin_id` int NOT NULL DEFAULT '0' COMMENT 'other than admin is 0', + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; + ALTER TABLE `rad_acct` ADD PRIMARY KEY (`id`), diff --git a/system/updates.json b/system/updates.json index 72a5bfbd..eee72c33 100644 --- a/system/updates.json +++ b/system/updates.json @@ -133,5 +133,8 @@ "2024.8.1" : [ "ALTER TABLE `tbl_payment_gateway` CHANGE `gateway_trx_id` `gateway_trx_id` VARCHAR(512) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '';", "ALTER TABLE `tbl_payment_gateway` CHANGE `pg_url_payment` `pg_url_payment` VARCHAR(512) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '';" + ], + "2024.8.2" : [ + "CREATE TABLE IF NOT EXISTS `tbl_customers_inbox` (`id` int UNSIGNED NOT NULL AUTO_INCREMENT, `customer_id` int NOT NULL, `date_created` datetime NOT NULL, `date_read` datetime DEFAULT NULL, `subject` varchar(64) COLLATE utf8mb4_general_ci NOT NULL, `body` varchar(512) COLLATE utf8mb4_general_ci NOT NULL, `from` varchar(8) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT 'System' COMMENT 'System or Admin or Else',`admin_id` int NOT NULL DEFAULT '0' COMMENT 'other than admin is 0', PRIMARY KEY (`id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;" ] } \ No newline at end of file From 587437c93c75a2115965df389745f0072f21f4fb Mon Sep 17 00:00:00 2001 From: Ibnu Maksum Date: Fri, 2 Aug 2024 17:22:42 +0700 Subject: [PATCH 002/841] customer inbox --- install/phpnuxbill.sql | 3 +- system/controllers/autoload_user.php | 12 +++++ system/controllers/mail.php | 46 +++++++++++++++++ ui/ui/paymentgateway-audit.tpl | 3 +- ui/ui/sections/user-header.tpl | 20 ++++++++ ui/ui/user-inbox.tpl | 75 ++++++++++++++++++++++++++++ 6 files changed, 156 insertions(+), 3 deletions(-) create mode 100644 system/controllers/mail.php create mode 100644 ui/ui/user-inbox.tpl diff --git a/install/phpnuxbill.sql b/install/phpnuxbill.sql index 73a3be1b..f66eb5c4 100644 --- a/install/phpnuxbill.sql +++ b/install/phpnuxbill.sql @@ -222,7 +222,8 @@ CREATE TABLE `rad_acct` ( `dateAdded` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; -CREATE TABLE IF NOT EXISTS `tbl_customers_inbox` ( +DROP TABLE IF EXISTS `tbl_customers_inbox`; +CREATE TABLE `tbl_customers_inbox` ( `id` int UNSIGNED NOT NULL AUTO_INCREMENT, `customer_id` int NOT NULL, `date_created` datetime NOT NULL, diff --git a/system/controllers/autoload_user.php b/system/controllers/autoload_user.php index 6e67f7c3..78b51c14 100644 --- a/system/controllers/autoload_user.php +++ b/system/controllers/autoload_user.php @@ -45,6 +45,18 @@ switch ($action) { die('--'); } break; + case 'inbox_unread': + $count = ORM::for_table('tbl_customers_inbox')->where('customer_id', $user['id'])->whereRaw('date_read is null')->count('id'); + if($count>0){ + echo $count; + } + die(); + case 'inbox': + $inboxs = ORM::for_table('tbl_customers_inbox')->selects(['id', 'subject', 'date_created'])->where('customer_id', $user['id'])->whereRaw('date_read is null')->order_by_desc('date_created')->limit(10)->find_many(); + foreach($inboxs as $inbox){ + echo '
  • '.$inbox['subject'].'
    '.Lang::dateTimeFormat($inbox['date_created']).'
  • '; + } + die(); default: $ui->display('404.tpl'); } diff --git a/system/controllers/mail.php b/system/controllers/mail.php new file mode 100644 index 00000000..c47f0b9d --- /dev/null +++ b/system/controllers/mail.php @@ -0,0 +1,46 @@ +assign('_user', $user); + +switch ($action) { + case 'view': + $mail = ORM::for_table('tbl_customers_inbox')->where('customer_id', $user['id'])->find_one($routes['2']); + if(!$mail){ + r2(U. 'mail', 'e', Lang::T('Message Not Found')); + } + if($mail['date_read'] == null){ + $mail->date_read = date('Y-m-d H:i:s'); + $mail->save(); + } + $ui->assign('mail', $mail); + $ui->assign('tipe', 'view'); + $ui->assign('_system_menu', 'inbox'); + $ui->assign('_title', Lang::T('Inbox')); + $ui->display('user-inbox.tpl'); + default: + $q = _req('q'); + $limit = 40; + $p = (int) _req('p', 0); + $offset = $p * $limit; + $query = ORM::for_table('tbl_customers_inbox')->where('customer_id', $user['id'])->order_by_desc('date_created'); + $query->limit($limit)->offset($offset); + if(!empty($q)){ + $query->whereRaw("(subject like '%$q%' or body like '%$q%')"); + } + $mails = $query->find_array(); + $ui->assign('tipe', ''); + $ui->assign('q', $q); + $ui->assign('p', $p); + $ui->assign('mails', $mails); + $ui->assign('_system_menu', 'inbox'); + $ui->assign('_title', Lang::T('Inbox')); + $ui->display('user-inbox.tpl'); +} \ No newline at end of file diff --git a/ui/ui/paymentgateway-audit.tpl b/ui/ui/paymentgateway-audit.tpl index 7c97a2f0..e10de7d3 100644 --- a/ui/ui/paymentgateway-audit.tpl +++ b/ui/ui/paymentgateway-audit.tpl @@ -9,8 +9,7 @@
    - +
    diff --git a/ui/ui/sections/user-header.tpl b/ui/ui/sections/user-header.tpl index e625871f..ffde8b59 100644 --- a/ui/ui/sections/user-header.tpl +++ b/ui/ui/sections/user-header.tpl @@ -87,6 +87,19 @@ @@ -66,17 +73,18 @@
    - +
    @@ -100,7 +108,7 @@ {foreach $d as $ds} - + {$ds['username']} {$ds['account_type']} @@ -110,7 +118,8 @@ {if $ds['phonenumber']} + title="{$ds['phonenumber']}"> {/if} {if $ds['email']}   {Lang::T('Edit')}   -   {Lang::T('Sync')}   + {include file="pagination.tpl"} - - - - - -{include file="sections/footer.tpl"} +{include file="sections/footer.tpl"} \ No newline at end of file From 7d2f69f96fe0762c943660d88af9ae76bcde232e Mon Sep 17 00:00:00 2001 From: Ibnu Maksum Date: Mon, 5 Aug 2024 15:20:18 +0700 Subject: [PATCH 013/841] Router Maps --- CHANGELOG.md | 1 + install/phpnuxbill.sql | 2 + system/autoload/Paginator.php | 8 +- system/controllers/customers.php | 1 - system/controllers/routers.php | 85 +++++++++----- system/lan/english.json | 6 +- system/updates.json | 4 + ui/ui/routers-edit.tpl | 185 ++++++++++++++++++++++--------- ui/ui/routers-maps.tpl | 84 ++++++++++++++ ui/ui/routers.tpl | 15 ++- ui/ui/sections/header.tpl | 6 +- version.json | 2 +- 12 files changed, 306 insertions(+), 93 deletions(-) create mode 100644 ui/ui/routers-maps.tpl diff --git a/CHANGELOG.md b/CHANGELOG.md index 717b42c8..25c78165 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ - Add pppoe customer and pppoe IP to make static username and IP - Add Sync button - Allow Mac Address Username +- Router Maps ## 2024.8.1 diff --git a/install/phpnuxbill.sql b/install/phpnuxbill.sql index 4bf59e16..e3b66ef4 100644 --- a/install/phpnuxbill.sql +++ b/install/phpnuxbill.sql @@ -137,6 +137,8 @@ CREATE TABLE `tbl_routers` ( `username` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, `password` varchar(60) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, `description` varchar(256) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL, + `coordinates` VARCHAR(50) NOT NULL DEFAULT '', + `coverage` VARCHAR(8) NOT NULL DEFAULT '0', `enabled` tinyint(1) NOT NULL DEFAULT '1' COMMENT '0 disabled' ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; diff --git a/system/autoload/Paginator.php b/system/autoload/Paginator.php index 3899d7b9..3d8b9014 100644 --- a/system/autoload/Paginator.php +++ b/system/autoload/Paginator.php @@ -8,7 +8,7 @@ class Paginator { - public static function findMany($query, $search = [], $per_page = '10', $append_url = "") + public static function findMany($query, $search = [], $per_page = '10', $append_url = "", $toArray = false) { global $routes, $ui; $adjacents = "2"; @@ -71,7 +71,11 @@ class Paginator if ($ui) { $ui->assign('paginator', $result); } - return $query->offset($startpoint)->limit($per_page)->find_many(); + if($toArray){ + return $query->offset($startpoint)->limit($per_page)->find_array(); + }else{ + return $query->offset($startpoint)->limit($per_page)->find_many(); + } } } diff --git a/system/controllers/customers.php b/system/controllers/customers.php index baf166cd..5aa83e80 100644 --- a/system/controllers/customers.php +++ b/system/controllers/customers.php @@ -713,7 +713,6 @@ switch ($action) { die(); } $d = Paginator::findMany($query, ['search' => $search], 30, $append_url); - $ui->assign('xheader', ''); $ui->assign('d', $d); $ui->assign('statuses', ORM::for_table('tbl_customers')->getEnum("status")); $ui->assign('filter', $filter); diff --git a/system/controllers/routers.php b/system/controllers/routers.php index a507207a..23bbbfb7 100644 --- a/system/controllers/routers.php +++ b/system/controllers/routers.php @@ -18,24 +18,26 @@ if (!in_array($admin['user_type'], ['SuperAdmin', 'Admin'])) { _alert(Lang::T('You do not have permission to access this page'), 'danger', "dashboard"); } +$leafletpickerHeader = << +EOT; + switch ($action) { - case 'list': - $ui->assign('xfooter', ''); - + case 'maps': $name = _post('name'); + $query = ORM::for_table('tbl_routers')->where_not_equal('coordinates', '')->order_by_desc('id'); + $query->selects(['id', 'name', 'coordinates', 'description', 'coverage', 'enabled']); if ($name != '') { - $query = ORM::for_table('tbl_routers')->where_like('name', '%' . $name . '%')->order_by_desc('id'); - $d = Paginator::findMany($query, ['name' => $name]); - } else { - $query = ORM::for_table('tbl_routers')->order_by_desc('id'); - $d = Paginator::findMany($query); + $query->where_like('name', '%' . $name . '%'); } - + $d = Paginator::findMany($query, ['name' => $name], '20', '', true); + $ui->assign('name', $name); $ui->assign('d', $d); - run_hook('view_list_routers'); #HOOK - $ui->display('routers.tpl'); + $ui->assign('_title', Lang::T('Routers Geo Location Information')); + $ui->assign('xheader', $leafletpickerHeader); + $ui->assign('xfooter', ''); + $ui->display('routers-maps.tpl'); break; - case 'add': run_hook('view_add_routers'); #HOOK $ui->display('routers-add.tpl'); @@ -47,6 +49,7 @@ switch ($action) { if (!$d) { $d = ORM::for_table('tbl_routers')->where_equal('name', _get('name'))->find_one(); } + $ui->assign('xheader', $leafletpickerHeader); if ($d) { $ui->assign('d', $d); run_hook('view_router_edit'); #HOOK @@ -75,16 +78,18 @@ switch ($action) { $enabled = _post('enabled'); $msg = ''; - if (Validator::Length($name, 30, 4) == false) { - $msg .= 'Name should be between 5 to 30 characters' . '
    '; - } - if ($ip_address == '' or $username == '') { - $msg .= Lang::T('All field is required') . '
    '; + if (Validator::Length($name, 30, 1) == false) { + $msg .= 'Name should be between 1 to 30 characters' . '
    '; } + if($enabled || _post("testIt")){ + if ($ip_address == '' or $username == '') { + $msg .= Lang::T('All field is required') . '
    '; + } - $d = ORM::for_table('tbl_routers')->where('ip_address', $ip_address)->find_one(); - if ($d) { - $msg .= Lang::T('IP Router Already Exist') . '
    '; + $d = ORM::for_table('tbl_routers')->where('ip_address', $ip_address)->find_one(); + if ($d) { + $msg .= Lang::T('IP Router Already Exist') . '
    '; + } } if (strtolower($name) == 'radius') { $msg .= 'Radius name is reserved
    '; @@ -92,7 +97,7 @@ switch ($action) { if ($msg == '') { run_hook('add_router'); #HOOK - if(_post("testIt")){ + if (_post("testIt")) { (new MikrotikHotspot())->getClient($ip_address, $username, $password); } $d = ORM::for_table('tbl_routers')->create(); @@ -104,7 +109,7 @@ switch ($action) { $d->enabled = $enabled; $d->save(); - r2(U . 'routers/list', 's', Lang::T('Data Created Successfully')); + r2(U . 'routers/edit/' . $d->id(), 's', Lang::T('Data Created Successfully')); } else { r2(U . 'routers/add', 'e', $msg); } @@ -117,13 +122,17 @@ switch ($action) { $username = _post('username'); $password = _post('password'); $description = _post('description'); + $coordinates = _post('coordinates'); + $coverage = _post('coverage'); $enabled = $_POST['enabled']; $msg = ''; if (Validator::Length($name, 30, 4) == false) { $msg .= 'Name should be between 5 to 30 characters' . '
    '; } - if ($ip_address == '' or $username == '') { - $msg .= Lang::T('All field is required') . '
    '; + if($enabled || _post("testIt")){ + if ($ip_address == '' or $username == '') { + $msg .= Lang::T('All field is required') . '
    '; + } } $id = _post('id'); @@ -141,10 +150,12 @@ switch ($action) { } $oldname = $d['name']; - if ($d['ip_address'] != $ip_address) { - $c = ORM::for_table('tbl_routers')->where('ip_address', $ip_address)->where_not_equal('id', $id)->find_one(); - if ($c) { - $msg .= 'IP Already Exists
    '; + if($enabled || _post("testIt")){ + if ($d['ip_address'] != $ip_address) { + $c = ORM::for_table('tbl_routers')->where('ip_address', $ip_address)->where_not_equal('id', $id)->find_one(); + if ($c) { + $msg .= 'IP Already Exists
    '; + } } } @@ -154,7 +165,7 @@ switch ($action) { if ($msg == '') { run_hook('router_edit'); #HOOK - if(_post("testIt")){ + if (_post("testIt")) { (new MikrotikHotspot())->getClient($ip_address, $username, $password); } $d->name = $name; @@ -162,6 +173,8 @@ switch ($action) { $d->username = $username; $d->password = $password; $d->description = $description; + $d->coordinates = $coordinates; + $d->coverage = $coverage; $d->enabled = $enabled; $d->save(); if ($name != $oldname) { @@ -191,5 +204,17 @@ switch ($action) { break; default: - r2(U . 'routers/list/', 's', ''); + $ui->assign('xfooter', ''); + + $name = _post('name'); + $name = _post('name'); + $query = ORM::for_table('tbl_routers')->order_by_desc('id'); + if ($name != '') { + $query->where_like('name', '%' . $name . '%'); + } + $d = Paginator::findMany($query, ['name' => $name]); + $ui->assign('d', $d); + run_hook('view_list_routers'); #HOOK + $ui->display('routers.tpl'); + break; } diff --git a/system/lan/english.json b/system/lan/english.json index d2d7717a..e775eb4f 100644 --- a/system/lan/english.json +++ b/system/lan/english.json @@ -690,5 +690,9 @@ "Mail_Deleted_Successfully": "Mail Deleted Successfully", "Message_Not_Found": "Message Not Found", "Send_Welcome_Message": "Send Welcome Message", - "WA": "WA" + "WA": "WA", + "_": "-", + "Routers_Maps": "Routers Maps", + "Routers_Geo_Location_Information": "Routers Geo Location Information", + "Coverage": "Coverage" } \ No newline at end of file diff --git a/system/updates.json b/system/updates.json index 32df040d..87db6cf1 100644 --- a/system/updates.json +++ b/system/updates.json @@ -140,5 +140,9 @@ "2024.8.5" : [ "ALTER TABLE `tbl_customers` ADD `pppoe_username` VARCHAR(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT 'For PPPOE Login' AFTER `password`;", "ALTER TABLE `tbl_customers` ADD `pppoe_ip` VARCHAR(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT 'For PPPOE Login' AFTER `pppoe_password`;" + ], + "2024.8.5.1" : [ + "ALTER TABLE `tbl_routers` ADD `coordinates` VARCHAR(50) NOT NULL DEFAULT '' AFTER `description`;", + "ALTER TABLE `tbl_routers` ADD `coverage` VARCHAR(8) NOT NULL DEFAULT '0' AFTER `coordinates`;" ] } \ No newline at end of file diff --git a/ui/ui/routers-edit.tpl b/ui/ui/routers-edit.tpl index 737d74a0..df2ffba2 100644 --- a/ui/ui/routers-edit.tpl +++ b/ui/ui/routers-edit.tpl @@ -5,70 +5,147 @@
    {Lang::T('Edit Router')}
    -
    - - -
    - -
    - - -
    +
    + + +
    + +
    + +
    -
    - -
    - -

    {Lang::T('Name of Area that router operated')}

    -
    +
    +
    -{include file="sections/footer.tpl"} +{literal} + + +{/literal} +{include file="sections/footer.tpl"} \ No newline at end of file diff --git a/ui/ui/routers-maps.tpl b/ui/ui/routers-maps.tpl new file mode 100644 index 00000000..7e5b1046 --- /dev/null +++ b/ui/ui/routers-maps.tpl @@ -0,0 +1,84 @@ +{include file="sections/header.tpl"} + + + + + +
    + +{include file="pagination.tpl"} + +{literal} + +{/literal} +{include file="sections/footer.tpl"} \ No newline at end of file diff --git a/ui/ui/routers.tpl b/ui/ui/routers.tpl index 9aad56a3..53c2dd4d 100644 --- a/ui/ui/routers.tpl +++ b/ui/ui/routers.tpl @@ -4,7 +4,12 @@
    -
    {Lang::T('Routers')}
    +
    {Lang::T('Routers')} +
    + + +
    +
    @@ -43,7 +48,13 @@ {foreach $d as $ds} - {$ds['name']} + + {if $ds['coordinates']} + + {/if} + {$ds['name']} {$ds['ip_address']} {$ds['username']} {$ds['description']} diff --git a/ui/ui/sections/header.tpl b/ui/ui/sections/header.tpl index 307df2d9..cd337197 100644 --- a/ui/ui/sections/header.tpl +++ b/ui/ui/sections/header.tpl @@ -427,10 +427,12 @@ diff --git a/version.json b/version.json index 9db2c31a..7602a143 100644 --- a/version.json +++ b/version.json @@ -1,3 +1,3 @@ { - "version": "2024.8.5" + "version": "2024.8.5.1" } \ No newline at end of file From d138e1b36fc2841e31b8981369993168a32b7075 Mon Sep 17 00:00:00 2001 From: iBNu Maksum Date: Mon, 5 Aug 2024 18:03:59 +0700 Subject: [PATCH 014/841] move I'd to first MikrotikPppoe.php --- system/devices/MikrotikPppoe.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/system/devices/MikrotikPppoe.php b/system/devices/MikrotikPppoe.php index 2c9e2c67..a71a9161 100644 --- a/system/devices/MikrotikPppoe.php +++ b/system/devices/MikrotikPppoe.php @@ -41,6 +41,7 @@ class MikrotikPppoe $this->addPpoeUser($client, $plan, $customer); }else{ $setRequest = new RouterOS\Request('/ppp/secret/set'); + $setRequest->setArgument('numbers', $cid); if (!empty($customer['pppoe_password'])) { $setRequest->setArgument('password', $customer['pppoe_password']); } else { @@ -54,7 +55,6 @@ class MikrotikPppoe if (!empty($customer['pppoe_ip'])) { $setRequest->setArgument('local-address', $customer['pppoe_ip']); } - $setRequest->setArgument('numbers', $cid); $setRequest->setArgument('profile', $plan['name_plan']); $setRequest->setArgument('comment', $customer['fullname'] . ' | ' . $customer['email'] . ' | ' . implode(', ', User::getBillNames($customer['id']))); $client->sendSync($setRequest); From bcdad02274cd7bad5cde5f93652e2ec5cf6338bb Mon Sep 17 00:00:00 2001 From: ABDALRAHMAN MOLOOD Date: Mon, 5 Aug 2024 15:47:25 +0300 Subject: [PATCH 015/841] Create arabic.json - add arabic translation --- system/lan/arabic.json | 719 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 719 insertions(+) create mode 100644 system/lan/arabic.json diff --git a/system/lan/arabic.json b/system/lan/arabic.json new file mode 100644 index 00000000..d052069a --- /dev/null +++ b/system/lan/arabic.json @@ -0,0 +1,719 @@ +{ + "Log_in": "تسجيل الدخول", + "Register": "تسجيل", + "Announcement": "إعلان", + "Registration_Info": "معلومات التسجيل", + "Voucher_not_found__please_buy_voucher_befor_register": "القسيمة غير موجودة، يرجى شراء القسيمة قبل التسجيل", + "Register_Success__You_can_login_now": "تم التسجيل بنجاح! يمكنك تسجيل الدخول الآن", + "Log_in_to_Member_Panel": "تسجيل الدخول إلى لوحة الأعضاء", + "Register_as_Member": "التسجيل كعضو", + "Enter_Admin_Area": "دخول منطقة الإدارة", + "PHPNuxBill": "PHPNuxBill", + "Username": "اسم المستخدم", + "Password": "كلمة المرور", + "Passwords_does_not_match": "كلمات المرور غير متطابقة", + "Account_already_axist": "الحساب موجود بالفعل", + "Manage": "إدارة", + "Submit": "إرسال", + "Save_Changes": "حفظ التغييرات", + "Cancel": "إلغاء", + "Edit": "تعديل", + "Delete": "حذف", + "Welcome": "مرحباً", + "Data_Created_Successfully": "تم إنشاء البيانات بنجاح", + "Data_Updated_Successfully": "تم تحديث البيانات بنجاح", + "Data_Deleted_Successfully": "تم حذف البيانات بنجاح", + "Static_Pages": "صفحات ثابتة", + "Failed_to_save_page__make_sure_i_can_write_to_folder_pages___i_chmod_664_pages___html_i_": "فشل في حفظ الصفحة، تأكد من أنني أستطيع الكتابة إلى مجلد الصفحات، chmod 664 pages/*.html", + "Saving_page_success": "تم حفظ الصفحة بنجاح", + "Sometimes_you_need_to_refresh_3_times_until_content_change": "أحيانًا تحتاج إلى التحديث ثلاث مرات حتى يتغير المحتوى", + "Dashboard": "لوحة التحكم", + "Search_Customers___": "بحث العملاء...", + "My_Account": "حسابي", + "My_Profile": "ملفي الشخصي", + "Settings": "الإعدادات", + "Edit_Profile": "تعديل الملف الشخصي", + "Change_Password": "تغيير كلمة المرور", + "Logout": "تسجيل الخروج", + "Services": "الخدمات", + "Bandwidth_Plans": "خطط عرض النطاق الترددي", + "Bandwidth_Name": "اسم عرض النطاق الترددي", + "New_Bandwidth": "عرض نطاق ترددي جديد", + "Edit_Bandwidth": "تعديل عرض النطاق الترددي", + "Add_New_Bandwidth": "إضافة عرض نطاق ترددي جديد", + "Rate_Download": "معدل التنزيل", + "Rate_Upload": "معدل الرفع", + "Name_Bandwidth_Already_Exist": "اسم عرض النطاق الترددي موجود بالفعل", + "Hotspot_Plans": "خطط هوتسبوت", + "PPPOE_Plans": "خطط PPPOE", + "Plan_Name": "اسم الخطة", + "New_Service_Plan": "خطة خدمة جديدة", + "Add_Service_Plan": "إضافة خطة خدمة", + "Edit_Service_Plan": "تعديل خطة الخدمة", + "Name_Plan_Already_Exist": "اسم الخطة موجود بالفعل", + "Plan_Type": "نوع الخطة", + "Plan_Price": "سعر الخطة", + "Limit_Type": "نوع الحد", + "Unlimited": "غير محدود", + "Limited": "محدود", + "Time_Limit": "حد زمني", + "Data_Limit": "حد البيانات", + "Both_Limit": "كلاهما", + "Plan_Validity": "صلاحية الخطة", + "Select_Bandwidth": "اختر عرض النطاق الترددي", + "Shared_Users": "المستخدمون المشتركين", + "Choose_User_Type_Sales_to_disable_access_to_Settings": "اختر نوع المستخدم المبيعات لتعطيل الوصول إلى الإعدادات", + "Current_Password": "كلمة المرور الحالية", + "New_Password": "كلمة المرور الجديدة", + "Administrator": "مدير", + "Sales": "مبيعات", + "Member": "عضو", + "Confirm_New_Password": "تأكيد كلمة المرور الجديدة", + "Confirm_Password": "تأكيد كلمة المرور", + "Full_Name": "الاسم الكامل", + "User_Type": "نوع المستخدم", + "Address": "العنوان", + "Created_On": "تم الإنشاء في", + "Expires_On": "ينتهي في", + "Phone_Number": "رقم الهاتف", + "User_deleted_Successfully": "تم حذف المستخدم بنجاح", + "Full_Administrator": "مدير كامل", + "Keep_Blank_to_do_not_change_Password": "اتركه فارغًا لعدم تغيير كلمة المرور", + "Keep_it_blank_if_you_do_not_want_to_show_currency_code": "اتركه فارغًا إذا كنت لا تريد عرض رمز العملة", + "Theme_Style": "نمط السمة", + "Theme_Color": "لون السمة", + "Default_Language": "اللغة الافتراضية", + "Network": "الشبكة", + "Routers": "الموجهات", + "IP_Pool": "مجمع IP", + "New_Router": "موجه جديد", + "Add_Router": "إضافة موجه", + "Edit_Router": "تعديل الموجه", + "Router_Name": "اسم الموجه", + "IP_Address": "عنوان IP", + "Router_Secret": "سر الموجه", + "Description": "الوصف", + "IP_Router_Already_Exist": "عنوان IP للموجه موجود بالفعل", + "Name_Pool": "اسم المجمع", + "Range_IP": "نطاق IP", + "New_Pool": "مجمع جديد", + "Add_Pool": "إضافة مجمع", + "Edit_Pool": "تعديل المجمع", + "Pool_Name_Already_Exist": "اسم المجمع موجود بالفعل", + "Refill_Account": "إعادة شحن الحساب", + "Recharge_Account": "إعادة شحن الحساب", + "Select_Account": "اختر الحساب", + "Service_Plan": "خطة الخدمة", + "Recharge": "إعادة شحن", + "Method": "طريقة", + "Account_Created_Successfully": "تم إنشاء الحساب بنجاح", + "Database_Status": "حالة قاعدة البيانات", + "Total_Database_Size": "إجمالي حجم قاعدة البيانات", + "Download_Database_Backup": "تحميل نسخة احتياطية من قاعدة البيانات", + "Table_Name": "اسم الجدول", + "Rows": "الصفوف", + "Size": "الحجم", + "Customer": "العميل", + "Add_New_Contact": "إضافة جهة اتصال جديدة", + "Edit_Contact": "تعديل جهة الاتصال", + "List_Contact": "قائمة جهات الاتصال", + "Manage_Contact": "إدارة جهات الاتصال", + "Reports": "التقارير", + "Daily_Reports": "التقارير اليومية", + "Period_Reports": "تقارير الفترة", + "All_Transactions": "جميع المعاملات", + "Total_Income": "إجمالي الدخل", + "All_Transactions_at_Date": "جميع المعاملات في التاريخ", + "Export_for_Print": "تصدير للطباعة", + "Print": "طباعة", + "Export_to_PDF": "تصدير إلى PDF", + "Click_Here_to_Print": "انقر هنا للطباعة", + "You_can_use_html_tag": "يمكنك استخدام وسم HTML", + "Date_Format": "تنسيق التاريخ", + "Income_Today": "الدخل اليوم", + "Income_This_Month": "الدخل هذا الشهر", + "Users_Active": "المستخدمون النشطون", + "Total_Users": "إجمالي المستخدمين", + "Users": "المستخدمون", + "Edit_User": "تعديل المستخدم", + "Last_Login": "آخر تسجيل دخول", + "Administrator_Users": "مستخدمو المدير", + "Manage_Administrator": "إدارة المدير", + "Add_New_Administrator": "إضافة مدير جديد", + "Localisation": "الموقع", + "Backup_Restore": "النسخ الاحتياطي / الاستعادة", + "General_Settings": "الإعدادات العامة", + "Date": "التاريخ", + "Login_Successful": "تم تسجيل الدخول بنجاح", + "Failed_Login": "فشل تسجيل الدخول", + "Settings_Saved_Successfully": "تم حفظ الإعدادات بنجاح", + "User_Updated_Successfully": "تم تحديث المستخدم بنجاح", + "User_Expired__Today": "انتهت صلاحية المستخدم، اليوم", + "Activity_Log": "سجل النشاطات", + "View_Reports": "عرض التقارير", + "View_All": "عرض الكل", + "Number_of_Vouchers": "عدد القسائم", + "Length_Code": "طول الكود", + "Code_Voucher": "كود القسيمة", + "Voucher": "قسيمة", + "Hotspot_Voucher": "قسيمة هوتسبوت", + "Status_Voucher": "حالة القسيمة", + "Add_Vouchers": "إضافة قسائم", + "Create_Vouchers_Successfully": "تم إنشاء القسائم بنجاح", + "Generate": "توليد", + "Print_side_by_side__it_will_easy_to_cut": "اطبع جنبًا إلى جنب، سيكون من السهل قصها", + "From_Date": "من التاريخ", + "To_Date": "إلى التاريخ", + "New_Service": "خدمة جديدة", + "Type": "نوع", + "Finish": "إنهاء", + "Application_Name__Company_Name": "اسم التطبيق / اسم الشركة", + "This_Name_will_be_shown_on_the_Title": "سيتم عرض هذا الاسم في العنوان", + "Next": "التالي", + "Last": "الأخير", + "Timezone": "المنطقة الزمنية", + "Decimal_Point": "الفاصلة العشرية", + "Thousands_Separator": "فاصل الآلاف", + "Currency_Code": "رمز العملة", + "Order_Voucher": "طلب قسيمة", + "Voucher_Activation": "تفعيل القسيمة", + "List_Activated_Voucher": "قائمة القسائم المفعلة", + "Enter_voucher_code_here": "أدخل رمز القسيمة هنا", + "Private_Message": "رسالة خاصة", + "Inbox": "البريد الوارد", + "Outbox": "البريد الصادر", + "Compose": "إنشاء", + "Send_to": "إرسال إلى", + "Title": "العنوان", + "Message": "الرسالة", + "Your_Account_Information": "معلومات حسابك", + "Welcome_to_the_Panel_Members_page__on_this_page_you_can_": "مرحبًا بك في صفحة أعضاء اللوحة، في هذه الصفحة يمكنك:", + "Invalid_Username_or_Password": "اسم المستخدم أو كلمة المرور غير صالحة", + "You_do_not_have_permission_to_access_this_page": "ليس لديك إذن للوصول إلى هذه الصفحة", + "Incorrect_Current_Password": "كلمة المرور الحالية غير صحيحة", + "Password_changed_successfully__Please_login_again": "تم تغيير كلمة المرور بنجاح، يرجى تسجيل الدخول مرة أخرى", + "All_field_is_required": "جميع الحقول مطلوبة", + "Voucher_Not_Valid": "القسيمة غير صالحة", + "Activation_Vouchers_Successfully": "تم تفعيل القسائم بنجاح", + "Data_Not_Found": "لم يتم العثور على البيانات", + "Search_by_Username": "البحث حسب اسم المستخدم", + "Search_by_Name": "البحث حسب الاسم", + "Search_by_Code_Voucher": "البحث حسب كود القسيمة", + "Search": "بحث", + "Select_a_customer": "اختر عميلاً", + "Select_Routers": "اختر الموجهات", + "Select_Plans": "اختر الخطط", + "Select_Pool": "اختر المجمع", + "Hrs": "ساعات", + "Mins": "دقائق", + "Days": "أيام", + "Months": "أشهر", + "Add_Language": "إضافة لغة", + "Language_Name": "اسم اللغة", + "Folder_Name": "اسم المجلد", + "Translator": "المترجم", + "Language_Name_Already_Exist": "اسم اللغة موجود بالفعل", + "Payment_Gateway": "بوابة الدفع", + "Community": "المجتمع", + "1_user_can_be_used_for_many_devices_": "هل يمكن استخدام مستخدم واحد للعديد من الأجهزة؟", + "Cannot_be_change_after_saved": "لا يمكن تغييرها بعد الحفظ", + "Explain_Coverage_of_router": "شرح تغطية الموجه", + "Name_of_Area_that_router_operated": "اسم المنطقة التي يعمل بها الموجه", + "Payment_Notification_URL__Recurring_Notification_URL__Pay_Account_Notification_URL": "عنوان URL لإشعار الدفع، عنوان URL لإشعار المتكرر، عنوان URL لإشعار دفع الحساب", + "Finish_Redirect_URL__Unfinish_Redirect_URL__Error_Redirect_URL": "عنوان URL لإعادة التوجيه بعد الانتهاء، عنوان URL لإعادة التوجيه بعد عدم الانتهاء، عنوان URL لإعادة التوجيه عند حدوث خطأ", + "Status": "الحالة", + "Plan_Not_found": "الخطة غير موجودة", + "Failed_to_create_transaction_": "فشل في إنشاء المعاملة.", + "Seller_has_not_yet_setup_Xendit_payment_gateway": "البائع لم يقم بعد بإعداد بوابة الدفع Xendit", + "Admin_has_not_yet_setup_Xendit_payment_gateway__please_tell_admin": "المدير لم يقم بعد بإعداد بوابة الدفع Xendit، يرجى إخبار المدير", + "You_already_have_unpaid_transaction__cancel_it_or_pay_it_": "لديك معاملة غير مدفوعة، قم بإلغائها أو دفعها.", + "Transaction_Not_found": "المعاملة غير موجودة", + "Cancel_it_": "هل تريد إلغاءها؟", + "expired": "منتهية الصلاحية", + "Check_for_Payment": "التحقق من الدفع", + "Transaction_still_unpaid_": "المعاملة لا تزال غير مدفوعة.", + "Paid_Date": "تاريخ الدفع", + "Transaction_has_been_paid_": "تم دفع المعاملة.", + "PAID": "مدفوع", + "CANCELED": "ملغي", + "UNPAID": "غير مدفوع", + "PAY_NOW": "ادفع الآن", + "Buy_Hotspot_Plan": "شراء خطة هوتسبوت", + "Buy_PPOE_Plan": "شراء خطة PPOE", + "Package": "الحزمة", + "Order_Internet_Package": "طلب حزمة إنترنت", + "Unknown_Command_": "أمر غير معروف.", + "Checking_payment": "التحقق من الدفع", + "Create_Transaction_Success": "تم إنشاء المعاملة بنجاح", + "You_have_unpaid_transaction": "لديك معاملة غير مدفوعة", + "TripayPayment_Channel": "قناة الدفع Tripay", + "Payment_Channel": "قناة الدفع", + "Payment_check_failed_": "فشل التحقق من الدفع.", + "Order_Package": "طلب الحزمة", + "Transactions": "المعاملات", + "Payments": "المدفوعات", + "History": "التاريخ", + "Order_History": "تاريخ الطلبات", + "Gateway": "البوابة", + "Date_Done": "تاريخ الإنجاز", + "Unpaid_Order": "طلب غير مدفوع", + "Payment_Gateway_Not_Found": "لم يتم العثور على بوابة الدفع", + "Payment_Gateway_saved_successfully": "تم حفظ بوابة الدفع بنجاح", + "ORDER": "طلب", + "Package_History": "تاريخ الحزم", + "Buy_History": "تاريخ الشراء", + "Activation_History": "تاريخ التفعيل", + "Buy_Package": "شراء حزمة", + "Email": "البريد الإلكتروني", + "Company_Footer": "تذييل الشركة", + "Will_show_below_user_pages": "سيظهر أسفل صفحات المستخدم", + "Request_OTP": "طلب رمز التحقق", + "Verification_Code": "رمز التحقق", + "SMS_Verification_Code": "رمز التحقق عبر الرسائل القصيرة", + "Please_enter_your_email_address": "يرجى إدخال عنوان بريدك الإلكتروني", + "Failed_to_create_Paypal_transaction_": "فشل في إنشاء معاملة Paypal.", + "Plugin": "الإضافة", + "Plugin_Manager": "مدير الإضافات", + "User_Notification": "إشعار المستخدم", + "Expired_Notification": "إشعار انتهاء الصلاحية", + "User_will_get_notification_when_package_expired": "سيحصل المستخدم على إشعار عند انتهاء صلاحية الحزمة", + "Expired_Notification_Message": "رسالة إشعار انتهاء الصلاحية", + "Payment_Notification": "إشعار الدفع", + "User_will_get_invoice_notification_when_buy_package_or_package_refilled": "سيحصل المستخدم على إشعار بالفاتورة عند شراء حزمة أو إعادة تعبئة الحزمة", + "Current_IP": "عنوان IP الحالي", + "Current_MAC": "عنوان MAC الحالي", + "Login_Status": "حالة تسجيل الدخول", + "Login_Request_successfully": "تم طلب تسجيل الدخول بنجاح", + "Logout_Request_successfully": "تم طلب تسجيل الخروج بنجاح", + "Disconnect_Internet_": "قطع الاتصال بالإنترنت؟", + "Not_Online__Login_now_": "غير متصل، تسجيل الدخول الآن؟", + "You_are_Online__Logout_": "أنت متصل، تسجيل الخروج؟", + "Connect_to_Internet_": "الاتصال بالإنترنت؟", + "Your_account_not_connected_to_internet": "حسابك غير متصل بالإنترنت", + "Failed_to_create_transaction__": "فشل في إنشاء المعاملة.", + "Failed_to_check_status_transaction__": "فشل في التحقق من حالة المعاملة.", + "Disable_Voucher": "تعطيل القسيمة", + "Balance": "الرصيد", + "Balance_System": "نظام الرصيد", + "Enable_System": "تمكين النظام", + "Allow_Transfer": "السماح بالنقل", + "Telegram_Notification": "إشعار تليغرام", + "SMS_OTP_Registration": "تسجيل رمز التحقق عبر الرسائل القصيرة", + "Whatsapp_Notification": "إشعار واتساب", + "Tawk_to_Chat_Widget": "أداة الدردشة Tawk.to", + "Invoice": "الفاتورة", + "Country_Code_Phone": "رمز الهاتف للبلد", + "Voucher_activation_menu_will_be_hidden": "سيتم إخفاء قائمة تفعيل القسيمة", + "Customer_can_deposit_money_to_buy_voucher": "يمكن للعميل إيداع الأموال لشراء القسيمة", + "Allow_balance_transfer_between_customers": "السماح بنقل الرصيد بين العملاء", + "Reminder_Notification": "إشعار التذكير", + "Reminder_Notification_Message": "رسالة إشعار التذكير", + "Reminder_7_days": "تذكير 7 أيام", + "Reminder_3_days": "تذكير 3 أيام", + "Reminder_1_day": "تذكير يوم واحد", + "PPPOE_Password": "كلمة مرور PPPOE", + "User_Cannot_change_this__only_admin__if_it_Empty_it_will_use_user_password": "لا يمكن للمستخدم تغيير هذا، فقط المدير. إذا كان فارغًا، سيتم استخدام كلمة مرور المستخدم", + "Invoice_Balance_Message": "رسالة رصيد الفاتورة", + "Invoice_Notification_Payment": "إشعار دفع الفاتورة", + "Balance_Notification_Payment": "إشعار دفع الرصيد", + "Balance_Plans": "خطط الرصيد", + "Buy_Balance": "شراء رصيد", + "Price": "السعر", + "Validity": "الصلاحية", + "Disable_auto_renewal_": "تعطيل التجديد التلقائي؟", + "Auto_Renewal_On": "التجديد التلقائي مفعل", + "Enable_auto_renewal_": "تمكين التجديد التلقائي؟", + "Auto_Renewal_Off": "التجديد التلقائي معطل", + "Refill_Balance": "إعادة شحن الرصيد", + "Invoice_Footer": "تذييل الفاتورة", + "Pay_With_Balance": "الدفع بالرصيد", + "Pay_this_with_Balance__your_active_package_will_be_overwrite": "ادفع هذا بالرصيد؟ سيتم الكتابة فوق الحزمة النشطة الخاصة بك", + "Success_to_buy_package": "تم شراء الحزمة بنجاح", + "Auto_Renewal": "التجديد التلقائي", + "View": "عرض", + "Back": "العودة", + "Active": "نشط", + "Transfer_Balance": "نقل الرصيد", + "Send_your_balance_": "إرسال رصيدك؟", + "Send": "إرسال", + "Cannot_send_to_yourself": "لا يمكن الإرسال إلى نفسك", + "Sending_balance_success": "تم إرسال الرصيد بنجاح", + "From": "من", + "To": "إلى", + "insufficient_balance": "رصيد غير كافٍ", + "Send_Balance": "إرسال الرصيد", + "Received_Balance": "الرصيد المستلم", + "Minimum_Balance_Transfer": "الحد الأدنى لنقل الرصيد", + "Minimum_Transfer": "الحد الأدنى للنقل", + "Company_Logo": "شعار الشركة", + "Expired_IP_Pool": "مجمع IP منتهي الصلاحية", + "Proxy": "الوكيل", + "Proxy_Server": "خادم الوكيل", + "Proxy_Server_Login": "تسجيل دخول خادم الوكيل", + "Hotspot_Plan": "خطة هوتسبوت", + "PPPOE_Plan": "خطة PPPOE", + "UNKNOWN": "غير معروف", + "Are_You_Sure_": "هل أنت متأكد؟", + "Success_to_send_package": "تم إرسال الحزمة بنجاح", + "Target_has_active_plan__different_with_current_plant_": "الهدف لديه خطة نشطة، تختلف عن الخطة الحالية.", + "Recharge_a_friend": "إعادة شحن صديق", + "Buy_for_friend": "شراء لصديق", + "Buy_this_for_friend_account_": "شراء هذا لحساب صديقك؟", + "Review_package_before_recharge": "مراجعة الحزمة قبل الشحن", + "Activate": "تفعيل", + "Deactivate": "تعطيل", + "Sync": "مزامنة", + "Failed_to_create_PaymeTrust_transaction_": "فشل في إنشاء معاملة PaymeTrust.", + "Location": "الموقع", + "Radius_Plans": "خطط Radius", + "Change_title_in_user_Plan_order": "تغيير العنوان في طلب خطة المستخدم", + "Logs": "السجلات", + "Voucher_Format": "تنسيق القسيمة", + "Resend_To_Customer": "إعادة الإرسال للعميل", + "Your_friend_do_not_have_active_package": "صديقك لا يملك حزمة نشطة", + "Service_Type": "نوع الخدمة", + "Others": "أخرى", + "PPPoE": "PPPoE", + "Hotspot": "هوتسبوت", + "Disable_Registration": "تعطيل التسجيل", + "Customer_just_Login_with_Phone_number_and_Voucher_Code__Voucher_will_be_password": "العميل يسجل الدخول فقط باستخدام رقم الهاتف وكود القسيمة، ستكون القسيمة كلمة المرور", + "Login___Activate_Voucher": "تسجيل الدخول / تفعيل القسيمة", + "After_Customer_activate_voucher_or_login__customer_will_be_redirected_to_this_url": "بعد أن يقوم العميل بتفعيل القسيمة أو تسجيل الدخول، سيتم إعادة توجيه العميل إلى هذا الرابط", + "Voucher_Prefix": "بادئة القسيمة", + "Voucher_activation_success__now_you_can_login": "تم تفعيل القسيمة بنجاح، الآن يمكنك تسجيل الدخول", + "Buy_this__your_active_package_will_be_overwritten": "شراء هذا؟ سيتم الكتابة فوق الحزمة النشطة الخاصة بك", + "Pay_this_with_Balance__your_active_package_will_be_overwritten": "ادفع هذا بالرصيد؟ سيتم الكتابة فوق الحزمة النشطة الخاصة بك", + "Buy_this__your_active_package_will_be_overwrite": "شراء هذا؟ سيتم الكتابة فوق الحزمة النشطة الخاصة بك", + "Monthly_Registered_Customers": "العملاء المسجلين شهريًا", + "Total_Monthly_Sales": "إجمالي المبيعات الشهرية", + "Active_Users": "المستخدمون النشطون", + "All_Users_Insights": "رؤى جميع المستخدمين", + "SuperAdmin": "مدير النظام", + "Radius": "Radius", + "Radius_NAS": "Radius NAS", + "Translation": "الترجمة", + "Translation_saved_Successfully": "تم حفظ الترجمة بنجاح", + "Language_Editor": "محرر اللغة", + "year": "سنة", + "month": "شهر", + "week": "أسبوع", + "day": "يوم", + "hour": "ساعة", + "minute": "دقيقة", + "second": "ثانية", + "Attributes": "السمات", + "Profile": "الملف الشخصي", + "Phone": "الهاتف", + "City": "المدينة", + "Sub_District": "الحي", + "Ward": "الحي", + "Credentials": "بيانات الاعتماد", + "Agent": "الوكيل", + "This_Token_will_act_as_SuperAdmin_Admin": "سيعمل هذا الرمز المميز كمدير النظام / المدير", + "Login": "تسجيل الدخول", + "Expired_Action": "إجراء منتهي الصلاحية", + "Expired_Address_List_Name": "اسم قائمة العناوين المنتهية الصلاحية", + "Address_List": "قائمة العناوين", + "Optional": "اختياري", + "Generated_By": "تم إنشاؤه بواسطة", + "Admin": "مدير", + "Password_should_be_minimum_6_characters": "يجب أن تكون كلمة المرور مكونة من 6 أحرف على الأقل", + "Add_User": "إضافة مستخدم", + "Send_Notification": "إرسال إشعار", + "Code": "الكود", + "Send_To_Customer": "إرسال للعميل", + "Prev": "السابق", + "Voucher_Not_Found": "القسيمة غير موجودة", + "Miscellaneous": "متفرقات", + "OTP_Required": "رمز التحقق مطلوب", + "Change": "تغيير", + "Change_Phone_Number": "تغيير رقم الهاتف", + "Current_Number": "الرقم الحالي", + "New_Number": "الرقم الجديد", + "Input_your_phone_number": "أدخل رقم هاتفك", + "OTP": "رمز التحقق", + "Enter_OTP_that_was_sent_to_your_phone": "أدخل رمز التحقق الذي تم إرساله إلى هاتفك", + "Update": "تحديث", + "OTP_is_required_when_user_want_to_change_phone_number": "رمز التحقق مطلوب عندما يريد المستخدم تغيير رقم الهاتف", + "Rate": "المعدل", + "Burst": "الانفجار", + "Editing_Bandwidth_will_not_automatically_update_the_plan__you_need_to_edit_the_plan_then_save_again": "تحرير عرض النطاق الترددي لن يحدث تحديثًا تلقائيًا للخطة، تحتاج إلى تحرير الخطة ثم الحفظ مرة أخرى", + "OTP_Method": "طريقة رمز التحقق", + "SMS": "الرسائل القصيرة", + "WhatsApp": "واتساب", + "SMS_and_WhatsApp": "الرسائل القصيرة وواتساب", + "The_method_which_OTP_will_be_sent_to_user": "الطريقة التي سيتم إرسال رمز التحقق بها إلى المستخدم", + "Report_Viewer": "عارض التقارير", + "Super_Administrator": "مدير النظام الأعلى", + "Send_To": "إرسال إلى", + "Resend": "إعادة الإرسال", + "Alert": "تنبيه", + "success": "نجاح", + "Click_Here": "انقر هنا", + "danger": "خطر", + "Logout_Successful": "تم تسجيل الخروج بنجاح", + "warning": "تحذير", + "Users_Announcement": "إعلان للمستخدمين", + "Customer_Announcement": "إعلان للعملاء", + "1_Period___1_Month__Expires_the_20th_of_each_month": "1 فترة = 1 شهر، تنتهي في 20 من كل شهر", + "Period": "الفترة", + "Add": "إضافة", + "Select_Payment_Gateway": "اختر بوابة الدفع", + "Available_Payment_Gateway": "بوابة الدفع المتاحة", + "Pay_Now": "ادفع الآن", + "Please_select_Payment_Gateway": "يرجى اختيار بوابة الدفع", + "Payment_Gateway_Deleted": "تم حذف بوابة الدفع", + "Payment_Gateway_not_set__please_set_it_in_Settings": "بوابة الدفع غير محددة، يرجى إعدادها في الإعدادات", + "Failed_to_create_Transaction__": "فشل في إنشاء المعاملة.", + "Show_To_Customer": "عرض للعميل", + "Using": "باستخدام", + "Default": "افتراضي", + "Customer_Balance": "رصيد العميل", + "Vouchers": "القسائم", + "Refill_Customer": "إعادة شحن العميل", + "Recharge_Customer": "إعادة شحن العميل", + "Plans": "الخطط", + "PPPOE": "PPPOE", + "Bandwidth": "عرض النطاق الترددي", + "Customers": "العملاء", + "Actives": "النشطون", + "Name": "الاسم", + "Confirm": "تأكيد", + "Plan": "الخطة", + "Total": "الإجمالي", + "Current_Cycle": "الدورة الحالية", + "Additional_Cost": "التكلفة الإضافية", + "Remaining": "المتبقي", + "Not_Found": "غير موجود", + "Cash": "نقدًا", + "Payment_not_found": "لم يتم العثور على الدفع", + "If_your_friend_have_Additional_Cost__you_will_pay_for_that_too": "إذا كان لدى صديقك تكلفة إضافية، ستدفعها أيضًا", + "Cache_cleared_successfully_": "تم مسح الذاكرة المؤقتة بنجاح!", + "Paid": "مدفوع", + "Send_Message": "إرسال رسالة", + "Send_Personal_Message": "إرسال رسالة شخصية", + "Send_Via": "إرسال عبر", + "Compose_your_message___": "أنشئ رسالتك...", + "Use_placeholders_": "استخدم العناصر النائبة:", + "Customer_Name": "اسم العميل", + "Customer_Username": "اسم المستخدم للعميل", + "Customer_Phone": "هاتف العميل", + "Your_Company_Name": "اسم شركتك", + "Message_Sent_Successfully": "تم إرسال الرسالة بنجاح", + "Send_Bulk_Message": "إرسال رسالة مجمعة", + "Group": "المجموعة", + "All_Customers": "جميع العملاء", + "New_Customers": "عملاء جدد", + "Expired_Customers": "عملاء منتهية صلاحيتهم", + "Active_Customers": "العملاء النشطون", + "Map": "الخريطة", + "Customer_Location": "موقع العميل", + "Account_Type": "نوع الحساب", + "Coordinates": "الإحداثيات", + "Latitude_and_Longitude_coordinates_for_map_must_be_separate_with_comma____": "يجب أن تكون إحداثيات خطوط العرض والطول للخريطة مفصولة بفاصلة", + "Customer_Geo_Location_Information": "معلومات الموقع الجغرافي للعميل", + "List": "القائمة", + "Lists": "القوائم", + "Single_Customer": "عميل واحد", + "Bulk_Customers": "عملاء مجمعين", + "Message_per_time": "رسالة لكل مرة", + "5_Messages": "5 رسائل", + "10_Messages": "10 رسائل", + "15_Messages": "15 رسالة", + "20_Messages": "20 رسالة", + "30_Messages": "30 رسالة", + "40_Messages": "40 رسالة", + "50_Messages": "50 رسالة", + "60_Messages": "60 رسالة", + "Use_20_and_above_if_you_are_sending_to_all_customers_to_avoid_server_time_out": "استخدم 20 وما فوق إذا كنت ترسل لجميع العملاء لتجنب انتهاء مهلة الخادم", + "Delay": "التأخير", + "No_Delay": "بدون تأخير", + "5_Seconds": "5 ثوانٍ", + "10_Seconds": "10 ثوانٍ", + "15_Seconds": "15 ثانية", + "20_Seconds": "20 ثانية", + "Use_at_least_5_secs_if_you_are_sending_to_all_customers_to_avoid_being_banned_by_your_message_provider": "استخدم 5 ثوانٍ على الأقل إذا كنت ترسل لجميع العملاء لتجنب الحظر من مزود الرسائل الخاص بك", + "Testing__if_checked_no_real_message_is_sent_": "اختبار [إذا تم التحقق منه، لن يتم إرسال رسالة حقيقية]", + "All_fields_are_required": "جميع الحقول مطلوبة", + "Personal": "شخصي", + "Email_Notification": "إشعار البريد الإلكتروني", + "Router_Name___Location": "اسم الموجه / الموقع", + "Plan_Category": "فئة الخطة", + "ID": "المعرف", + "Internet_Plan": "خطة الإنترنت", + "Privacy_Policy": "سياسة الخصوصية", + "Terms_and_Conditions": "الشروط والأحكام", + "Contact": "الاتصال", + "will_be_replaced_with_Customer_Name": "سيتم استبداله باسم العميل", + "will_be_replaced_with_Customer_username": "سيتم استبداله باسم المستخدم للعميل", + "will_be_replaced_with_Package_name": "سيتم استبداله باسم الحزمة", + "will_be_replaced_with_Package_price": "سيتم استبداله بسعر الحزمة", + "additional_bills_for_customers": "فواتير إضافية للعملاء", + "will_be_replaced_with_Expiration_date": "سيتم استبداله بتاريخ انتهاء الصلاحية", + "Your_Company_Name_at_Settings": "اسم شركتك في الإعدادات", + "Your_Company_Address_at_Settings": "عنوان شركتك في الإعدادات", + "Your_Company_Phone_at_Settings": "هاتف شركتك في الإعدادات", + "Invoice_number": "رقم الفاتورة", + "Date_invoice_created": "تاريخ إنشاء الفاتورة", + "Payment_gateway_user_paid_from": "بوابة الدفع التي دفع منها المستخدم", + "Payment_channel_user_paid_from": "قناة الدفع التي دفع منها المستخدم", + "is_Hotspot_or_PPPOE": "هل هو هوتسبوت أو PPPOE", + "Internet_Package": "حزمة الإنترنت", + "Internet_Package_Prices": "أسعار حزمة الإنترنت", + "Receiver_name": "اسم المستلم", + "Username_internet": "اسم المستخدم للإنترنت", + "User_password": "كلمة مرور المستخدم", + "Expired_datetime": "تاريخ ووقت انتهاء الصلاحية", + "For_Notes_by_admin": "للملاحظات من قبل المدير", + "Transaction_datetime": "تاريخ ووقت المعاملة", + "Balance_Before": "الرصيد قبل", + "Balance_After": "الرصيد بعد", + "how_much_balance_have_been_send": "كم من الرصيد تم إرساله", + "Current_Balance": "الرصيد الحالي", + "Sender_name": "اسم المرسل", + "how_much_balance_have_been_received": "كم من الرصيد تم استلامه", + "Extend_Postpaid_Expiration": "تمديد انتهاء الدفع المسبق", + "Allow_Extend": "السماح بالتمديد", + "Extend_Days": "تمديد الأيام", + "Confirmation_Message": "رسالة التأكيد", + "You_are_already_logged_in": "أنت مسجل الدخول بالفعل", + "Extend": "تمديد", + "Created___Expired": "تم الإنشاء / منتهي الصلاحية", + "Bank_Transfer": "تحويل بنكي", + "Recharge_Using": "إعادة الشحن باستخدام", + "ago": "منذ", + "Disabled": "معطل", + "Banned": "محظور", + "Customer_cannot_login_again": "لا يمكن للعميل تسجيل الدخول مرة أخرى", + "Customer_can_login_but_cannot_buy_internet_plan__Admin_cannot_recharge_customer": "يمكن للعميل تسجيل الدخول ولكن لا يمكنه شراء خطة الإنترنت، لا يمكن للمدير إعادة شحن العميل", + "Don_t_forget_to_deactivate_all_active_plan_too": "لا تنسى تعطيل جميع الخطط النشطة أيضًا", + "Ascending": "تصاعدي", + "Descending": "تنازلي", + "Created_Date": "تاريخ الإنشاء", + "Inactive": "غير نشط", + "Suspended": "معلق", + "Query": "استعلام", + "Notes": "ملاحظات", + "This_account_status": "حالة هذا الحساب", + "Maintenance_Mode": "وضع الصيانة", + "Maintenance_Mode_Settings": "إعدادات وضع الصيانة", + "Status_": "الحالة:", + "End_Date_": "تاريخ الانتهاء:", + "Save": "حفظ", + "Site_is_temporarily_unavailable_": "الموقع غير متاح مؤقتًا.", + "Scheduled_maintenance_is_currently_in_progress__Please_check_back_soon_": "الصيانة المجدولة جارية حاليًا. يرجى التحقق مرة أخرى قريبًا.", + "We_apologize_for_any_inconvenience_": "نعتذر عن أي إزعاج.", + "The": "الـ", + "Team": "الفريق", + "Extend_Package_Expiry": "تمديد انتهاء الحزمة", + "No": "لا", + "Yes": "نعم", + "If_user_buy_same_internet_plan__expiry_date_will_extend": "إذا اشترى المستخدم نفس خطة الإنترنت، سيتم تمديد تاريخ انتهاء الصلاحية", + "Tax_System": "نظام الضرائب", + "Enable_Tax_System": "تمكين نظام الضرائب", + "Tax_will_be_calculated_in_Internet_Plan_Price": "سيتم حساب الضريبة في سعر خطة الإنترنت", + "Tax_Rate": "معدل الضريبة", + "0_5_": "0.5%", + "1_": "1%", + "1_5_": "1.5%", + "2_": "2%", + "5_": "5%", + "10_": "10%", + "Custom": "مخصص", + "Tax_Rates_in_percentage": "معدلات الضريبة بالنسبة المئوية", + "Custom_Tax_Rate": "معدل الضريبة المخصص", + "Enter_Custom_Tax_Rate": "أدخل معدل الضريبة المخصص", + "Enter_the_custom_tax_rate__e_g___3_75_for_3_75__": "أدخل معدل الضريبة المخصص (مثال: 3.75 لـ 3.75%)", + "Additional_Information": "معلومات إضافية", + "City_of_Resident": "مدينة الإقامة", + "District": "المنطقة", + "State": "الولاية", + "State_of_Resident": "ولاية الإقامة", + "Zip": "الرمز البريدي", + "Zip_Code": "الرمز البريدي", + "Local_IP": "IP المحلي", + "Device": "الجهاز", + "Expired_Internet_Plan": "خطة الإنترنت المنتهية الصلاحية", + "When_Expired__customer_will_be_move_to_selected_internet_plan": "عند انتهاء الصلاحية، سيتم نقل العميل إلى خطة الإنترنت المحددة", + "Plugin_Installer": "مثبت الإضافة", + "Expired_Date": "تاريخ الانتهاء", + "Expired": "منتهية الصلاحية", + "Time": "الوقت", + "Data": "البيانات", + "Category": "الفئة", + "later": "لاحقًا", + "Package_Details": "تفاصيل الحزمة", + "Summary": "الملخص", + "Devices_Not_Found": "لم يتم العثور على الأجهزة", + "Income_reset_date": "تاريخ إعادة ضبط الدخل", + "Devices": "الأجهزة", + "Documentation": "التوثيق", + "Hotspot_Auth_Method": "طريقة المصادقة لهوتسبوت", + "Api": "API", + "Http_Chap": "Http-Chap", + "Hotspot_Authentication_Method__Make_sure_you_have_changed_your_hotspot_login_page_": "طريقة المصادقة لهوتسبوت. تأكد من تغيير صفحة تسجيل الدخول لهوتسبوت.", + "Business": "الأعمال", + "Source": "المصدر", + "Destination": "الوجهة", + "Activate_Voucher": "تفعيل القسيمة", + "Voucher_invalid": "القسيمة غير صالحة", + "Account_Not_Found": "الحساب غير موجود", + "Internet_Voucher_Expired": "القسيمة الإنترنت منتهية الصلاحية", + "Additional_Billing": "الفواتير الإضافية", + "Used_Date": "تاريخ الاستخدام", + "Filter": "التصفية", + "Start_time": "وقت البدء", + "End_Time": "وقت الانتهاء", + "Internet_Plans": "خطط الإنترنت", + "Methods": "الطرق", + "Hap_Lite": "Hap Lite", + "balance": "الرصيد", + "radius": "Radius", + "Start_Date": "تاريخ البدء", + "End_Date": "تاريخ الانتهاء", + "New_Version_Notification": "إشعار الإصدار الجديد", + "Enabled": "مفعل", + "This_is_to_notify_you_when_new_updates_is_available": "هذا لإخطارك عندما تكون هناك تحديثات جديدة متاحة", + "Number": "الرقم", + "NAS": "NAS", + "MAC_Address": "عنوان MAC", + "Uptime": "وقت التشغيل", + "Upload": "الرفع", + "Download": "التنزيل", + "CPU_Load": "حمل المعالج", + "Temperature": "درجة الحرارة", + "Voltage": "الجهد الكهربائي", + "Wireless_Status": "حالة اللاسلكي", + "Interface_Status": "حالة الواجهة", + "Hotspot_Online_Users": "مستخدمو الهوتسبوت المتصلون", + "PPPoE_Online_Users": "مستخدمو PPPoE المتصلون", + "Traffic_Monitor": "مراقبة الحركة", + "Interface_Name": "اسم الواجهة", + "Tx__bytes_Out_": "Tx (البيانات المرسلة)", + "Rx__bytes_In_": "Rx (البيانات المستلمة)", + "Total_Usage": "إجمالي الاستخدام", + "Server": "الخادم", + "Mac_Address": "عنوان MAC", + "Session_Time_Left": "الوقت المتبقي للجلسة", + "Upload__RX_": "الرفع (RX)", + "Download__TX_": "التنزيل (TX)", + "Service": "الخدمة", + "Caller_ID": "معرف المتصل", + "Interface": "الواجهة", + "Last_Ip": "آخر IP", + "Last_Activity": "آخر نشاط", + "Signal_Strength": "قوة الإشارة", + "Tx___Rx_CCQ": "Tx / Rx CCQ", + "Rx_Rate": "معدل الاستلام", + "Tx_Rate": "معدل الإرسال", + "TX": "الإرسال", + "RX": "الاستلام", + "Date_Time": "التاريخ / الوقت", + "Topic": "الموضوع", + "Info": "المعلومات", + "Success": "نجاح", + "Error": "خطأ", + "Warning": "تحذير", + "Force_Logout_": "تسجيل الخروج القسري:", + "Disconnect": "قطع الاتصال" +} From 810c5ae82780e883a9e8e46c49eef55d433c02d2 Mon Sep 17 00:00:00 2001 From: ABDALRAHMAN MOLOOD Date: Mon, 5 Aug 2024 15:52:14 +0300 Subject: [PATCH 016/841] Update init.php - add Boolean function isMysqlRadius() to check if the system is using Radius mysql or not. --- init.php | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/init.php b/init.php index e5e02676..e636d04d 100644 --- a/init.php +++ b/init.php @@ -348,3 +348,13 @@ function displayMaintenanceMessage(): void $ui->display('maintenance.tpl'); die(); } + +function isMysqlRadius() +{ + try { + $record = ORM::forTable('radacct', 'radius')->find_one(); + return $record !== false; + } catch (Exception $e) { + return false; + } +} From 271dd2934a0f7b6e56185bde7c2d19cf445a94b5 Mon Sep 17 00:00:00 2001 From: Ibnu Maksum Date: Tue, 6 Aug 2024 09:14:36 +0700 Subject: [PATCH 017/841] getIDby customer --- system/devices/MikrotikPppoe.php | 53 ++++++++++++-------------------- 1 file changed, 19 insertions(+), 34 deletions(-) diff --git a/system/devices/MikrotikPppoe.php b/system/devices/MikrotikPppoe.php index a71a9161..486b85ce 100644 --- a/system/devices/MikrotikPppoe.php +++ b/system/devices/MikrotikPppoe.php @@ -32,10 +32,7 @@ class MikrotikPppoe global $isChangePlan; $mikrotik = $this->info($plan['routers']); $client = $this->getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']); - //check if customer exists - $printRequest = new RouterOS\Request('/ppp/secret/print'); - $printRequest->setQuery(RouterOS\Query::where('name', $customer['username'])); - $cid = $client->sendSync($printRequest)->getProperty('.id'); + $cid = self::getIdByCustomer($customer, $client); if (empty($cid)) { //customer not exists, add it $this->addPpoeUser($client, $plan, $customer); @@ -65,6 +62,7 @@ class MikrotikPppoe } } + function remove_customer($customer, $plan) { $mikrotik = $this->info($plan['routers']); @@ -130,6 +128,23 @@ class MikrotikPppoe ); } + /** + * Function to ID by username from Mikrotik + */ + function getIdByCustomer($customer, $client){ + $printRequest = new RouterOS\Request('/ppp/secret/print'); + $printRequest->setQuery(RouterOS\Query::where('name', $customer['username'])); + $id = $client->sendSync($printRequest)->getProperty('.id'); + if(empty($id)){ + if (!empty($customer['pppoe_username'])) { + $printRequest = new RouterOS\Request('/ppp/secret/print'); + $printRequest->setQuery(RouterOS\Query::where('name', $customer['pppoe_username'])); + $id = $client->sendSync($printRequest)->getProperty('.id'); + } + } + return $id; + } + function update_plan($old_name, $new_plan) { $mikrotik = $this->info($new_plan['routers']); @@ -312,36 +327,6 @@ class MikrotikPppoe $client->sendSync($setRequest); } - function setPpoeUser($client, $user, $pass) - { - $printRequest = new RouterOS\Request('/ppp/secret/print'); - $printRequest->setArgument('.proplist', '.id'); - $printRequest->setQuery(RouterOS\Query::where('name', $user)); - $id = $client->sendSync($printRequest)->getProperty('.id'); - - $setRequest = new RouterOS\Request('/ppp/secret/set'); - $setRequest->setArgument('numbers', $id); - $setRequest->setArgument('password', $pass); - $client->sendSync($setRequest); - } - - function setPpoeUserPlan($client, $user, $plan) - { - global $_app_stage; - if ($_app_stage == 'demo') { - return null; - } - $printRequest = new RouterOS\Request('/ppp/secret/print'); - $printRequest->setArgument('.proplist', '.id'); - $printRequest->setQuery(RouterOS\Query::where('name', $user)); - $id = $client->sendSync($printRequest)->getProperty('.id'); - - $setRequest = new RouterOS\Request('/ppp/secret/set'); - $setRequest->setArgument('numbers', $id); - $setRequest->setArgument('profile', $plan); - $client->sendSync($setRequest); - } - function removePpoeActive($client, $username) { global $_app_stage; From a09bfc01bfc46529c530ee22a8a85f40b494fe0c Mon Sep 17 00:00:00 2001 From: Ibnu Maksum Date: Tue, 6 Aug 2024 09:21:19 +0700 Subject: [PATCH 018/841] remove customer check pppoe_username --- system/devices/MikrotikPppoe.php | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/system/devices/MikrotikPppoe.php b/system/devices/MikrotikPppoe.php index 486b85ce..df55ee8e 100644 --- a/system/devices/MikrotikPppoe.php +++ b/system/devices/MikrotikPppoe.php @@ -51,6 +51,8 @@ class MikrotikPppoe } if (!empty($customer['pppoe_ip'])) { $setRequest->setArgument('local-address', $customer['pppoe_ip']); + }else{ + $setRequest->setArgument('local-address', null); } $setRequest->setArgument('profile', $plan['name_plan']); $setRequest->setArgument('comment', $customer['fullname'] . ' | ' . $customer['email'] . ' | ' . implode(', ', User::getBillNames($customer['id']))); @@ -72,8 +74,14 @@ class MikrotikPppoe $this->add_customer($customer, $p); } else { $this->removePpoeUser($client, $customer['username']); + if (!empty($customer['pppoe_username'])) { + $this->removePpoeUser($client, $customer['pppoe_username']); + } } $this->removePpoeActive($client, $customer['username']); + if (!empty($customer['pppoe_username'])) { + $this->removePpoeActive($client, $customer['pppoe_username']); + } } // customer change username From 096d3ea56d9ee006e05ec7a7b6741458956002db Mon Sep 17 00:00:00 2001 From: Ibnu Maksum Date: Tue, 6 Aug 2024 09:14:36 +0700 Subject: [PATCH 019/841] getIDby customer --- system/devices/MikrotikPppoe.php | 53 ++++++++++++-------------------- 1 file changed, 19 insertions(+), 34 deletions(-) diff --git a/system/devices/MikrotikPppoe.php b/system/devices/MikrotikPppoe.php index a71a9161..486b85ce 100644 --- a/system/devices/MikrotikPppoe.php +++ b/system/devices/MikrotikPppoe.php @@ -32,10 +32,7 @@ class MikrotikPppoe global $isChangePlan; $mikrotik = $this->info($plan['routers']); $client = $this->getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']); - //check if customer exists - $printRequest = new RouterOS\Request('/ppp/secret/print'); - $printRequest->setQuery(RouterOS\Query::where('name', $customer['username'])); - $cid = $client->sendSync($printRequest)->getProperty('.id'); + $cid = self::getIdByCustomer($customer, $client); if (empty($cid)) { //customer not exists, add it $this->addPpoeUser($client, $plan, $customer); @@ -65,6 +62,7 @@ class MikrotikPppoe } } + function remove_customer($customer, $plan) { $mikrotik = $this->info($plan['routers']); @@ -130,6 +128,23 @@ class MikrotikPppoe ); } + /** + * Function to ID by username from Mikrotik + */ + function getIdByCustomer($customer, $client){ + $printRequest = new RouterOS\Request('/ppp/secret/print'); + $printRequest->setQuery(RouterOS\Query::where('name', $customer['username'])); + $id = $client->sendSync($printRequest)->getProperty('.id'); + if(empty($id)){ + if (!empty($customer['pppoe_username'])) { + $printRequest = new RouterOS\Request('/ppp/secret/print'); + $printRequest->setQuery(RouterOS\Query::where('name', $customer['pppoe_username'])); + $id = $client->sendSync($printRequest)->getProperty('.id'); + } + } + return $id; + } + function update_plan($old_name, $new_plan) { $mikrotik = $this->info($new_plan['routers']); @@ -312,36 +327,6 @@ class MikrotikPppoe $client->sendSync($setRequest); } - function setPpoeUser($client, $user, $pass) - { - $printRequest = new RouterOS\Request('/ppp/secret/print'); - $printRequest->setArgument('.proplist', '.id'); - $printRequest->setQuery(RouterOS\Query::where('name', $user)); - $id = $client->sendSync($printRequest)->getProperty('.id'); - - $setRequest = new RouterOS\Request('/ppp/secret/set'); - $setRequest->setArgument('numbers', $id); - $setRequest->setArgument('password', $pass); - $client->sendSync($setRequest); - } - - function setPpoeUserPlan($client, $user, $plan) - { - global $_app_stage; - if ($_app_stage == 'demo') { - return null; - } - $printRequest = new RouterOS\Request('/ppp/secret/print'); - $printRequest->setArgument('.proplist', '.id'); - $printRequest->setQuery(RouterOS\Query::where('name', $user)); - $id = $client->sendSync($printRequest)->getProperty('.id'); - - $setRequest = new RouterOS\Request('/ppp/secret/set'); - $setRequest->setArgument('numbers', $id); - $setRequest->setArgument('profile', $plan); - $client->sendSync($setRequest); - } - function removePpoeActive($client, $username) { global $_app_stage; From 7a95d793154fc62a2fdff4e92e565213ef577dd0 Mon Sep 17 00:00:00 2001 From: Ibnu Maksum Date: Tue, 6 Aug 2024 09:21:19 +0700 Subject: [PATCH 020/841] remove customer check pppoe_username --- system/devices/MikrotikPppoe.php | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/system/devices/MikrotikPppoe.php b/system/devices/MikrotikPppoe.php index 486b85ce..df55ee8e 100644 --- a/system/devices/MikrotikPppoe.php +++ b/system/devices/MikrotikPppoe.php @@ -51,6 +51,8 @@ class MikrotikPppoe } if (!empty($customer['pppoe_ip'])) { $setRequest->setArgument('local-address', $customer['pppoe_ip']); + }else{ + $setRequest->setArgument('local-address', null); } $setRequest->setArgument('profile', $plan['name_plan']); $setRequest->setArgument('comment', $customer['fullname'] . ' | ' . $customer['email'] . ' | ' . implode(', ', User::getBillNames($customer['id']))); @@ -72,8 +74,14 @@ class MikrotikPppoe $this->add_customer($customer, $p); } else { $this->removePpoeUser($client, $customer['username']); + if (!empty($customer['pppoe_username'])) { + $this->removePpoeUser($client, $customer['pppoe_username']); + } } $this->removePpoeActive($client, $customer['username']); + if (!empty($customer['pppoe_username'])) { + $this->removePpoeActive($client, $customer['pppoe_username']); + } } // customer change username From 5d6a06b6fa456c6422109baec9f91ff0f9673461 Mon Sep 17 00:00:00 2001 From: ABDALRAHMAN MOLOOD Date: Mon, 5 Aug 2024 15:52:14 +0300 Subject: [PATCH 021/841] Update init.php - add Boolean function isMysqlRadius() to check if the system is using Radius mysql or not. --- init.php | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/init.php b/init.php index e5e02676..e636d04d 100644 --- a/init.php +++ b/init.php @@ -348,3 +348,13 @@ function displayMaintenanceMessage(): void $ui->display('maintenance.tpl'); die(); } + +function isMysqlRadius() +{ + try { + $record = ORM::forTable('radacct', 'radius')->find_one(); + return $record !== false; + } catch (Exception $e) { + return false; + } +} From 95899b4ebad6af489321c48ac6b46c1ce63028ae Mon Sep 17 00:00:00 2001 From: Ibnu Maksum Date: Tue, 6 Aug 2024 10:00:35 +0700 Subject: [PATCH 022/841] check if admin change username pppoe or not --- system/controllers/customers.php | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/system/controllers/customers.php b/system/controllers/customers.php index 5aa83e80..d1c76a31 100644 --- a/system/controllers/customers.php +++ b/system/controllers/customers.php @@ -524,8 +524,10 @@ switch ($action) { ->find_many(); $oldusername = $c['username']; - $oldPppoePassword = $c['password']; - $oldPassPassword = $c['pppoe_password']; + $oldPppoeUsername = $c['pppoe_username']; + $oldPppoePassword = $c['pppoe_password']; + $oldPppoeIp = $c['pppoe_ip']; + $oldPassPassword = $c['password']; $userDiff = false; $pppoeDiff = false; $passDiff = false; @@ -536,7 +538,7 @@ switch ($action) { } $userDiff = true; } - if ($oldPppoePassword != $pppoe_password) { + if ($oldPppoeUsername != $pppoe_username) { $pppoeDiff = true; } if ($password != '' && $oldPassPassword != $password) { @@ -616,8 +618,6 @@ switch ($action) { if ($userDiff || $pppoeDiff || $passDiff) { $turs = ORM::for_table('tbl_user_recharges')->where('customer_id', $c['id'])->findMany(); foreach ($turs as $tur) { - $tur->username = $username; - $tur->save(); $p = ORM::for_table('tbl_plans')->find_one($tur['plan_id']); $dvc = Package::getDevice($p); if ($_app_stage != 'demo') { @@ -628,12 +628,22 @@ switch ($action) { if ($userDiff) { (new $p['device'])->change_username($p, $oldusername, $username); } + if ($pppoeDiff && $tur['type'] == 'PPPOE') { + if(empty($oldPppoeUsername)){ + // admin just add pppoe username + (new $p['device'])->change_username($p, $username, $pppoe_username); + }else{ + (new $p['device'])->change_username($p, $oldPppoeUsername, $pppoe_username); + } + } (new $p['device'])->add_customer($c, $p); } else { new Exception(Lang::T("Devices Not Found")); } } } + $tur->username = $username; + $tur->save(); } } r2(U . 'customers/view/' . $id, 's', 'User Updated Successfully'); From 2a7563f43dafec455ccdd2f79473d64451a4e474 Mon Sep 17 00:00:00 2001 From: Ibnu Maksum Date: Tue, 6 Aug 2024 10:03:49 +0700 Subject: [PATCH 023/841] if expired plan deleted, go delete customer when expired --- system/devices/MikrotikHotspot.php | 7 ++++--- system/devices/MikrotikPppoe.php | 12 +++++++----- system/devices/Radius.php | 9 +++++---- 3 files changed, 16 insertions(+), 12 deletions(-) diff --git a/system/devices/MikrotikHotspot.php b/system/devices/MikrotikHotspot.php index 726d6b00..c10461bf 100644 --- a/system/devices/MikrotikHotspot.php +++ b/system/devices/MikrotikHotspot.php @@ -44,10 +44,11 @@ class MikrotikHotspot $client = $this->getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']); if (!empty($plan['plan_expired'])) { $p = ORM::for_table("tbl_plans")->find_one($plan['plan_expired']); - $this->add_customer($customer, $p); - } else { - $this->removeHotspotUser($client, $customer['username']); + if($p){ + $this->add_customer($customer, $p); + } } + $this->removeHotspotUser($client, $customer['username']); $this->removeHotspotActiveUser($client, $customer['username']); } diff --git a/system/devices/MikrotikPppoe.php b/system/devices/MikrotikPppoe.php index df55ee8e..79a46f0f 100644 --- a/system/devices/MikrotikPppoe.php +++ b/system/devices/MikrotikPppoe.php @@ -71,13 +71,15 @@ class MikrotikPppoe $client = $this->getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']); if (!empty($plan['plan_expired'])) { $p = ORM::for_table("tbl_plans")->find_one($plan['plan_expired']); - $this->add_customer($customer, $p); - } else { - $this->removePpoeUser($client, $customer['username']); - if (!empty($customer['pppoe_username'])) { - $this->removePpoeUser($client, $customer['pppoe_username']); + if($p){ + $this->add_customer($customer, $p); + return; } } + $this->removePpoeUser($client, $customer['username']); + if (!empty($customer['pppoe_username'])) { + $this->removePpoeUser($client, $customer['pppoe_username']); + } $this->removePpoeActive($client, $customer['username']); if (!empty($customer['pppoe_username'])) { $this->removePpoeActive($client, $customer['pppoe_username']); diff --git a/system/devices/Radius.php b/system/devices/Radius.php index 46cc2f31..0fa404a2 100644 --- a/system/devices/Radius.php +++ b/system/devices/Radius.php @@ -85,10 +85,11 @@ class Radius { if (!empty($plan['plan_expired'])) { $p = ORM::for_table("tbl_plans")->find_one($plan['plan_expired']); - $this->customerAddPlan($customer, $p); - } else { - $this->customerDeactivate($customer['username'], true); + if ($p) { + $this->customerAddPlan($customer, $p); + } } + $this->customerDeactivate($customer['username'], true); } public function change_username($from, $to) @@ -469,7 +470,7 @@ class Radius $unitdown = ($bw['rate_down_unit'] == 'Kbps') ? 'K' : 'M'; $unitup = ($bw['rate_up_unit'] == 'Kbps') ? 'K' : 'M'; - // TODO Burst mode [ 2M/1M 256K/128K 128K/64K 1s 1 64K/32K] + // TODO Burst mode [ 2M/1M 256K/128K 128K/64K 1s 1 64K/32K] if (!empty(trim($bw['burst']))) { // burst format: 2M/1M 256K/128K 128K/64K 1s 1 64K/32K From a3c255e77a468b95b3eb6e974a95f6ed96425563 Mon Sep 17 00:00:00 2001 From: Ibnu Maksum Date: Tue, 6 Aug 2024 10:17:11 +0700 Subject: [PATCH 024/841] what if admin want to revert using customer username? now it can revert username --- system/controllers/customers.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/system/controllers/customers.php b/system/controllers/customers.php index d1c76a31..d5828183 100644 --- a/system/controllers/customers.php +++ b/system/controllers/customers.php @@ -629,10 +629,14 @@ switch ($action) { (new $p['device'])->change_username($p, $oldusername, $username); } if ($pppoeDiff && $tur['type'] == 'PPPOE') { - if(empty($oldPppoeUsername)){ + if(empty($oldPppoeUsername) && !empty($pppoe_username)){ // admin just add pppoe username (new $p['device'])->change_username($p, $username, $pppoe_username); + }else if(empty($pppoe_username) && !empty($oldPppoeUsername)){ + // admin want to use customer username + (new $p['device'])->change_username($p, $oldPppoeUsername, $username); }else{ + // regular change pppoe username (new $p['device'])->change_username($p, $oldPppoeUsername, $pppoe_username); } } From 8ab1939dd992a2c4d24f33e7d947c8d4d6052bfd Mon Sep 17 00:00:00 2001 From: Ibnu Maksum Date: Tue, 6 Aug 2024 10:17:31 +0700 Subject: [PATCH 025/841] check if pppoe customer already used by another customer --- system/controllers/customers.php | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/system/controllers/customers.php b/system/controllers/customers.php index d5828183..b6222faa 100644 --- a/system/controllers/customers.php +++ b/system/controllers/customers.php @@ -540,6 +540,12 @@ switch ($action) { } if ($oldPppoeUsername != $pppoe_username) { $pppoeDiff = true; + if(ORM::for_table('tbl_customers')->where('pppoe_username', $pppoe_username)->find_one()){ + $msg.= Lang::T('PPPoE Username already used by another customer') . '
    '; + } + if(ORM::for_table('tbl_customers')->where('username', $pppoe_username)->find_one()){ + $msg.= Lang::T('PPPoE Username already used by another customer') . '
    '; + } } if ($password != '' && $oldPassPassword != $password) { $passDiff = true; From cb0e77523da7bcae2affc6aec2a89c52e3454b40 Mon Sep 17 00:00:00 2001 From: Ibnu Maksum Date: Tue, 6 Aug 2024 10:19:12 +0700 Subject: [PATCH 026/841] check if customer username already used by pppoe_username --- system/controllers/customers.php | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/system/controllers/customers.php b/system/controllers/customers.php index b6222faa..baee9405 100644 --- a/system/controllers/customers.php +++ b/system/controllers/customers.php @@ -532,20 +532,22 @@ switch ($action) { $pppoeDiff = false; $passDiff = false; if ($oldusername != $username) { - $cx = ORM::for_table('tbl_customers')->where('username', $username)->find_one(); - if ($cx) { - $msg .= Lang::T('Account already exist') . '
    '; + if (ORM::for_table('tbl_customers')->where('username', $username)->find_one()) { + $msg .= Lang::T('Username already used by another customer') . '
    '; + } + if(ORM::for_table('tbl_customers')->where('pppoe_username', $username)->find_one()){ + $msg.= Lang::T('Username already used by another customer') . '
    '; } $userDiff = true; } if ($oldPppoeUsername != $pppoe_username) { - $pppoeDiff = true; if(ORM::for_table('tbl_customers')->where('pppoe_username', $pppoe_username)->find_one()){ $msg.= Lang::T('PPPoE Username already used by another customer') . '
    '; } if(ORM::for_table('tbl_customers')->where('username', $pppoe_username)->find_one()){ $msg.= Lang::T('PPPoE Username already used by another customer') . '
    '; } + $pppoeDiff = true; } if ($password != '' && $oldPassPassword != $password) { $passDiff = true; From 3ca43c69a8df19adb22a901675df602631493edc Mon Sep 17 00:00:00 2001 From: Ibnu Maksum Date: Tue, 6 Aug 2024 10:21:26 +0700 Subject: [PATCH 027/841] allow $pppoe_username so it will back to customer username --- system/controllers/customers.php | 12 +++++++----- system/lan/english.json | 3 ++- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/system/controllers/customers.php b/system/controllers/customers.php index baee9405..511040e3 100644 --- a/system/controllers/customers.php +++ b/system/controllers/customers.php @@ -541,11 +541,13 @@ switch ($action) { $userDiff = true; } if ($oldPppoeUsername != $pppoe_username) { - if(ORM::for_table('tbl_customers')->where('pppoe_username', $pppoe_username)->find_one()){ - $msg.= Lang::T('PPPoE Username already used by another customer') . '
    '; - } - if(ORM::for_table('tbl_customers')->where('username', $pppoe_username)->find_one()){ - $msg.= Lang::T('PPPoE Username already used by another customer') . '
    '; + if(!empty($pppoe_username)){ + if(ORM::for_table('tbl_customers')->where('pppoe_username', $pppoe_username)->find_one()){ + $msg.= Lang::T('PPPoE Username already used by another customer') . '
    '; + } + if(ORM::for_table('tbl_customers')->where('username', $pppoe_username)->find_one()){ + $msg.= Lang::T('PPPoE Username already used by another customer') . '
    '; + } } $pppoeDiff = true; } diff --git a/system/lan/english.json b/system/lan/english.json index e775eb4f..5797a2d0 100644 --- a/system/lan/english.json +++ b/system/lan/english.json @@ -694,5 +694,6 @@ "_": "-", "Routers_Maps": "Routers Maps", "Routers_Geo_Location_Information": "Routers Geo Location Information", - "Coverage": "Coverage" + "Coverage": "Coverage", + "PPPoE_Username_already_used_by_another_customer": "PPPoE Username already used by another customer" } \ No newline at end of file From 3b8a5ad2dcc2d1ab2765268ba83e57a02e34372b Mon Sep 17 00:00:00 2001 From: Ibnu Maksum Date: Tue, 6 Aug 2024 10:26:40 +0700 Subject: [PATCH 028/841] update CHANGELOG --- CHANGELOG.md | 4 ++++ version.json | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 25c78165..bfb6d5ab 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ # CHANGELOG +## 2024.8.6 + +- Fix Customer pppoe username + ## 2024.8.5 - Add Customer Mail Inbox diff --git a/version.json b/version.json index 7602a143..bed772bd 100644 --- a/version.json +++ b/version.json @@ -1,3 +1,3 @@ { - "version": "2024.8.5.1" + "version": "2024.8.6" } \ No newline at end of file From bf71393fffdcafec666e34aa10c341202da1b569 Mon Sep 17 00:00:00 2001 From: Ibnu Maksum Date: Tue, 6 Aug 2024 15:42:57 +0700 Subject: [PATCH 029/841] sync PPPOE IP when it change --- system/controllers/customers.php | 7 ++++++- system/lan/english.json | 3 ++- version.json | 2 +- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/system/controllers/customers.php b/system/controllers/customers.php index 511040e3..f486b2c2 100644 --- a/system/controllers/customers.php +++ b/system/controllers/customers.php @@ -531,6 +531,7 @@ switch ($action) { $userDiff = false; $pppoeDiff = false; $passDiff = false; + $pppoeIpDiff = false; if ($oldusername != $username) { if (ORM::for_table('tbl_customers')->where('username', $username)->find_one()) { $msg .= Lang::T('Username already used by another customer') . '
    '; @@ -551,6 +552,10 @@ switch ($action) { } $pppoeDiff = true; } + + if ($oldPppoeIp != $pppoe_ip) { + $pppoeIpDiff = true; + } if ($password != '' && $oldPassPassword != $password) { $passDiff = true; } @@ -625,7 +630,7 @@ switch ($action) { } } - if ($userDiff || $pppoeDiff || $passDiff) { + if ($userDiff || $pppoeDiff || $pppoeIpDiff || $passDiff) { $turs = ORM::for_table('tbl_user_recharges')->where('customer_id', $c['id'])->findMany(); foreach ($turs as $tur) { $p = ORM::for_table('tbl_plans')->find_one($tur['plan_id']); diff --git a/system/lan/english.json b/system/lan/english.json index 5797a2d0..d900c1a4 100644 --- a/system/lan/english.json +++ b/system/lan/english.json @@ -695,5 +695,6 @@ "Routers_Maps": "Routers Maps", "Routers_Geo_Location_Information": "Routers Geo Location Information", "Coverage": "Coverage", - "PPPoE_Username_already_used_by_another_customer": "PPPoE Username already used by another customer" + "PPPoE_Username_already_used_by_another_customer": "PPPoE Username already used by another customer", + "just_now": "just now" } \ No newline at end of file diff --git a/version.json b/version.json index bed772bd..602299ec 100644 --- a/version.json +++ b/version.json @@ -1,3 +1,3 @@ { - "version": "2024.8.6" + "version": "2024.8.6.1" } \ No newline at end of file From da3ef535a2ec431a31b34c40b064e7e90b667490 Mon Sep 17 00:00:00 2001 From: Ibnu Maksum Date: Tue, 6 Aug 2024 16:19:55 +0700 Subject: [PATCH 030/841] Text::convertDataUnit($datalimit, $unit) --- scan/webqr.js | 0 system/autoload/Text.php | 16 ++++++++++++++++ 2 files changed, 16 insertions(+) delete mode 100644 scan/webqr.js diff --git a/scan/webqr.js b/scan/webqr.js deleted file mode 100644 index e69de29b..00000000 diff --git a/system/autoload/Text.php b/system/autoload/Text.php index beb55164..92867869 100644 --- a/system/autoload/Text.php +++ b/system/autoload/Text.php @@ -67,4 +67,20 @@ class Text { return preg_match("/<[^<]+>/", $string, $m) != 0; } + + public static function convertDataUnit($datalimit, $unit = 'MB') + { + $unit = strtoupper($unit); + if ($unit == 'KB') { + return $datalimit * 1024; + } elseif ($unit == 'MB') { + return $datalimit * 1024 * 1000; + } elseif ($unit == 'GB') { + return $datalimit * 1024 * 1000 * 1000; + } elseif ($unit == 'TB') { + return $datalimit * 1024 * 1000 * 1000 * 1000; + } else { + return $datalimit; + } + } } From 8c00496a5b5d0038cc4727cc2e348e28832c8b28 Mon Sep 17 00:00:00 2001 From: Ibnu Maksum Date: Tue, 6 Aug 2024 16:25:36 +0700 Subject: [PATCH 031/841] add acctinputoctets acctoutputoctets --- install/phpnuxbill.sql | 2 ++ radius.php | 57 ++++++++++++++++++++++++------------------ system/updates.json | 4 +++ 3 files changed, 39 insertions(+), 24 deletions(-) diff --git a/install/phpnuxbill.sql b/install/phpnuxbill.sql index e3b66ef4..173dc46c 100644 --- a/install/phpnuxbill.sql +++ b/install/phpnuxbill.sql @@ -221,6 +221,8 @@ CREATE TABLE `rad_acct` ( `nasportid` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL, `nasporttype` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL, `framedipaddress` varchar(15) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '', + `acctinputoctets` BIGINT NOT NULL DEFAULT '0', + `acctoutputoctets` BIGINT NOT NULL DEFAULT '0', `acctstatustype` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL, `macaddr` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, `dateAdded` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP diff --git a/radius.php b/radius.php index c47a1578..8a12f649 100644 --- a/radius.php +++ b/radius.php @@ -68,31 +68,31 @@ try { $username = _req('username'); $password = _req('password'); $isVoucher = ($username == $password); - $real = _req('CHAPassword'); - $challenge = _req('CHAPchallenge'); - if (!empty($real)) { //aktif hanya kalo chappasword ada isinya - $dd = ORM::for_table('tbl_customers')->select('password')->where('username', $username)->find_one(); - $pwd = $dd['password']; //ambil password text - $challenger = hex2bin(substr($challenge, 2)); //buang 0x - $realr = substr($real, 2); //buang 0x lagi - $chapid = substr($realr, 0, 2); //ambil chap-id dari chap-pass - $chapidr = hex2bin($chapid); //konvert chap-id - $result = $chapidr . $pwd . $challenger; //mix semua - $response = $chapid.md5($result); //enkripsi lagi hasilnya trus di mix sama chap id - if ($response != $realr) { //begal kalo hasil gak sama - show_radius_result(['Reply-Message' => 'Username or Password is wrong'], 401); - } - - //if ($response == $realr) { echo 'ok betul 100'; }else{ echo 'salah'; } // untuk keperluan debug - } else { //kalo chappassword kosong brrti eksekusi yg ini + $real = _req('CHAPassword'); + $challenge = _req('CHAPchallenge'); + if (!empty($real)) { //aktif hanya kalo chappasword ada isinya + $dd = ORM::for_table('tbl_customers')->select('password')->where('username', $username)->find_one(); + $pwd = $dd['password']; //ambil password text + $challenger = hex2bin(substr($challenge, 2)); //buang 0x + $realr = substr($real, 2); //buang 0x lagi + $chapid = substr($realr, 0, 2); //ambil chap-id dari chap-pass + $chapidr = hex2bin($chapid); //konvert chap-id + $result = $chapidr . $pwd . $challenger; //mix semua + $response = $chapid . md5($result); //enkripsi lagi hasilnya trus di mix sama chap id + if ($response != $realr) { //begal kalo hasil gak sama + show_radius_result(['Reply-Message' => 'Username or Password is wrong'], 401); + } - if (empty($username) || empty($password)) { - show_radius_result([ - "control:Auth-Type" => "Reject", - "reply:Reply-Message" => 'Login invalid......' - ], 401); - } - } + //if ($response == $realr) { echo 'ok betul 100'; }else{ echo 'salah'; } // untuk keperluan debug + } else { //kalo chappassword kosong brrti eksekusi yg ini + + if (empty($username) || empty($password)) { + show_radius_result([ + "control:Auth-Type" => "Reject", + "reply:Reply-Message" => 'Login invalid......' + ], 401); + } + } $tur = ORM::for_table('tbl_user_recharges')->where('username', $username)->find_one(); if ($tur) { if (!$isVoucher) { @@ -151,6 +151,15 @@ try { if (!$d) { $d = ORM::for_table('rad_acct')->create(); } + $acctOutputOctets = _post('acctOutputOctets'); + $acctInputOctets = _post('acctInputOctets'); + if ($acctOutputOctets !== false && $acctInputOctets !== false) { + $d->acctOutputOctets += $acctOutputOctets; + $d->acctInputOctets += $acctInputOctets; + }else{ + $d->acctOutputOctets = 0; + $d->acctInputOctets = 0; + } $d->acctsessionid = _post('acctSessionId'); $d->username = $username; $d->realm = _post('realm'); diff --git a/system/updates.json b/system/updates.json index 87db6cf1..8d0ceb65 100644 --- a/system/updates.json +++ b/system/updates.json @@ -144,5 +144,9 @@ "2024.8.5.1" : [ "ALTER TABLE `tbl_routers` ADD `coordinates` VARCHAR(50) NOT NULL DEFAULT '' AFTER `description`;", "ALTER TABLE `tbl_routers` ADD `coverage` VARCHAR(8) NOT NULL DEFAULT '0' AFTER `coordinates`;" + ], + "2024.8.6" : [ + "ALTER TABLE `rad_acct` ADD `acctinputoctets` BIGINT NOT NULL DEFAULT '0' AFTER `framedipaddress`;", + "ALTER TABLE `rad_acct` ADD `acctoutputoctets` BIGINT NOT NULL DEFAULT '0' AFTER `acctinputoctets`;" ] } \ No newline at end of file From 668c7af1e9511b9388cd96aba6715eb2383a781a Mon Sep 17 00:00:00 2001 From: Ibnu Maksum Date: Tue, 6 Aug 2024 16:39:03 +0700 Subject: [PATCH 032/841] update acctOutputOctets for limiting data usage --- radius.php | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/radius.php b/radius.php index 8a12f649..2a3d2847 100644 --- a/radius.php +++ b/radius.php @@ -156,7 +156,7 @@ try { if ($acctOutputOctets !== false && $acctInputOctets !== false) { $d->acctOutputOctets += $acctOutputOctets; $d->acctInputOctets += $acctInputOctets; - }else{ + } else { $d->acctOutputOctets = 0; $d->acctInputOctets = 0; } @@ -172,6 +172,18 @@ try { $d->macaddr = _post('macAddr'); $d->dateAdded = date('Y-m-d H:i:s'); $d->save(); + if($d->acctstatustype == 'Start'){ + $tur = ORM::for_table('tbl_user_recharges')->where('username', $username)->where('status', 'on')->where('routers', 'radius')->find_one(); + $plan = ORM::for_table('tbl_plans')->where('id', $tur['plan_id'])->find_one(); + if ($plan['limit_type'] == "Data_Limit" || $plan['limit_type'] == "Both_Limit") { + $totalUsage = $d['acctOutputOctets'] + $d['acctInputOctets']; + $attrs['reply:Mikrotik-Total-Limit'] = Text::convertDataUnit($plan['data_limit'], $plan['data_unit']) - $totalUsage; + if ($attrs['reply:Mikrotik-Total-Limit'] < 0) { + $attrs['reply:Mikrotik-Total-Limit'] = 0; + show_radius_result(["control:Auth-Type" => "Accept", 'Reply-Message' => 'You have exceeded your data limit.'], 401); + } + } + } show_radius_result([ "control:Auth-Type" => "Accept", "reply:Reply-Message" => 'Saved' @@ -239,6 +251,15 @@ function process_radiust_rest($tur, $code) } if ($plan['typebp'] == "Limited") { + if ($plan['limit_type'] == "Data_Limit" || $plan['limit_type'] == "Both_Limit") { + $raddact = ORM::for_table('rad_acct')->where('username', $tur['username'])->find_one(); + $totalUsage = $raddact['acctOutputOctets'] + $raddact['acctInputOctets']; + $attrs['reply:Mikrotik-Total-Limit'] = Text::convertDataUnit($plan['data_limit'], $plan['data_unit']) - $totalUsage; + if ($attrs['reply:Mikrotik-Total-Limit'] < 0) { + $attrs['reply:Mikrotik-Total-Limit'] = 0; + show_radius_result(["control:Auth-Type" => "Accept", 'Reply-Message' => 'You have exceeded your data limit.'], 401); + } + } if ($plan['limit_type'] == "Time_Limit") { if ($plan['time_unit'] == 'Hrs') $timelimit = $plan['time_limit'] * 60 * 60; From 6316992bc3e3c3a52500cc97f71f5fbbddb2bb8e Mon Sep 17 00:00:00 2001 From: ABDALRAHMAN MOLOOD Date: Wed, 7 Aug 2024 01:53:31 +0300 Subject: [PATCH 033/841] Update paymentgateway-audit-view.tpl - fix the view --- ui/ui/paymentgateway-audit-view.tpl | 187 +++++++++++++++++----------- 1 file changed, 115 insertions(+), 72 deletions(-) diff --git a/ui/ui/paymentgateway-audit-view.tpl b/ui/ui/paymentgateway-audit-view.tpl index 844f6fb0..90dc2308 100644 --- a/ui/ui/paymentgateway-audit-view.tpl +++ b/ui/ui/paymentgateway-audit-view.tpl @@ -1,79 +1,122 @@ {include file="sections/header.tpl"} +
    +
    +
    +
    +
    + {$pg['id']} +
    +
    +
      +
    • + Gateway trx id + {$pg['gateway_trx_id']} +
    • +
    • + {Lang::T('Invoice')} + + {$pg['trx_invoice']} + +
    • +
    • + {Lang::T('Status')} + + {if $pg['status'] == 1}UNPAID{elseif $pg['status'] == 2}PAID{elseif $pg['status'] == 3}FAILED{else}CANCELED{/if} + +
    • +
    • + {Lang::T('Username')} + + {$pg['username']} + +
    • +
    • + {Lang::T('Plan Name')} + {$pg['plan_name']} +
    • +
    • + {Lang::T('Routers')} + {$pg['routers']} +
    • +
    • + {Lang::T('Price')} + {Lang::moneyFormat($pg['price'])} +
    • +
    • + {Lang::T('Payment Link')} + + {if $pg['pg_url_payment']} + click here + {/if} + +
    • +
    • + {Lang::T('Channel')} + {$pg['payment_method']} - {$pg['payment_channel']} +
    • +
    • + {Lang::T('Created')} + {if $pg['created_date'] != null}{Lang::dateTimeFormat($pg['created_date'])}{/if} +
    • +
    • + {Lang::T('Expired')} + {if $pg['expired_date'] != null}{Lang::dateTimeFormat($pg['expired_date'])}{/if} +
    • +
    • + {Lang::T('Paid')} + {if $pg['paid_date'] != null}{Lang::dateTimeFormat($pg['paid_date'])}{/if} +
    • +
    +
    +
    +
    +
    -
    -
    -
    -
    - {$pg['gateway_trx_id']} -
    -
    -
      -
    • - TRX ID  {$pg['id']}  -
    • -
    • - {Lang::T('Invoice')}   - {$pg['trx_invoice']} -   -
    • -
    • - {Lang::T('Status')}  {if $pg['status'] == 1}UNPAID{elseif $pg['status'] == 2}PAID{elseif $pg['status'] == 3}FAILED{else}CANCELED{/if}  -
    • -
    • - {Lang::T('Username')} -  {$pg['username']}  -
    • -
    • - {Lang::T('Plan Name')}  {$pg['plan_name']}  -
    • -
    • - {Lang::T('Routers')}  {$pg['routers']}  -
    • -
    • - {Lang::T('Price')}  {Lang::moneyFormat($pg['price'])}  -
    • -
    • - {Lang::T('Payment Link')}  {if $pg['pg_url_payment']} - open - {/if}  -
    • -
    • - {Lang::T('Channel')}  {$pg['payment_method']} - - {$pg['payment_channel']}  -
    • -
    • - {Lang::T('Created')}  {if $pg['created_date'] != null}{Lang::dateTimeFormat($pg['created_date'])}{/if}  -
    • -
    • - {Lang::T('Expired')}  {if $pg['expired_date'] != null}{Lang::dateTimeFormat($pg['expired_date'])}{/if}  -
    • -
    • - {Lang::T('Paid')}  {if $pg['paid_date'] != null}{Lang::dateTimeFormat($pg['paid_date'])}{/if}  -
    • -
    -
    +
    +
    + Response +
    +
    + {if $pg['pg_paid_response'] != null} + {assign var='paid_response' value=json_decode($pg['pg_paid_response'], true)} + + + + + + + + + {foreach from=$paid_response key=k item=v} + {if is_array($v)} + {foreach from=$v key=vk item=vv} + {if is_array($vv)} + {foreach from=$vv key=vvk item=vvv} + + + + + {/foreach} + {else} + + + + + {/if} + {/foreach} + {else} + + + + + {/if} + {/foreach} + +
    KeyValue
    {$k} - {$vk} - {$vvk}{$vvv|json_encode}
    {$k} - {$vk}{$vv|json_encode nofilter}
    {$k}{if is_array(json_decode($v, true))}{$v|json_encode}{else}{$v nofilter}{/if}
    + {/if}
    -
    -
    - Response when request payment -
    -
    {if $pg['pg_request'] != null}{Lang::jsonArray2text(json_decode($pg['pg_request'], true))}{/if}
    -
    -
    -
    - Response when payment PAID -
    -
    {if $pg['pg_request'] != null}{Lang::jsonArray2text(json_decode($pg['pg_paid_response'], true))}{/if}
    -
    - -{include file="sections/footer.tpl"} \ No newline at end of file +{include file="sections/footer.tpl"} From dc4adbc0c6b93b536fe47bd17e52c215a1d4b214 Mon Sep 17 00:00:00 2001 From: ABDALRAHMAN MOLOOD Date: Wed, 7 Aug 2024 01:53:53 +0300 Subject: [PATCH 034/841] Update paymentgateway-audit.tpl - fix the view --- ui/ui/paymentgateway-audit.tpl | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/ui/ui/paymentgateway-audit.tpl b/ui/ui/paymentgateway-audit.tpl index e10de7d3..3863bece 100644 --- a/ui/ui/paymentgateway-audit.tpl +++ b/ui/ui/paymentgateway-audit.tpl @@ -17,16 +17,12 @@ - - - - @@ -35,13 +31,11 @@ {foreach $pgs as $pg} - + class="text-black">{$pg['id']} - - - @@ -63,8 +55,8 @@
    TRX ID PG ID {Lang::T('Username')} {Lang::T('Plan Name')}{Lang::T('Routers')} {Lang::T('Price')} {Lang::T('Payment Link')}{Lang::T('Channel')} {Lang::T('Created')}{Lang::T('Expired')} {Lang::T('Paid')} {Lang::T('Invoice')} {Lang::T('Status')}
    {$pg['id']} {$pg['gateway_trx_id']} {$pg['username']} {$pg['plan_name']}{$pg['routers']} {Lang::moneyFormat($pg['price'])} {if $pg['pg_url_payment']} @@ -49,9 +43,7 @@ rel="noopener noreferrer">open {/if} {$pg['payment_method']} - {$pg['payment_channel']} {if $pg['created_date'] != null}{Lang::dateTimeFormat($pg['created_date'])}{/if}{if $pg['expired_date'] != null}{Lang::dateTimeFormat($pg['expired_date'])}{/if} {if $pg['paid_date'] != null}{Lang::dateTimeFormat($pg['paid_date'])}{/if} {if $pg['trx_invoice']}{$pg['trx_invoice']}{/if}
    {include file="pagination.tpl"} - kembali +
    -{include file="sections/footer.tpl"} \ No newline at end of file +{include file="sections/footer.tpl"} From d35c7080d9963c2cd68dda4068d2b8d898e13dfb Mon Sep 17 00:00:00 2001 From: iBNu Maksum Date: Wed, 7 Aug 2024 09:32:01 +0700 Subject: [PATCH 035/841] Revert "Fix the view" --- ui/ui/paymentgateway-audit-view.tpl | 187 +++++++++++----------------- ui/ui/paymentgateway-audit.tpl | 14 ++- 2 files changed, 83 insertions(+), 118 deletions(-) diff --git a/ui/ui/paymentgateway-audit-view.tpl b/ui/ui/paymentgateway-audit-view.tpl index 90dc2308..844f6fb0 100644 --- a/ui/ui/paymentgateway-audit-view.tpl +++ b/ui/ui/paymentgateway-audit-view.tpl @@ -1,122 +1,79 @@ {include file="sections/header.tpl"} -
    -
    -
    -
    -
    - {$pg['id']} -
    -
    -
      -
    • - Gateway trx id - {$pg['gateway_trx_id']} -
    • -
    • - {Lang::T('Invoice')} - - {$pg['trx_invoice']} - -
    • -
    • - {Lang::T('Status')} - - {if $pg['status'] == 1}UNPAID{elseif $pg['status'] == 2}PAID{elseif $pg['status'] == 3}FAILED{else}CANCELED{/if} - -
    • -
    • - {Lang::T('Username')} - - {$pg['username']} - -
    • -
    • - {Lang::T('Plan Name')} - {$pg['plan_name']} -
    • -
    • - {Lang::T('Routers')} - {$pg['routers']} -
    • -
    • - {Lang::T('Price')} - {Lang::moneyFormat($pg['price'])} -
    • -
    • - {Lang::T('Payment Link')} - - {if $pg['pg_url_payment']} - click here - {/if} - -
    • -
    • - {Lang::T('Channel')} - {$pg['payment_method']} - {$pg['payment_channel']} -
    • -
    • - {Lang::T('Created')} - {if $pg['created_date'] != null}{Lang::dateTimeFormat($pg['created_date'])}{/if} -
    • -
    • - {Lang::T('Expired')} - {if $pg['expired_date'] != null}{Lang::dateTimeFormat($pg['expired_date'])}{/if} -
    • -
    • - {Lang::T('Paid')} - {if $pg['paid_date'] != null}{Lang::dateTimeFormat($pg['paid_date'])}{/if} -
    • -
    -
    -
    -
    -
    -
    -
    - Response -
    -
    - {if $pg['pg_paid_response'] != null} - {assign var='paid_response' value=json_decode($pg['pg_paid_response'], true)} - - - - - - - - - {foreach from=$paid_response key=k item=v} - {if is_array($v)} - {foreach from=$v key=vk item=vv} - {if is_array($vv)} - {foreach from=$vv key=vvk item=vvv} - - - - - {/foreach} - {else} - - - - - {/if} - {/foreach} - {else} - - - - - {/if} - {/foreach} - -
    KeyValue
    {$k} - {$vk} - {$vvk}{$vvv|json_encode}
    {$k} - {$vk}{$vv|json_encode nofilter}
    {$k}{if is_array(json_decode($v, true))}{$v|json_encode}{else}{$v nofilter}{/if}
    - {/if} +
    +
    +
    +
    + {$pg['gateway_trx_id']} +
    +
    +
      +
    • + TRX ID  {$pg['id']}  +
    • +
    • + {Lang::T('Invoice')}   + {$pg['trx_invoice']} +   +
    • +
    • + {Lang::T('Status')}  {if $pg['status'] == 1}UNPAID{elseif $pg['status'] == 2}PAID{elseif $pg['status'] == 3}FAILED{else}CANCELED{/if}  +
    • +
    • + {Lang::T('Username')} +  {$pg['username']}  +
    • +
    • + {Lang::T('Plan Name')}  {$pg['plan_name']}  +
    • +
    • + {Lang::T('Routers')}  {$pg['routers']}  +
    • +
    • + {Lang::T('Price')}  {Lang::moneyFormat($pg['price'])}  +
    • +
    • + {Lang::T('Payment Link')}  {if $pg['pg_url_payment']} + open + {/if}  +
    • +
    • + {Lang::T('Channel')}  {$pg['payment_method']} - + {$pg['payment_channel']}  +
    • +
    • + {Lang::T('Created')}  {if $pg['created_date'] != null}{Lang::dateTimeFormat($pg['created_date'])}{/if}  +
    • +
    • + {Lang::T('Expired')}  {if $pg['expired_date'] != null}{Lang::dateTimeFormat($pg['expired_date'])}{/if}  +
    • +
    • + {Lang::T('Paid')}  {if $pg['paid_date'] != null}{Lang::dateTimeFormat($pg['paid_date'])}{/if}  +
    • +
    +
    -{include file="sections/footer.tpl"} +
    +
    + Response when request payment +
    +
    {if $pg['pg_request'] != null}{Lang::jsonArray2text(json_decode($pg['pg_request'], true))}{/if}
    +
    +
    +
    + Response when payment PAID +
    +
    {if $pg['pg_request'] != null}{Lang::jsonArray2text(json_decode($pg['pg_paid_response'], true))}{/if}
    +
    + +{include file="sections/footer.tpl"} \ No newline at end of file diff --git a/ui/ui/paymentgateway-audit.tpl b/ui/ui/paymentgateway-audit.tpl index 3863bece..e10de7d3 100644 --- a/ui/ui/paymentgateway-audit.tpl +++ b/ui/ui/paymentgateway-audit.tpl @@ -17,12 +17,16 @@ + + + + @@ -31,11 +35,13 @@ {foreach $pgs as $pg} + + class="text-black">{$pg['gateway_trx_id']} + + + @@ -55,8 +63,8 @@
    TRX ID PG ID {Lang::T('Username')} {Lang::T('Plan Name')}{Lang::T('Routers')} {Lang::T('Price')} {Lang::T('Payment Link')}{Lang::T('Channel')} {Lang::T('Created')}{Lang::T('Expired')} {Lang::T('Paid')} {Lang::T('Invoice')} {Lang::T('Status')}
    {$pg['id']} {$pg['id']} {$pg['username']} {$pg['plan_name']}{$pg['routers']} {Lang::moneyFormat($pg['price'])} {if $pg['pg_url_payment']} @@ -43,7 +49,9 @@ rel="noopener noreferrer">open {/if} {$pg['payment_method']} - {$pg['payment_channel']} {if $pg['created_date'] != null}{Lang::dateTimeFormat($pg['created_date'])}{/if}{if $pg['expired_date'] != null}{Lang::dateTimeFormat($pg['expired_date'])}{/if} {if $pg['paid_date'] != null}{Lang::dateTimeFormat($pg['paid_date'])}{/if} {if $pg['trx_invoice']}{$pg['trx_invoice']}{/if}
    {include file="pagination.tpl"} - + kembali
    -{include file="sections/footer.tpl"} +{include file="sections/footer.tpl"} \ No newline at end of file From 3c218d9ec9830b43c3b8d7ffab19b0a4864fed09 Mon Sep 17 00:00:00 2001 From: Ibnu Maksum Date: Wed, 7 Aug 2024 09:51:37 +0700 Subject: [PATCH 036/841] Change UI and code payment gateway audit --- system/autoload/Lang.php | 12 -- system/autoload/Text.php | 26 ++++ system/controllers/paymentgateway.php | 164 +++++++++++++------------- ui/ui/paymentgateway-audit-view.tpl | 22 +++- 4 files changed, 127 insertions(+), 97 deletions(-) diff --git a/system/autoload/Lang.php b/system/autoload/Lang.php index 5b3f42ed..c6328293 100644 --- a/system/autoload/Lang.php +++ b/system/autoload/Lang.php @@ -259,16 +259,4 @@ class Lang } } - // echo Json array to text - public static function jsonArray2text($array, $start = '', $result = '') - { - foreach ($array as $k => $v) { - if (is_array($v)) { - $result .= self::jsonArray2text($v, "$start$k.", ''); - } else { - $result .= "$start$k = " . strval($v) . "\n"; - } - } - return $result; - } } diff --git a/system/autoload/Text.php b/system/autoload/Text.php index 92867869..45793b26 100644 --- a/system/autoload/Text.php +++ b/system/autoload/Text.php @@ -83,4 +83,30 @@ class Text return $datalimit; } } + + // echo Json array to text + public static function jsonArray2text($array, $start = '', $result = '') + { + foreach ($array as $k => $v) { + if (is_array($v)) { + $result .= self::jsonArray2text($v, "$start$k.", ''); + } else { + $result .= "$start$k = " . strval($v) . "\n"; + } + } + return $result; + } + + public static function jsonArray21Array($array){ + $text = self::jsonArray2text($array); + $lines = explode("\n", $text); + $result = []; + foreach($lines as $line){ + $parts = explode(' = ', $line); + if(count($parts) == 2){ + $result[trim($parts[0])] = trim($parts[1]); + } + } + return $result; + } } diff --git a/system/controllers/paymentgateway.php b/system/controllers/paymentgateway.php index a22f848b..7183551f 100644 --- a/system/controllers/paymentgateway.php +++ b/system/controllers/paymentgateway.php @@ -10,93 +10,91 @@ $ui->assign('_system_menu', 'paymentgateway'); $action = alphanumeric($routes[1]); $ui->assign('_admin', $admin); - -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 ($action == 'audit') { - $pg = alphanumeric($routes[2]); - $q = alphanumeric(_req('q'),'-._ '); - $query = ORM::for_table('tbl_payment_gateway')->order_by_desc("id"); - $query->selects('id', 'username', 'gateway', 'gateway_trx_id', 'plan_id', 'plan_name', 'routers_id', 'routers', 'price', 'pg_url_payment', 'payment_method', 'payment_channel', 'expired_date', 'created_date', 'paid_date', 'trx_invoice', 'status'); - $query->where('gateway', $pg); - if(!empty($q)) { - $query->whereRaw("(gateway_trx_id LIKE '%$q%' OR username LIKE '%$q%' OR routers LIKE '%$q%' OR plan_name LIKE '%$q%')"); - $append_url = 'q='. urlencode($q); - } - $pgs = Paginator::findMany($query, ["search" => $search], 50, $append_url); - - $ui->assign('_title', 'Payment Gateway Audit'); - $ui->assign('pgs', $pgs); - $ui->assign('pg', $pg); - $ui->assign('q', $q); - $ui->display('paymentgateway-audit.tpl'); - die(); -} - -if ($action == 'auditview') { - $pg = alphanumeric($routes[2]); - - $d = ORM::for_table('tbl_payment_gateway')->find_one($pg); - $ui->assign('_title', 'Payment Gateway Audit View'); - $ui->assign('pg', $d); - $ui->display('paymentgateway-audit-view.tpl'); - die(); -} - -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 { - $ui->display('a404.tpl'); +switch ($action) { + case 'delete': + $pg = alphanumeric($routes[2]); + if (file_exists($PAYMENTGATEWAY_PATH . DIRECTORY_SEPARATOR . $pg . '.php')) { + deleteFile($PAYMENTGATEWAY_PATH . DIRECTORY_SEPARATOR, $pg); } - } else { - if (function_exists($action . '_show_config')) { - call_user_func($action . '_show_config'); - } else { - $ui->display('a404.tpl'); + r2(U . 'paymentgateway', 's', Lang::T('Payment Gateway Deleted')); + + case 'audit': + $pg = alphanumeric($routes[2]); + $q = alphanumeric(_req('q'), '-._ '); + $query = ORM::for_table('tbl_payment_gateway')->order_by_desc("id"); + $query->selects('id', 'username', 'gateway', 'gateway_trx_id', 'plan_id', 'plan_name', 'routers_id', 'routers', 'price', 'pg_url_payment', 'payment_method', 'payment_channel', 'expired_date', 'created_date', 'paid_date', 'trx_invoice', 'status'); + $query->where('gateway', $pg); + if (!empty($q)) { + $query->whereRaw("(gateway_trx_id LIKE '%$q%' OR username LIKE '%$q%' OR routers LIKE '%$q%' OR plan_name LIKE '%$q%')"); + $append_url = 'q=' . urlencode($q); } - } -} else { - if (!empty($action)) { - r2(U . 'paymentgateway', 'w', Lang::T('Payment Gateway Not Found')); - } else { - $files = scandir($PAYMENTGATEWAY_PATH); - foreach ($files as $file) { - if (pathinfo($file, PATHINFO_EXTENSION) == 'php') { - $pgs[] = str_replace('.php', '', $file); + $pgs = Paginator::findMany($query, ["search" => $search], 50, $append_url); + + $ui->assign('_title', 'Payment Gateway Audit'); + $ui->assign('pgs', $pgs); + $ui->assign('pg', $pg); + $ui->assign('q', $q); + $ui->display('paymentgateway-audit.tpl'); + break; + case 'auditview': + $pg = alphanumeric($routes[2]); + $d = ORM::for_table('tbl_payment_gateway')->find_one($pg); + $d['pg_request'] = (!empty($d['pg_request']))? Text::jsonArray21Array(json_decode($d['pg_request'], true)) : []; + $d['pg_paid_response'] = (!empty($d['pg_paid_response']))? Text::jsonArray21Array(json_decode($d['pg_paid_response'], true)) : []; + $ui->assign('_title', 'Payment Gateway Audit View'); + $ui->assign('pg', $d); + $ui->display('paymentgateway-audit-view.tpl'); + break; + default: + 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 { + $ui->display('a404.tpl'); + } + } else { + if (function_exists($action . '_show_config')) { + call_user_func($action . '_show_config'); + } else { + $ui->display('a404.tpl'); + } + } + } else { + if (!empty($action)) { + r2(U . 'paymentgateway', 'w', Lang::T('Payment Gateway Not Found')); + } else { + $files = scandir($PAYMENTGATEWAY_PATH); + foreach ($files as $file) { + if (pathinfo($file, PATHINFO_EXTENSION) == 'php') { + $pgs[] = str_replace('.php', '', $file); + } + } + $ui->assign('_title', 'Payment Gateway Settings'); + $ui->assign('pgs', $pgs); + $ui->assign('actives', explode(',', $config['payment_gateway'])); + $ui->display('paymentgateway.tpl'); } } - $ui->assign('_title', 'Payment Gateway Settings'); - $ui->assign('pgs', $pgs); - $ui->assign('actives', explode(',', $config['payment_gateway'])); - $ui->display('paymentgateway.tpl'); - } } diff --git a/ui/ui/paymentgateway-audit-view.tpl b/ui/ui/paymentgateway-audit-view.tpl index 844f6fb0..a72838a7 100644 --- a/ui/ui/paymentgateway-audit-view.tpl +++ b/ui/ui/paymentgateway-audit-view.tpl @@ -67,13 +67,31 @@
    Response when request payment
    -
    {if $pg['pg_request'] != null}{Lang::jsonArray2text(json_decode($pg['pg_request'], true))}{/if}
    +
    + + {foreach $pg['pg_request'] as $k => $v} + + + + + {/foreach} +
    {$k}{$v}
    +
    Response when payment PAID
    -
    {if $pg['pg_request'] != null}{Lang::jsonArray2text(json_decode($pg['pg_paid_response'], true))}{/if}
    +
    + + {foreach $pg['pg_paid_response'] as $k => $v} + + + + + {/foreach} +
    {$k}{$v}
    +
    {include file="sections/footer.tpl"} \ No newline at end of file From e5ff8c56753af468a332fe5bfc9a14c0fab3eeee Mon Sep 17 00:00:00 2001 From: Ibnu Maksum Date: Wed, 7 Aug 2024 10:52:31 +0700 Subject: [PATCH 037/841] fix radius change username --- system/devices/Radius.php | 2 +- system/devices/RadiusRest.php | 2 +- system/devices/readme.md | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/system/devices/Radius.php b/system/devices/Radius.php index 0fa404a2..2544c7c5 100644 --- a/system/devices/Radius.php +++ b/system/devices/Radius.php @@ -92,7 +92,7 @@ class Radius $this->customerDeactivate($customer['username'], true); } - public function change_username($from, $to) + public function change_username($plan, $from, $to) { $c = $this->getTableCustomer()->where_equal('username', $from)->findMany(); if ($c) { diff --git a/system/devices/RadiusRest.php b/system/devices/RadiusRest.php index c1095ef6..5e3fb95b 100644 --- a/system/devices/RadiusRest.php +++ b/system/devices/RadiusRest.php @@ -28,7 +28,7 @@ class RadiusRest { } // customer change username - public function change_username($from, $to) + public function change_username($plan, $from, $to) { } diff --git a/system/devices/readme.md b/system/devices/readme.md index 0a0022e8..c47cbbd6 100644 --- a/system/devices/readme.md +++ b/system/devices/readme.md @@ -34,7 +34,7 @@ class FileName { } // customer change username - public function change_username($from, $to) + public function change_username($plan, $from, $to) { } From f1a9ad6d6395067b04b40293a9fb0941e537553b Mon Sep 17 00:00:00 2001 From: Ibnu Maksum Date: Wed, 7 Aug 2024 11:10:43 +0700 Subject: [PATCH 038/841] simplify Chap verify RadiusRest --- radius.php | 61 ++++++++++++++++++++++++------------ system/autoload/Password.php | 15 +++++++++ 2 files changed, 56 insertions(+), 20 deletions(-) diff --git a/radius.php b/radius.php index 2a3d2847..e822fe16 100644 --- a/radius.php +++ b/radius.php @@ -38,11 +38,30 @@ try { case 'authenticate': $username = _req('username'); $password = _req('password'); - if (empty($username) || empty($password)) { - show_radius_result([ - "control:Auth-Type" => "Reject", - "reply:Reply-Message" => 'Login invalid' - ], 401); + $CHAPassword = _req('CHAPassword'); + $CHAPchallenge = _req('CHAPchallenge'); + if (!empty($CHAPassword)) { + $c = ORM::for_table('tbl_customers')->select('password')->where('username', $username)->find_one(); + //if verified + if (Password::chap_verify($c['password'], $CHAPassword, $CHAPchallenge)) { + $password = $c['password']; + $isVoucher = false; + }else{ + // check if voucher + if (Password::chap_verify($username, $CHAPassword, $CHAPchallenge)) { + $isVoucher = true; + $password = $username; + } else { + show_radius_result(['Reply-Message' => 'Username or Password is wrong'], 401); + } + } + } else { + if (empty($username) || empty($password)) { + show_radius_result([ + "control:Auth-Type" => "Reject", + "reply:Reply-Message" => 'Login invalid......' + ], 401); + } } if ($username == $password) { $d = ORM::for_table('tbl_voucher')->where('code', $username)->find_one(); @@ -68,22 +87,24 @@ try { $username = _req('username'); $password = _req('password'); $isVoucher = ($username == $password); - $real = _req('CHAPassword'); - $challenge = _req('CHAPchallenge'); - if (!empty($real)) { //aktif hanya kalo chappasword ada isinya - $dd = ORM::for_table('tbl_customers')->select('password')->where('username', $username)->find_one(); - $pwd = $dd['password']; //ambil password text - $challenger = hex2bin(substr($challenge, 2)); //buang 0x - $realr = substr($real, 2); //buang 0x lagi - $chapid = substr($realr, 0, 2); //ambil chap-id dari chap-pass - $chapidr = hex2bin($chapid); //konvert chap-id - $result = $chapidr . $pwd . $challenger; //mix semua - $response = $chapid . md5($result); //enkripsi lagi hasilnya trus di mix sama chap id - if ($response != $realr) { //begal kalo hasil gak sama - show_radius_result(['Reply-Message' => 'Username or Password is wrong'], 401); + $CHAPassword = _req('CHAPassword'); + $CHAPchallenge = _req('CHAPchallenge'); + if (!empty($CHAPassword)) { + $c = ORM::for_table('tbl_customers')->select('password')->where('username', $username)->find_one(); + //if verified + if (Password::chap_verify($c['password'], $CHAPassword, $CHAPchallenge)) { + $password = $c['password']; + $isVoucher = false; + }else{ + // check if voucher + if (Password::chap_verify($username, $CHAPassword, $CHAPchallenge)) { + $isVoucher = true; + $password = $username; + } else { + show_radius_result(['Reply-Message' => 'Username or Password is wrong'], 401); + } } - - //if ($response == $realr) { echo 'ok betul 100'; }else{ echo 'salah'; } // untuk keperluan debug + //if ($response == $CHAPr) { echo 'ok betul 100'; }else{ echo 'salah'; } // untuk keperluan debug } else { //kalo chappassword kosong brrti eksekusi yg ini if (empty($username) || empty($password)) { diff --git a/system/autoload/Password.php b/system/autoload/Password.php index 989e27b9..81692ae8 100644 --- a/system/autoload/Password.php +++ b/system/autoload/Password.php @@ -32,4 +32,19 @@ class Password $pass = substr(str_shuffle(str_repeat('ABCDEFGHIJKLMNPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz@#!123456789', 8)), 0, 8); return $pass; } + + /** + * verify CHAP password + * @param string $realPassword + * @param string $CHAPassword + * @param string $CHAPChallenge + * @return bool + */ + public static function chap_verify($realPassword, $CHAPassword, $CHAPChallenge){ + $CHAPassword = substr($CHAPassword, 2); + $chapid = substr($CHAPassword, 0, 2); + $result = hex2bin($chapid) . $realPassword . hex2bin(substr($CHAPChallenge, 2)); + $response = $chapid . md5($result); + return ($response != $CHAPassword); + } } From b24ad24e89f92e9976bf7b267aea880ee7f4a034 Mon Sep 17 00:00:00 2001 From: Ibnu Maksum Date: Wed, 7 Aug 2024 13:51:27 +0700 Subject: [PATCH 039/841] Fix QRCode Scanner --- scan/index.html | 281 --------------------------------------- scan/index.php | 80 +++++++++++ scan/llqrcode.js | 1 - scan/qrcode.min.js | 1 + system/lan/english.json | 5 +- ui/ui/customers-add.tpl | 111 ++++++++-------- ui/ui/customers-edit.tpl | 4 +- version.json | 2 +- 8 files changed, 144 insertions(+), 341 deletions(-) delete mode 100644 scan/index.html create mode 100644 scan/index.php delete mode 100644 scan/llqrcode.js create mode 100644 scan/qrcode.min.js diff --git a/scan/index.html b/scan/index.html deleted file mode 100644 index b7614928..00000000 --- a/scan/index.html +++ /dev/null @@ -1,281 +0,0 @@ - - - - - - - QR Scanner - - - - - -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    Refresh Camera
    -

    Point Camera to Barcode

    -
    -
    - - - - - \ No newline at end of file diff --git a/scan/index.php b/scan/index.php new file mode 100644 index 00000000..7151913d --- /dev/null +++ b/scan/index.php @@ -0,0 +1,80 @@ + + + + + + + QRCode Scanner + + + + +
    +
    + + + + + \ No newline at end of file diff --git a/scan/llqrcode.js b/scan/llqrcode.js deleted file mode 100644 index b78c3254..00000000 --- a/scan/llqrcode.js +++ /dev/null @@ -1 +0,0 @@ -var _aa={};_aa._ab=function(f,e){var d=qrcode.width;var b=qrcode.height;var c=true;for(var g=0;gd||h<-1||h>b){throw"Error._ab "}c=false;if(a==-1){e[g]=0;c=true}else{if(a==d){e[g]=d-1;c=true}}if(h==-1){e[g+1]=0;c=true}else{if(h==b){e[g+1]=b-1;c=true}}}c=true;for(var g=e.length-2;g>=0&&c;g-=2){var a=Math.floor(e[g]);var h=Math.floor(e[g+1]);if(a<-1||a>d||h<-1||h>b){throw"Error._ab "}c=false;if(a==-1){e[g]=0;c=true}else{if(a==d){e[g]=d-1;c=true}}if(h==-1){e[g+1]=0;c=true}else{if(h==b){e[g+1]=b-1;c=true}}}};_aa._af=function(b,d,a){var k=new _ac(d);var j=new Array(d<<1);for(var f=0;f>1)+0.5;j[h+1]=i}a._ad(j);_aa._ab(b,j);try{for(var h=0;h>1,f)}}}catch(c){throw"Error._ab"}}return k};_aa._ah=function(h,o,l,k,q,p,b,a,f,e,n,m,s,r,d,c,j,i){var g=_ae._ag(l,k,q,p,b,a,f,e,n,m,s,r,d,c,j,i);return _aa._af(h,o,g)};function _a1(b,a){this.count=b;this._fc=a;this.__defineGetter__("Count",function(){return this.count});this.__defineGetter__("_dm",function(){return this._fc})}function _a2(a,c,b){this._bm=a;if(b){this._do=new Array(c,b)}else{this._do=new Array(c)}this.__defineGetter__("_bo",function(){return this._bm});this.__defineGetter__("_dn",function(){return this._bm*this._fo});this.__defineGetter__("_fo",function(){var e=0;for(var d=0;d6){o._bq(q-11,0,3,6);o._bq(0,q-11,6,3)}return o};this._bu=function(i){return this._do[i.ordinal()]}}_a3._bv=new Array(31892,34236,39577,42195,48118,51042,55367,58893,63784,68472,70749,76311,79154,84390,87683,92361,96236,102084,102881,110507,110734,117786,119615,126325,127568,133589,136944,141498,145311,150283,152622,158308,161089,167017);_a3.VERSIONS=_ay();_a3._av=function(a){if(a<1||a>40){throw"bad arguments"}return _a3.VERSIONS[a-1]};_a3._at=function(b){if(b%4!=1){throw"Error _at"}try{return _a3._av((b-17)>>2)}catch(a){throw"Error _av"}};_a3._aw=function(d){var b=4294967295;var f=0;for(var c=0;c<_a3._bv.length;c++){var a=_a3._bv[c];if(a==d){return this._av(c+7)}var e=_ax._gj(d,a);if(eMath.abs(c-m);if(d){var r=m;m=l;l=r;r=c;c=b;b=r}var j=Math.abs(c-m);var i=Math.abs(b-l);var p=-j>>1;var u=l0){if(g==b){break}g+=u;p-=j}}var k=c-m;var q=b-l;return Math.sqrt((k*k+q*q))};this._bh=function(i,g,h,f){var b=this._bi(i,g,h,f);var e=1;var d=i-(h-i);if(d<0){e=i/(i-d);d=0}else{if(d>=qrcode.width){e=(qrcode.width-1-i)/(d-i);d=qrcode.width-1}}var c=Math.floor(g-(f-g)*e);e=1;if(c<0){e=g/(g-c);c=0}else{if(c>=qrcode.height){e=(qrcode.height-1-g)/(c-g);c=qrcode.height-1}}d=Math.floor(i+(d-i)*e);b+=this._bi(i,g,d,c);return b-1};this._bj=function(c,d){var b=this._bh(Math.floor(c.X),Math.floor(c.Y),Math.floor(d.X),Math.floor(d.Y));var e=this._bh(Math.floor(d.X),Math.floor(d.Y),Math.floor(c.X),Math.floor(c.Y));if(isNaN(b)){return e/7}if(isNaN(e)){return b/7}return(b+e)/14};this._bk=function(d,c,b){return(this._bj(d,c)+this._bj(d,b))/2};this.distance=function(d,b){var e=d.X-b.X;var c=d.Y-b.Y;return Math.sqrt((e*e+c*c))};this._bx=function(g,f,d,e){var b=Math.round(this.distance(g,f)/e);var c=Math.round(this.distance(g,d)/e);var h=((b+c)>>1)+7;switch(h&3){case 0:h++;break;case 2:h--;break;case 3:throw"Error"}return h};this._bl=function(g,f,d,j){var k=Math.floor(j*g);var h=Math.max(0,f-k);var i=Math.min(qrcode.width-1,f+k);if(i-h0){var f=h.X-j.X+n.X;var e=h.Y-j.Y+n.Y;var c=1-3/k;var t=Math.floor(j.X+c*(f-j.X));var s=Math.floor(j.Y+c*(e-j.Y));for(var p=4;p<=16;p<<=1){l=this._bl(d,t,s,p);break}}var g=this.createTransform(j,h,n,l,r);var m=this._bz(this.image,g,r);var o;if(l==null){o=new Array(n,j,h)}else{o=new Array(n,j,h,l)}return new _bg(m,o)};this.detect=function(){var b=new _cc()._ce(this.image);return this._cd(b)}}var _ca=21522;var _cb=new Array(new Array(21522,0),new Array(20773,1),new Array(24188,2),new Array(23371,3),new Array(17913,4),new Array(16590,5),new Array(20375,6),new Array(19104,7),new Array(30660,8),new Array(29427,9),new Array(32170,10),new Array(30877,11),new Array(26159,12),new Array(25368,13),new Array(27713,14),new Array(26998,15),new Array(5769,16),new Array(5054,17),new Array(7399,18),new Array(6608,19),new Array(1890,20),new Array(597,21),new Array(3340,22),new Array(2107,23),new Array(13663,24),new Array(12392,25),new Array(16177,26),new Array(14854,27),new Array(9396,28),new Array(8579,29),new Array(11994,30),new Array(11245,31));var _ch=new Array(0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4);function _ax(a){this._cf=_cg.forBits((a>>3)&3);this._fe=(a&7);this.__defineGetter__("_cg",function(){return this._cf});this.__defineGetter__("_dx",function(){return this._fe});this.GetHashCode=function(){return(this._cf.ordinal()<<3)|this._fe};this.Equals=function(c){var b=c;return this._cf==b._cf&&this._fe==b._fe}}_ax._gj=function(d,c){d^=c;return _ch[d&15]+_ch[(_ew(d,4)&15)]+_ch[(_ew(d,8)&15)]+_ch[(_ew(d,12)&15)]+_ch[(_ew(d,16)&15)]+_ch[(_ew(d,20)&15)]+_ch[(_ew(d,24)&15)]+_ch[(_ew(d,28)&15)]};_ax._ci=function(a){var b=_ax._cj(a);if(b!=null){return b}return _ax._cj(a^_ca)};_ax._cj=function(d){var b=4294967295;var a=0;for(var c=0;c<_cb.length;c++){var g=_cb[c];var f=g[0];if(f==d){return new _ax(g[1])}var e=this._gj(d,f);if(e=FOR_BITS.length){throw"bad arguments"}return FOR_BITS[a]};var L=new _cg(0,1,"L");var M=new _cg(1,0,"M");var Q=new _cg(2,3,"Q");var H=new _cg(3,2,"H");var FOR_BITS=new Array(M,L,H,Q);function _ac(d,a){if(!a){a=d}if(d<1||a<1){throw"Both dimensions must be greater than 0"}this.width=d;this.height=a;var c=d>>5;if((d&31)!=0){c++}this.rowSize=c;this.bits=new Array(c*a);for(var b=0;b>5);return((_ew(this.bits[f],(e&31)))&1)!=0};this._dq=function(e,g){var f=g*this.rowSize+(e>>5);this.bits[f]|=1<<(e&31)};this.flip=function(e,g){var f=g*this.rowSize+(e>>5);this.bits[f]^=1<<(e&31)};this.clear=function(){var e=this.bits.length;for(var f=0;fthis.height||l>this.width){throw"The region must fit inside the matrix"}for(var i=j;i>5)]|=1<<(k&31)}}}}function _dl(a,b){this._dv=a;this._dw=b;this.__defineGetter__("_du",function(){return this._dv});this.__defineGetter__("Codewords",function(){return this._dw})}_dl._gn=function(c,h,r){if(c.length!=h._dp){throw"bad arguments"}var k=h._bu(r);var e=0;var d=k._fb();for(var q=0;q=0){var v=l[b]._dw.length;if(v==t){break}b--}b++;var g=t-k._bo;var a=0;for(var q=0;q=0;c--){g=this._dk(8,c,g)}this._co=_ax._ci(g);if(this._co!=null){return this._co}var f=this._au.Dimension;g=0;var d=f-8;for(var e=f-1;e>=d;e--){g=this._dk(e,8,g)}for(var c=f-7;c>2;if(f<=6){return _a3._av(f)}var g=0;var e=h-11;for(var c=5;c>=0;c--){for(var d=h-9;d>=e;d--){g=this._dk(d,c,g)}}this._cp=_a3._aw(g);if(this._cp!=null&&this._cp._cr==h){return this._cp}g=0;for(var d=5;d>=0;d--){for(var c=h-9;c>=e;c--){g=this._dk(d,c,g)}}this._cp=_a3._aw(g);if(this._cp!=null&&this._cp._cr==h){return this._cp}throw"Error _cq"};this._gk=function(){var q=this._cm();var o=this._cq();var c=_dx._gl(q._dx);var f=this._au.Dimension;c._dj(this._au,f);var k=o._aq();var n=true;var r=new Array(o._dp);var m=0;var p=0;var h=0;for(var e=f-1;e>0;e-=2){if(e==6){e--}for(var l=0;l7){throw"bad arguments"}return _dx._dy[a]};function _fg(){this._dj=function(c,d){for(var b=0;b=Math.floor(f/2)){var x=B;var g=o;var v=e;B=k;o=j;e=i;if(B.Zero){throw"r_{i-1} was zero"}k=x;var m=this._fa.Zero;var p=B._ex(B._ec);var h=this._fa.inverse(p);while(k._ec>=B._ec&&!k.Zero){var c=k._ec-B._ec;var A=this._fa.multiply(k._ex(k._ec),h);m=m._bd(this._fa._ba(c,A));k=k._bd(B._dc(c,A))}j=m.multiply1(o)._bd(g);i=m.multiply1(e)._bd(v)}var u=i._ex(0);if(u==0){throw"ReedSolomonException sigmaTilde(0) was zero"}var d=this._fa.inverse(u);var n=i.multiply2(d);var l=k.multiply2(d);return new Array(n,l)};this._ey=function(f){var g=f._ec;if(g==1){return new Array(f._ex(1))}var b=new Array(g);var d=0;for(var c=1;c<256&&d1&&e[0]==0){var d=1;while(dn.length){var j=o;o=n;n=j}var h=new Array(n.length);var k=n.length-o.length;for(var m=0;m=l._ec&&!o.Zero){var m=o._ec-l._ec;var h=this._fa.multiply(o._ex(o._ec),n);var i=l._dc(m,h);var k=this._fa._ba(m,h);j=j._bd(k);o=o._bd(i)}return new Array(j,o)}}function _az(b){this._gh=new Array(256);this._gi=new Array(256);var a=1;for(var e=0;e<256;e++){this._gh[e]=a;a<<=1;if(a>=256){a^=b}}for(var e=0;e<255;e++){this._gi[this._gh[e]]=e}var d=new Array(1);d[0]=0;this.zero=new _bp(this,new Array(d));var c=new Array(1);c[0]=1;this.one=new _bp(this,new Array(c));this.__defineGetter__("Zero",function(){return this.zero});this.__defineGetter__("One",function(){return this.one});this._ba=function(j,f){if(j<0){throw"bad arguments"}if(f==0){return this.zero}var h=new Array(j+1);for(var g=0;g-1){a=[{sourceId:f.deviceId}]}}console.log(f.kind+": "+f.label+" id = "+f.deviceId)})})}catch(b){console.log(b)}}else{console.log("no navigator.mediaDevices.enumerateDevices")}if(d.getUserMedia){d.getUserMedia({video:a,audio:false},qrcode.vidSuccess,qrcode.vidError)}else{if(d.webkitGetUserMedia){qrcode.webkit=true;d.webkitGetUserMedia({video:a,audio:false},qrcode.vidSuccess,qrcode.vidError)}else{if(d.mozGetUserMedia){qrcode.moz=true;d.mozGetUserMedia({video:a,audio:false},qrcode.vidSuccess,qrcode.vidError)}}}};qrcode.decode=function(d){if(arguments.length==0){if(qrcode.canvas_qr2){var b=qrcode.canvas_qr2;var a=qrcode.qrcontext2}else{var b=document.getElementById("qr-canvas");var a=b.getContext("2d")}qrcode.width=b.width;qrcode.height=b.height;qrcode.imagedata=a.getImageData(0,0,qrcode.width,qrcode.height);qrcode.result=qrcode.process(a);if(qrcode.callback!=null){qrcode.callback(qrcode.result)}return qrcode.result}else{var c=new Image();c.crossOrigin="Anonymous";c.onload=function(){var g=document.getElementById("out-canvas");if(g!=null){var j=g.getContext("2d");j.clearRect(0,0,320,240);j.drawImage(c,0,0,320,240)}var i=document.createElement("canvas");var h=i.getContext("2d");var f=c.height;var l=c.width;if(c.width*c.height>qrcode.maxImgSize){var k=c.width/c.height;f=Math.sqrt(qrcode.maxImgSize/k);l=k*f}i.width=l;i.height=f;h.drawImage(c,0,0,i.width,i.height);qrcode.width=i.width;qrcode.height=i.height;try{qrcode.imagedata=h.getImageData(0,0,i.width,i.height)}catch(m){qrcode.result="Cross domain image reading not supported in your browser! Save it to your computer then drag and drop the file!";if(qrcode.callback!=null){qrcode.callback(qrcode.result)}return}try{qrcode.result=qrcode.process(h)}catch(m){console.log(m);qrcode.result="error decoding QR Code"}if(qrcode.callback!=null){qrcode.callback(qrcode.result)}};c.onerror=function(){if(qrcode.callback!=null){qrcode.callback("Failed to load the image")}};c.src=d}};qrcode.isUrl=function(a){var b=/(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?/;return b.test(a)};qrcode.decode_url=function(b){var d="";try{d=escape(b)}catch(c){console.log(c);d=b}var a="";try{a=decodeURIComponent(d)}catch(c){console.log(c);a=d}return a};qrcode.decode_utf8=function(a){if(qrcode.isUrl(a)){return qrcode.decode_url(a)}else{return a}};qrcode.process=function(q){var a=new Date().getTime();var c=qrcode.grayScaleToBitmap(qrcode.grayscale());if(qrcode.debug){for(var m=0;mf[a][o][1]){f[a][o][1]=h}}}}}var m=new Array(c);for(var b=0;b=0){return a>>b}else{return(a>>b)+(2<<~b)}}var _gf=3;var _eh=57;var _el=8;var _eg=2;qrcode._er=function(c){function b(m,k){var n=m.X-k.X;var l=m.Y-k.Y;return Math.sqrt((n*n+l*l))}function d(k,o,n){var m=o.x;var l=o.y;return((n.x-m)*(k.y-l))-((n.y-l)*(k.x-m))}var i=b(c[0],c[1]);var f=b(c[1],c[2]);var e=b(c[0],c[2]);var a,j,h;if(f>=i&&f>=e){j=c[0];a=c[1];h=c[2]}else{if(e>=f&&e>=i){j=c[1];a=c[0];h=c[2]}else{j=c[2];a=c[0];h=c[1]}}if(d(a,j,h)<0){var g=a;a=h;h=g}c[0]=a;c[1]=j;c[2]=h};function _cz(c,a,b){this.x=c;this.y=a;this.count=1;this._aj=b;this.__defineGetter__("_ei",function(){return this._aj});this.__defineGetter__("Count",function(){return this.count});this.__defineGetter__("X",function(){return this.x});this.__defineGetter__("Y",function(){return this.y});this._ek=function(){this.count++};this._ev=function(f,e,d){if(Math.abs(e-this.y)<=f&&Math.abs(d-this.x)<=f){var g=Math.abs(f-this._aj);return g<=1||g/this._aj<=1}return false}}function _es(a){this._go=a[0];this._gu=a[1];this._gr=a[2];this.__defineGetter__("_gp",function(){return this._go});this.__defineGetter__("_gq",function(){return this._gu});this.__defineGetter__("_gs",function(){return this._gr})}function _cc(){this.image=null;this._cv=[];this._ge=false;this._al=new Array(0,0,0,0,0);this._am=null;this.__defineGetter__("_da",function(){this._al[0]=0;this._al[1]=0;this._al[2]=0;this._al[3]=0;this._al[4]=0;return this._al});this._ao=function(f){var b=0;for(var d=0;d<5;d++){var e=f[d];if(e==0){return false}b+=e}if(b<7){return false}var c=Math.floor((b<<_el)/7);var a=Math.floor(c/2);return Math.abs(c-(f[0]<<_el))=0&&c[j+f*qrcode.width]){b[2]++;f--}if(f<0){return NaN}while(f>=0&&!c[j+f*qrcode.width]&&b[1]<=d){b[1]++;f--}if(f<0||b[1]>d){return NaN}while(f>=0&&c[j+f*qrcode.width]&&b[0]<=d){b[0]++;f--}if(b[0]>d){return NaN}f=a+1;while(f=d){return NaN}while(f=d){return NaN}var e=b[0]+b[1]+b[2]+b[3]+b[4];if(5*Math.abs(e-g)>=2*g){return NaN}return this._ao(b)?this._an(b,f):NaN};this._ej=function(b,a,e,h){var d=this.image;var i=qrcode.width;var c=this._da;var g=b;while(g>=0&&d[g+a*qrcode.width]){c[2]++;g--}if(g<0){return NaN}while(g>=0&&!d[g+a*qrcode.width]&&c[1]<=e){c[1]++;g--}if(g<0||c[1]>e){return NaN}while(g>=0&&d[g+a*qrcode.width]&&c[0]<=e){c[0]++;g--}if(c[0]>e){return NaN}g=b+1;while(g=e){return NaN}while(g=e){return NaN}var f=c[0]+c[1]+c[2]+c[3]+c[4];if(5*Math.abs(f-h)>=h){return NaN}return this._ao(c)?this._an(c,g):NaN};this._cu=function(c,f,e){var d=c[0]+c[1]+c[2]+c[3]+c[4];var n=this._an(c,e);var b=this._ap(f,Math.floor(n),c[2],d);if(!isNaN(b)){n=this._ej(Math.floor(n),Math.floor(b),c[2],d);if(!isNaN(n)){var l=d/7;var m=false;var h=this._cv.length;for(var g=0;g3){var b=0;var j=0;for(var d=0;d=0;d--){var f=this._cv[d];if(Math.abs(f._ei-a)>c){this._cv.splice(d,1)}}}if(this._cv.length>3){this._cv.sort(function(k,i){if(k.count>i.count){return -1}if(k.count=_eg){if(c==null){c=a}else{this._ge=true;return Math.floor((Math.abs(c.X-a.X)-Math.abs(c.Y-a.Y))/2)}}}return 0};this._cx=function(){var g=0;var c=0;var a=this._cv.length;for(var d=0;d=_eg){g++;c+=f._ei}}if(g<3){return false}var e=c/a;var b=0;for(var d=0;dd[2]){h+=m-d[2]-a;f=k-1}}}else{do{f++}while(f=h){return false}}return true};this._ap=function(h,q,l,o){var k=this.image;var p=qrcode.height;var j=this._al;j[0]=0;j[1]=0;j[2]=0;var n=h;while(n>=0&&k[q+n*qrcode.width]&&j[1]<=l){j[1]++;n--}if(n<0||j[1]>l){return NaN}while(n>=0&&!k[q+n*qrcode.width]&&j[0]<=l){j[0]++;n--}if(j[0]>l){return NaN}n=h+1;while(nl){return NaN}while(nl){return NaN}var m=j[0]+j[1]+j[2];if(5*Math.abs(m-o)>=2*o){return NaN}return this._ao(j)?this._an(j,n):NaN};this._cu=function(l,o,n){var m=l[0]+l[1]+l[2];var t=this._an(l,n);var k=this._ap(o,Math.floor(t),2*l[1],m);if(!isNaN(k)){var s=(l[0]+l[1]+l[2])/3;var q=this._cv.length;for(var p=0;p>1);var m=new Array(0,0,0);for(var k=0;k>1):-((k+1)>>1));m[0]=0;m[1]=0;m[2]=0;var n=p;while(n=10&&a<=26){this.dataLengthMode=1}else{if(a>=27&&a<=40){this.dataLengthMode=2}}}this._gd=function(f){var k=0;if(f>(this._cw-f+1);this._cw-=f;return k}else{if(f>(8-(f-(this._cw+1))));this._cw=this._cw-f%8;if(this._cw<0){this._cw=8+this._cw}return k}else{if(f>(8-(f-(this._cw+1+8)));k=g+d+l;this._cw=this._cw-(f-8)%8;if(this._cw<0){this._cw=8+this._cw}return k}else{return 0}}}};this.NextMode=function(){if((this._ed>this.blocks.length-this._en-2)){return 0}else{return this._gd(4)}};this.getDataLength=function(d){var e=0;while(true){if((d>>e)==1){break}e++}return this._gd(qrcode._eo[this.dataLengthMode][e])};this.getRomanAndFigureString=function(h){var f=h;var g=0;var j="";var d=new Array("0","1","2","3","4","5","6","7","8","9","A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z"," ","$","%","*","+","-",".","/",":");do{if(f>1){g=this._gd(11);var i=Math.floor(g/45);var e=g%45;j+=d[i];j+=d[e];f-=2}else{if(f==1){g=this._gd(6);j+=d[g];f-=1}}}while(f>0);return j};this.getFigureString=function(f){var d=f;var e=0;var g="";do{if(d>=3){e=this._gd(10);if(e<100){g+="0"}if(e<10){g+="0"}d-=3}else{if(d==2){e=this._gd(7);if(e<10){g+="0"}d-=2}else{if(d==1){e=this._gd(4);d-=1}}}g+=e}while(d>0);return g};this.get8bitByteArray=function(g){var e=g;var f=0;var d=new Array();do{f=this._gd(8);d.push(f);e--}while(e>0);return d};this.getKanjiString=function(j){var g=j;var i=0;var h="";do{i=this._gd(13);var e=i%192;var f=i/192;var k=(f<<8)+e;var d=0;if(k+33088<=40956){d=k+33088}else{d=k+49472}h+=String.fromCharCode(d);g--}while(g>0);return h};this.parseECIValue=function(){var f=0;var e=this._gd(8);if((e&128)==0){f=e&127}if((e&192)==128){var d=this._gd(8);f=((e&63)<<8)|d}if((e&224)==192){var g=this._gd(8);f=((e&31)<<16)|g}return f};this.__defineGetter__("DataByte",function(){var h=new Array();var e=1;var f=2;var d=4;var n=7;var p=8;do{var l=this.NextMode();if(l==0){if(h.length>0){break}else{throw"Empty data block"}}if(l!=e&&l!=f&&l!=d&&l!=p&&l!=n){throw"Invalid mode: "+l+" in (block:"+this._ed+" bit:"+this._cw+")"}if(l==n){var o=this.parseECIValue()}else{var g=this.getDataLength(l);if(g<1){throw"Invalid data length: "+g}switch(l){case e:var m=this.getFigureString(g);var k=new Array(m.length);for(var i=0;i{var t={449:function(t,e,r){!function(t){"use strict";function e(t){return null==t}var n=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(t,e){t.__proto__=e}||function(t,e){for(var r in e)e.hasOwnProperty(r)&&(t[r]=e[r])};var i,o=function(t){function e(e){var r,n,i,o=this.constructor,s=t.call(this,e)||this;return Object.defineProperty(s,"name",{value:o.name,enumerable:!1}),r=s,n=o.prototype,(i=Object.setPrototypeOf)?i(r,n):r.__proto__=n,function(t,e){void 0===e&&(e=t.constructor);var r=Error.captureStackTrace;r&&r(t,e)}(s),s}return function(t,e){function r(){this.constructor=t}n(t,e),t.prototype=null===e?Object.create(e):(r.prototype=e.prototype,new r)}(e,t),e}(Error);class s extends o{constructor(t=undefined){super(t),this.message=t}getKind(){return this.constructor.kind}}s.kind="Exception";class a extends s{}a.kind="ArgumentException";class c extends s{}c.kind="IllegalArgumentException";class l{constructor(t){if(this.binarizer=t,null===t)throw new c("Binarizer must be non-null.")}getWidth(){return this.binarizer.getWidth()}getHeight(){return this.binarizer.getHeight()}getBlackRow(t,e){return this.binarizer.getBlackRow(t,e)}getBlackMatrix(){return null!==this.matrix&&void 0!==this.matrix||(this.matrix=this.binarizer.getBlackMatrix()),this.matrix}isCropSupported(){return this.binarizer.getLuminanceSource().isCropSupported()}crop(t,e,r,n){const i=this.binarizer.getLuminanceSource().crop(t,e,r,n);return new l(this.binarizer.createBinarizer(i))}isRotateSupported(){return this.binarizer.getLuminanceSource().isRotateSupported()}rotateCounterClockwise(){const t=this.binarizer.getLuminanceSource().rotateCounterClockwise();return new l(this.binarizer.createBinarizer(t))}rotateCounterClockwise45(){const t=this.binarizer.getLuminanceSource().rotateCounterClockwise45();return new l(this.binarizer.createBinarizer(t))}toString(){try{return this.getBlackMatrix().toString()}catch(t){return""}}}class h extends s{static getChecksumInstance(){return new h}}h.kind="ChecksumException";class u{constructor(t){this.source=t}getLuminanceSource(){return this.source}getWidth(){return this.source.getWidth()}getHeight(){return this.source.getHeight()}}class d{static arraycopy(t,e,r,n,i){for(;i--;)r[n++]=t[e++]}static currentTimeMillis(){return Date.now()}}class f extends s{}f.kind="IndexOutOfBoundsException";class g extends f{constructor(t=undefined,e=undefined){super(e),this.index=t,this.message=e}}g.kind="ArrayIndexOutOfBoundsException";class w{static fill(t,e){for(let r=0,n=t.length;rr)throw new c("fromIndex("+e+") > toIndex("+r+")");if(e<0)throw new g(e);if(r>t)throw new g(r)}static asList(...t){return t}static create(t,e,r){return Array.from({length:t}).map((t=>Array.from({length:e}).fill(r)))}static createInt32Array(t,e,r){return Array.from({length:t}).map((t=>Int32Array.from({length:e}).fill(r)))}static equals(t,e){if(!t)return!1;if(!e)return!1;if(!t.length)return!1;if(!e.length)return!1;if(t.length!==e.length)return!1;for(let r=0,n=t.length;r>1,s=r(e,t[o]);if(s>0)n=o+1;else{if(!(s<0))return o;i=o-1}}return-n-1}static numberComparator(t,e){return t-e}}class m{static numberOfTrailingZeros(t){let e;if(0===t)return 32;let r=31;return e=t<<16,0!==e&&(r-=16,t=e),e=t<<8,0!==e&&(r-=8,t=e),e=t<<4,0!==e&&(r-=4,t=e),e=t<<2,0!==e&&(r-=2,t=e),r-(t<<1>>>31)}static numberOfLeadingZeros(t){if(0===t)return 32;let e=1;return t>>>16==0&&(e+=16,t<<=16),t>>>24==0&&(e+=8,t<<=8),t>>>28==0&&(e+=4,t<<=4),t>>>30==0&&(e+=2,t<<=2),e-=t>>>31,e}static toHexString(t){return t.toString(16)}static toBinaryString(t){return String(parseInt(String(t),2))}static bitCount(t){return t=(t=(858993459&(t-=t>>>1&1431655765))+(t>>>2&858993459))+(t>>>4)&252645135,63&(t+=t>>>8)+(t>>>16)}static truncDivision(t,e){return Math.trunc(t/e)}static parseInt(t,e=undefined){return parseInt(t,e)}}m.MIN_VALUE_32_BITS=-2147483648,m.MAX_VALUE=Number.MAX_SAFE_INTEGER;class p{constructor(t,e){void 0===t?(this.size=0,this.bits=new Int32Array(1)):(this.size=t,this.bits=null==e?p.makeArray(t):e)}getSize(){return this.size}getSizeInBytes(){return Math.floor((this.size+7)/8)}ensureCapacity(t){if(t>32*this.bits.length){const e=p.makeArray(t);d.arraycopy(this.bits,0,e,0,this.bits.length),this.bits=e}}get(t){return 0!=(this.bits[Math.floor(t/32)]&1<<(31&t))}set(t){this.bits[Math.floor(t/32)]|=1<<(31&t)}flip(t){this.bits[Math.floor(t/32)]^=1<<(31&t)}getNextSet(t){const e=this.size;if(t>=e)return e;const r=this.bits;let n=Math.floor(t/32),i=r[n];i&=~((1<<(31&t))-1);const o=r.length;for(;0===i;){if(++n===o)return e;i=r[n]}const s=32*n+m.numberOfTrailingZeros(i);return s>e?e:s}getNextUnset(t){const e=this.size;if(t>=e)return e;const r=this.bits;let n=Math.floor(t/32),i=~r[n];i&=~((1<<(31&t))-1);const o=r.length;for(;0===i;){if(++n===o)return e;i=~r[n]}const s=32*n+m.numberOfTrailingZeros(i);return s>e?e:s}setBulk(t,e){this.bits[Math.floor(t/32)]=e}setRange(t,e){if(ethis.size)throw new c;if(e===t)return;e--;const r=Math.floor(t/32),n=Math.floor(e/32),i=this.bits;for(let o=r;o<=n;o++){const s=(2<<(or?0:31&t));i[o]|=s}}clear(){const t=this.bits.length,e=this.bits;for(let r=0;rthis.size)throw new c;if(e===t)return!0;e--;const n=Math.floor(t/32),i=Math.floor(e/32),o=this.bits;for(let s=n;s<=i;s++){const a=(2<<(sn?0:31&t))&4294967295;if((o[s]&a)!==(r?a:0))return!1}return!0}appendBit(t){this.ensureCapacity(this.size+1),t&&(this.bits[Math.floor(this.size/32)]|=1<<(31&this.size)),this.size++}appendBits(t,e){if(e<0||e>32)throw new c("Num bits must be between 0 and 32");this.ensureCapacity(this.size+e);for(let r=e;r>0;r--)this.appendBit(1==(t>>r-1&1))}appendBitArray(t){const e=t.size;this.ensureCapacity(this.size+e);for(let r=0;r>1&1431655765|(1431655765&r)<<1,r=r>>2&858993459|(858993459&r)<<2,r=r>>4&252645135|(252645135&r)<<4,r=r>>8&16711935|(16711935&r)<<8,r=r>>16&65535|(65535&r)<<16,t[e-i]=r}if(this.size!==32*r){const e=32*r-this.size;let n=t[0]>>>e;for(let i=1;i>>e}t[r-1]=n}this.bits=t}static makeArray(t){return new Int32Array(Math.floor((t+31)/32))}equals(t){if(!(t instanceof p))return!1;const e=t;return this.size===e.size&&w.equals(this.bits,e.bits)}hashCode(){return 31*this.size+w.hashCode(this.bits)}toString(){let t="";for(let e=0,r=this.size;e=900)throw new E("incorect value");const e=I.VALUES_TO_ECI.get(t);if(void 0===e)throw new E("incorect value");return e}static getCharacterSetECIByName(t){const e=I.NAME_TO_ECI.get(t);if(void 0===e)throw new E("incorect value");return e}equals(t){if(!(t instanceof I))return!1;const e=t;return this.getName()===e.getName()}}I.VALUE_IDENTIFIER_TO_ECI=new Map,I.VALUES_TO_ECI=new Map,I.NAME_TO_ECI=new Map,I.Cp437=new I(A.Cp437,Int32Array.from([0,2]),"Cp437"),I.ISO8859_1=new I(A.ISO8859_1,Int32Array.from([1,3]),"ISO-8859-1","ISO88591","ISO8859_1"),I.ISO8859_2=new I(A.ISO8859_2,4,"ISO-8859-2","ISO88592","ISO8859_2"),I.ISO8859_3=new I(A.ISO8859_3,5,"ISO-8859-3","ISO88593","ISO8859_3"),I.ISO8859_4=new I(A.ISO8859_4,6,"ISO-8859-4","ISO88594","ISO8859_4"),I.ISO8859_5=new I(A.ISO8859_5,7,"ISO-8859-5","ISO88595","ISO8859_5"),I.ISO8859_6=new I(A.ISO8859_6,8,"ISO-8859-6","ISO88596","ISO8859_6"),I.ISO8859_7=new I(A.ISO8859_7,9,"ISO-8859-7","ISO88597","ISO8859_7"),I.ISO8859_8=new I(A.ISO8859_8,10,"ISO-8859-8","ISO88598","ISO8859_8"),I.ISO8859_9=new I(A.ISO8859_9,11,"ISO-8859-9","ISO88599","ISO8859_9"),I.ISO8859_10=new I(A.ISO8859_10,12,"ISO-8859-10","ISO885910","ISO8859_10"),I.ISO8859_11=new I(A.ISO8859_11,13,"ISO-8859-11","ISO885911","ISO8859_11"),I.ISO8859_13=new I(A.ISO8859_13,15,"ISO-8859-13","ISO885913","ISO8859_13"),I.ISO8859_14=new I(A.ISO8859_14,16,"ISO-8859-14","ISO885914","ISO8859_14"),I.ISO8859_15=new I(A.ISO8859_15,17,"ISO-8859-15","ISO885915","ISO8859_15"),I.ISO8859_16=new I(A.ISO8859_16,18,"ISO-8859-16","ISO885916","ISO8859_16"),I.SJIS=new I(A.SJIS,20,"SJIS","Shift_JIS"),I.Cp1250=new I(A.Cp1250,21,"Cp1250","windows-1250"),I.Cp1251=new I(A.Cp1251,22,"Cp1251","windows-1251"),I.Cp1252=new I(A.Cp1252,23,"Cp1252","windows-1252"),I.Cp1256=new I(A.Cp1256,24,"Cp1256","windows-1256"),I.UnicodeBigUnmarked=new I(A.UnicodeBigUnmarked,25,"UnicodeBigUnmarked","UTF-16BE","UnicodeBig"),I.UTF8=new I(A.UTF8,26,"UTF8","UTF-8"),I.ASCII=new I(A.ASCII,Int32Array.from([27,170]),"ASCII","US-ASCII"),I.Big5=new I(A.Big5,28,"Big5"),I.GB18030=new I(A.GB18030,29,"GB18030","GB2312","EUC_CN","GBK"),I.EUC_KR=new I(A.EUC_KR,30,"EUC_KR","EUC-KR");class S extends s{}S.kind="UnsupportedOperationException";class _{static decode(t,e){const r=this.encodingName(e);return this.customDecoder?this.customDecoder(t,r):"undefined"==typeof TextDecoder||this.shouldDecodeOnFallback(r)?this.decodeFallback(t,r):new TextDecoder(r).decode(t)}static shouldDecodeOnFallback(t){return!_.isBrowser()&&"ISO-8859-1"===t}static encode(t,e){const r=this.encodingName(e);return this.customEncoder?this.customEncoder(t,r):"undefined"==typeof TextEncoder?this.encodeFallback(t):(new TextEncoder).encode(t)}static isBrowser(){return"undefined"!=typeof window&&"[object Window]"==={}.toString.call(window)}static encodingName(t){return"string"==typeof t?t:t.getName()}static encodingCharacterSet(t){return t instanceof I?t:I.getCharacterSetECIByName(t)}static decodeFallback(t,e){const r=this.encodingCharacterSet(e);if(_.isDecodeFallbackSupported(r)){let e="";for(let r=0,n=t.length;r3&&239===t[0]&&187===t[1]&&191===t[2];for(let e=0;e0?0==(128&r)?o=!1:s--:0!=(128&r)&&(0==(64&r)?o=!1:(s++,0==(32&r)?a++:(s++,0==(16&r)?c++:(s++,0==(8&r)?l++:o=!1))))),n&&(r>127&&r<160?n=!1:r>159&&(r<192||215===r||247===r)&&m++),i&&(h>0?r<64||127===r||r>252?i=!1:h--:128===r||160===r||r>239?i=!1:r>160&&r<224?(u++,f=0,d++,d>g&&(g=d)):r>127?(h++,d=0,f++,f>w&&(w=f)):(d=0,f=0))}return o&&s>0&&(o=!1),i&&h>0&&(i=!1),o&&(p||a+c+l>0)?T.UTF8:i&&(T.ASSUME_SHIFT_JIS||g>=3||w>=3)?T.SHIFT_JIS:n&&i?2===g&&2===u||10*m>=r?T.SHIFT_JIS:T.ISO88591:n?T.ISO88591:i?T.SHIFT_JIS:o?T.UTF8:T.PLATFORM_DEFAULT_ENCODING}static format(t,...e){let r=-1;return t.replace(/%(-)?(0?[0-9]+)?([.][0-9]+)?([#][0-9]+)?([scfpexd%])/g,(function(t,n,i,o,s,a){if("%%"===t)return"%";if(void 0===e[++r])return;t=o?parseInt(o.substr(1)):void 0;let c,l=s?parseInt(s.substr(1)):void 0;switch(a){case"s":c=e[r];break;case"c":c=e[r][0];break;case"f":c=parseFloat(e[r]).toFixed(t);break;case"p":c=parseFloat(e[r]).toPrecision(t);break;case"e":c=parseFloat(e[r]).toExponential(t);break;case"x":c=parseInt(e[r]).toString(l||16);break;case"d":c=parseFloat(parseInt(e[r],l||10).toPrecision(t)).toFixed(0)}c="object"==typeof c?JSON.stringify(c):(+c).toString(l);let h=parseInt(i),u=i&&i[0]+""=="0"?"0":" ";for(;c.lengtho){if(-1===s)s=i-o;else if(i-o!==s)throw new c("row lengths do not match");o=i,a++}l++}else if(t.substring(l,l+e.length)===e)l+=e.length,n[i]=!0,i++;else{if(t.substring(l,l+r.length)!==r)throw new c("illegal character encountered: "+t.substring(l));l+=r.length,n[i]=!1,i++}if(i>o){if(-1===s)s=i-o;else if(i-o!==s)throw new c("row lengths do not match");a++}const h=new N(s,a);for(let t=0;t>>(31&t)&1)}set(t,e){const r=e*this.rowSize+Math.floor(t/32);this.bits[r]|=1<<(31&t)&4294967295}unset(t,e){const r=e*this.rowSize+Math.floor(t/32);this.bits[r]&=~(1<<(31&t)&4294967295)}flip(t,e){const r=e*this.rowSize+Math.floor(t/32);this.bits[r]^=1<<(31&t)&4294967295}xor(t){if(this.width!==t.getWidth()||this.height!==t.getHeight()||this.rowSize!==t.getRowSize())throw new c("input matrix dimensions do not match");const e=new p(Math.floor(this.width/32)+1),r=this.rowSize,n=this.bits;for(let i=0,o=this.height;ithis.height||i>this.width)throw new c("The region must fit inside the matrix");const s=this.rowSize,a=this.bits;for(let r=e;ra&&(a=t),32*es){let t=31;for(;c>>>t==0;)t--;32*e+t>s&&(s=32*e+t)}}}return s=0&&0===e[r];)r--;if(r<0)return null;const n=Math.floor(r/t);let i=32*Math.floor(r%t);const o=e[r];let s=31;for(;o>>>s==0;)s--;return i+=s,Int32Array.from([i,n])}getWidth(){return this.width}getHeight(){return this.height}getRowSize(){return this.rowSize}equals(t){if(!(t instanceof N))return!1;const e=t;return this.width===e.width&&this.height===e.height&&this.rowSize===e.rowSize&&w.equals(this.bits,e.bits)}hashCode(){let t=this.width;return t=31*t+this.width,t=31*t+this.height,t=31*t+this.rowSize,t=31*t+w.hashCode(this.bits),t}toString(t="X ",e=" ",r="\n"){return this.buildToString(t,e,r)}buildToString(t,e,r){let n=new y;for(let i=0,o=this.height;i>M.LUMINANCE_SHIFT]++;const s=M.estimateBlackPoint(o);if(n<3)for(let t=0;t>M.LUMINANCE_SHIFT]++}const o=M.estimateBlackPoint(i),s=t.getMatrix();for(let t=0;ti&&(n=o,i=t[o]),t[o]>r&&(r=t[o]);let o=0,s=0;for(let r=0;rs&&(o=r,s=i)}if(n>o){const t=n;n=o,o=t}if(o-n<=e/16)throw new D;let a=o-1,c=-1;for(let e=o-1;e>n;e--){const i=e-n,s=i*i*(o-e)*(r-t[e]);s>c&&(a=e,c=s)}return a<=R.MINIMUM_DIMENSION&&r>=R.MINIMUM_DIMENSION){const n=t.getMatrix();let i=e>>R.BLOCK_SIZE_POWER;0!=(e&R.BLOCK_SIZE_MASK)&&i++;let o=r>>R.BLOCK_SIZE_POWER;0!=(r&R.BLOCK_SIZE_MASK)&&o++;const s=R.calculateBlackPoints(n,i,o,e,r),a=new N(e,r);R.calculateThresholdForBlock(n,i,o,e,r,s,a),this.matrix=a}else this.matrix=super.getBlackMatrix();return this.matrix}createBinarizer(t){return new R(t)}static calculateThresholdForBlock(t,e,r,n,i,o,s){const a=i-R.BLOCK_SIZE,c=n-R.BLOCK_SIZE;for(let i=0;ia&&(l=a);const h=R.cap(i,2,r-3);for(let r=0;rc&&(i=c);const a=R.cap(r,2,e-3);let u=0;for(let t=-2;t<=2;t++){const e=o[h+t];u+=e[a-2]+e[a-1]+e[a]+e[a+1]+e[a+2]}const d=u/25;R.thresholdBlock(t,i,l,d,n,s)}}}static cap(t,e,r){return tr?r:t}static thresholdBlock(t,e,r,n,i,o){for(let s=0,a=r*i+e;so&&(r=o);for(let o=0;os&&(e=s);let c=0,l=255,h=0;for(let i=0,o=r*n+e;ih&&(h=r)}if(h-l>R.MIN_DYNAMIC_RANGE)for(i++,o+=n;i>2*R.BLOCK_SIZE_POWER;if(h-l<=R.MIN_DYNAMIC_RANGE&&(u=l/2,i>0&&o>0)){const t=(a[i-1][o]+2*a[i][o-1]+a[i-1][o-1])/4;l>10,n[r]=i}return n}getRow(t,e){if(t<0||t>=this.getHeight())throw new c("Requested row is outside the image: "+t);const r=this.getWidth(),n=t*r;return null===e?e=this.buffer.slice(n,n+r):(e.lengthnew L(t.deviceId,t.label)))}))}findDeviceById(t){return v(this,void 0,void 0,(function*(){const e=yield this.listVideoInputDevices();return e?e.find((e=>e.deviceId===t)):null}))}decodeFromInputVideoDevice(t,e){return v(this,void 0,void 0,(function*(){return yield this.decodeOnceFromVideoDevice(t,e)}))}decodeOnceFromVideoDevice(t,e){return v(this,void 0,void 0,(function*(){let r;this.reset(),r=t?{deviceId:{exact:t}}:{facingMode:"environment"};const n={video:r};return yield this.decodeOnceFromConstraints(n,e)}))}decodeOnceFromConstraints(t,e){return v(this,void 0,void 0,(function*(){const r=yield navigator.mediaDevices.getUserMedia(t);return yield this.decodeOnceFromStream(r,e)}))}decodeOnceFromStream(t,e){return v(this,void 0,void 0,(function*(){this.reset();const r=yield this.attachStreamToVideo(t,e);return yield this.decodeOnce(r)}))}decodeFromInputVideoDeviceContinuously(t,e,r){return v(this,void 0,void 0,(function*(){return yield this.decodeFromVideoDevice(t,e,r)}))}decodeFromVideoDevice(t,e,r){return v(this,void 0,void 0,(function*(){let n;n=t?{deviceId:{exact:t}}:{facingMode:"environment"};const i={video:n};return yield this.decodeFromConstraints(i,e,r)}))}decodeFromConstraints(t,e,r){return v(this,void 0,void 0,(function*(){const n=yield navigator.mediaDevices.getUserMedia(t);return yield this.decodeFromStream(n,e,r)}))}decodeFromStream(t,e,r){return v(this,void 0,void 0,(function*(){this.reset();const n=yield this.attachStreamToVideo(t,e);return yield this.decodeContinuously(n,r)}))}stopAsyncDecode(){this._stopAsyncDecode=!0}stopContinuousDecode(){this._stopContinuousDecode=!0}attachStreamToVideo(t,e){return v(this,void 0,void 0,(function*(){const r=this.prepareVideoElement(e);return this.addVideoSource(r,t),this.videoElement=r,this.stream=t,yield this.playVideoOnLoadAsync(r),r}))}playVideoOnLoadAsync(t){return new Promise(((e,r)=>this.playVideoOnLoad(t,(()=>e()))))}playVideoOnLoad(t,e){this.videoEndedListener=()=>this.stopStreams(),this.videoCanPlayListener=()=>this.tryPlayVideo(t),t.addEventListener("ended",this.videoEndedListener),t.addEventListener("canplay",this.videoCanPlayListener),t.addEventListener("playing",e),this.tryPlayVideo(t)}isVideoPlaying(t){return t.currentTime>0&&!t.paused&&!t.ended&&t.readyState>2}tryPlayVideo(t){return v(this,void 0,void 0,(function*(){if(this.isVideoPlaying(t))console.warn("Trying to play video that is already playing.");else try{yield t.play()}catch(t){console.warn("It was not possible to play the video.")}}))}getMediaElement(t,e){const r=document.getElementById(t);if(!r)throw new a(`element with id '${t}' not found`);if(r.nodeName.toLowerCase()!==e.toLowerCase())throw new a(`element with id '${t}' must be an ${e} element`);return r}decodeFromImage(t,e){if(!t&&!e)throw new a("either imageElement with a src set or an url must be provided");return e&&!t?this.decodeFromImageUrl(e):this.decodeFromImageElement(t)}decodeFromVideo(t,e){if(!t&&!e)throw new a("Either an element with a src set or an URL must be provided");return e&&!t?this.decodeFromVideoUrl(e):this.decodeFromVideoElement(t)}decodeFromVideoContinuously(t,e,r){if(void 0===t&&void 0===e)throw new a("Either an element with a src set or an URL must be provided");return e&&!t?this.decodeFromVideoUrlContinuously(e,r):this.decodeFromVideoElementContinuously(t,r)}decodeFromImageElement(t){if(!t)throw new a("An image element must be provided.");this.reset();const e=this.prepareImageElement(t);let r;return this.imageElement=e,r=this.isImageLoaded(e)?this.decodeOnce(e,!1,!0):this._decodeOnLoadImage(e),r}decodeFromVideoElement(t){const e=this._decodeFromVideoElementSetup(t);return this._decodeOnLoadVideo(e)}decodeFromVideoElementContinuously(t,e){const r=this._decodeFromVideoElementSetup(t);return this._decodeOnLoadVideoContinuously(r,e)}_decodeFromVideoElementSetup(t){if(!t)throw new a("A video element must be provided.");this.reset();const e=this.prepareVideoElement(t);return this.videoElement=e,e}decodeFromImageUrl(t){if(!t)throw new a("An URL must be provided.");this.reset();const e=this.prepareImageElement();this.imageElement=e;const r=this._decodeOnLoadImage(e);return e.src=t,r}decodeFromVideoUrl(t){if(!t)throw new a("An URL must be provided.");this.reset();const e=this.prepareVideoElement(),r=this.decodeFromVideoElement(e);return e.src=t,r}decodeFromVideoUrlContinuously(t,e){if(!t)throw new a("An URL must be provided.");this.reset();const r=this.prepareVideoElement(),n=this.decodeFromVideoElementContinuously(r,e);return r.src=t,n}_decodeOnLoadImage(t){return new Promise(((e,r)=>{this.imageLoadedListener=()=>this.decodeOnce(t,!1,!0).then(e,r),t.addEventListener("load",this.imageLoadedListener)}))}_decodeOnLoadVideo(t){return v(this,void 0,void 0,(function*(){return yield this.playVideoOnLoadAsync(t),yield this.decodeOnce(t)}))}_decodeOnLoadVideoContinuously(t,e){return v(this,void 0,void 0,(function*(){yield this.playVideoOnLoadAsync(t),this.decodeContinuously(t,e)}))}isImageLoaded(t){return!!t.complete&&0!==t.naturalWidth}prepareImageElement(t){let e;return void 0===t&&(e=document.createElement("img"),e.width=200,e.height=200),"string"==typeof t&&(e=this.getMediaElement(t,"img")),t instanceof HTMLImageElement&&(e=t),e}prepareVideoElement(t){let e;return t||"undefined"==typeof document||(e=document.createElement("video"),e.width=200,e.height=200),"string"==typeof t&&(e=this.getMediaElement(t,"video")),t instanceof HTMLVideoElement&&(e=t),e.setAttribute("autoplay","true"),e.setAttribute("muted","true"),e.setAttribute("playsinline","true"),e}decodeOnce(t,e=!0,r=!0){this._stopAsyncDecode=!1;const n=(i,o)=>{if(this._stopAsyncDecode)return o(new D("Video stream has ended before any code could be detected.")),void(this._stopAsyncDecode=void 0);try{i(this.decode(t))}catch(t){if(e&&t instanceof D||(t instanceof h||t instanceof E)&&r)return setTimeout(n,this._timeBetweenDecodingAttempts,i,o);o(t)}};return new Promise(((t,e)=>n(t,e)))}decodeContinuously(t,e){this._stopContinuousDecode=!1;const r=()=>{if(this._stopContinuousDecode)this._stopContinuousDecode=void 0;else try{const n=this.decode(t);e(n,null),setTimeout(r,this.timeBetweenScansMillis)}catch(t){e(null,t),(t instanceof h||t instanceof E||t instanceof D)&&setTimeout(r,this._timeBetweenDecodingAttempts)}};r()}decode(t){const e=this.createBinaryBitmap(t);return this.decodeBitmap(e)}_isHTMLVideoElement(t){return 0!==t.videoWidth}drawFrameOnCanvas(t,e,r){e||(e={sx:0,sy:0,sWidth:t.videoWidth,sHeight:t.videoHeight,dx:0,dy:0,dWidth:t.videoWidth,dHeight:t.videoHeight}),r||(r=this.captureCanvasContext),r.drawImage(t,e.sx,e.sy,e.sWidth,e.sHeight,e.dx,e.dy,e.dWidth,e.dHeight)}drawImageOnCanvas(t,e,r=this.captureCanvasContext){e||(e={sx:0,sy:0,sWidth:t.naturalWidth,sHeight:t.naturalHeight,dx:0,dy:0,dWidth:t.naturalWidth,dHeight:t.naturalHeight}),r||(r=this.captureCanvasContext),r.drawImage(t,e.sx,e.sy,e.sWidth,e.sHeight,e.dx,e.dy,e.dWidth,e.dHeight)}createBinaryBitmap(t){this.getCaptureCanvasContext(t),this._isHTMLVideoElement(t)?this.drawFrameOnCanvas(t):this.drawImageOnCanvas(t);const e=this.getCaptureCanvas(t),r=new B(e),n=new R(r);return new l(n)}getCaptureCanvasContext(t){if(!this.captureCanvasContext){const e=this.getCaptureCanvas(t).getContext("2d");this.captureCanvasContext=e}return this.captureCanvasContext}getCaptureCanvas(t){if(!this.captureCanvas){const e=this.createCaptureCanvas(t);this.captureCanvas=e}return this.captureCanvas}decodeBitmap(t){return this.reader.decode(t,this._hints)}createCaptureCanvas(t){if("undefined"==typeof document)return this._destroyCaptureCanvas(),null;const e=document.createElement("canvas");let r,n;return void 0!==t&&(t instanceof HTMLVideoElement?(r=t.videoWidth,n=t.videoHeight):t instanceof HTMLImageElement&&(r=t.naturalWidth||t.width,n=t.naturalHeight||t.height)),e.style.width=r+"px",e.style.height=n+"px",e.width=r,e.height=n,e}stopStreams(){this.stream&&(this.stream.getVideoTracks().forEach((t=>t.stop())),this.stream=void 0),!1===this._stopAsyncDecode&&this.stopAsyncDecode(),!1===this._stopContinuousDecode&&this.stopContinuousDecode()}reset(){this.stopStreams(),this._destroyVideoElement(),this._destroyImageElement(),this._destroyCaptureCanvas()}_destroyVideoElement(){this.videoElement&&(void 0!==this.videoEndedListener&&this.videoElement.removeEventListener("ended",this.videoEndedListener),void 0!==this.videoPlayingEventListener&&this.videoElement.removeEventListener("playing",this.videoPlayingEventListener),void 0!==this.videoCanPlayListener&&this.videoElement.removeEventListener("loadedmetadata",this.videoCanPlayListener),this.cleanVideoSource(this.videoElement),this.videoElement=void 0)}_destroyImageElement(){this.imageElement&&(void 0!==this.imageLoadedListener&&this.imageElement.removeEventListener("load",this.imageLoadedListener),this.imageElement.src=void 0,this.imageElement.removeAttribute("src"),this.imageElement=void 0)}_destroyCaptureCanvas(){this.captureCanvasContext=void 0,this.captureCanvas=void 0}addVideoSource(t,e){try{t.srcObject=e}catch(r){t.src=URL.createObjectURL(e)}}cleanVideoSource(t){try{t.srcObject=null}catch(e){t.src=""}this.videoElement.removeAttribute("src")}}class x{constructor(t,e,r=(null==e?0:8*e.length),n,i,o=d.currentTimeMillis()){this.text=t,this.rawBytes=e,this.numBits=r,this.resultPoints=n,this.format=i,this.timestamp=o,this.text=t,this.rawBytes=e,this.numBits=null==r?null==e?0:8*e.length:r,this.resultPoints=n,this.format=i,this.resultMetadata=null,this.timestamp=null==o?d.currentTimeMillis():o}getText(){return this.text}getRawBytes(){return this.rawBytes}getNumBits(){return this.numBits}getResultPoints(){return this.resultPoints}getBarcodeFormat(){return this.format}getResultMetadata(){return this.resultMetadata}putMetadata(t,e){null===this.resultMetadata&&(this.resultMetadata=new Map),this.resultMetadata.set(t,e)}putAllMetadata(t){null!==t&&(null===this.resultMetadata?this.resultMetadata=t:this.resultMetadata=new Map(t))}addResultPoints(t){const e=this.resultPoints;if(null===e)this.resultPoints=t;else if(null!==t&&t.length>0){const r=new Array(e.length+t.length);d.arraycopy(e,0,r,0,e.length),d.arraycopy(t,0,r,e.length,t.length),this.resultPoints=r}}getTimestamp(){return this.timestamp}toString(){return this.text}}!function(t){t[t.AZTEC=0]="AZTEC",t[t.CODABAR=1]="CODABAR",t[t.CODE_39=2]="CODE_39",t[t.CODE_93=3]="CODE_93",t[t.CODE_128=4]="CODE_128",t[t.DATA_MATRIX=5]="DATA_MATRIX",t[t.EAN_8=6]="EAN_8",t[t.EAN_13=7]="EAN_13",t[t.ITF=8]="ITF",t[t.MAXICODE=9]="MAXICODE",t[t.PDF_417=10]="PDF_417",t[t.QR_CODE=11]="QR_CODE",t[t.RSS_14=12]="RSS_14",t[t.RSS_EXPANDED=13]="RSS_EXPANDED",t[t.UPC_A=14]="UPC_A",t[t.UPC_E=15]="UPC_E",t[t.UPC_EAN_EXTENSION=16]="UPC_EAN_EXTENSION"}(P||(P={}));var k,U=P;!function(t){t[t.OTHER=0]="OTHER",t[t.ORIENTATION=1]="ORIENTATION",t[t.BYTE_SEGMENTS=2]="BYTE_SEGMENTS",t[t.ERROR_CORRECTION_LEVEL=3]="ERROR_CORRECTION_LEVEL",t[t.ISSUE_NUMBER=4]="ISSUE_NUMBER",t[t.SUGGESTED_PRICE=5]="SUGGESTED_PRICE",t[t.POSSIBLE_COUNTRY=6]="POSSIBLE_COUNTRY",t[t.UPC_EAN_EXTENSION=7]="UPC_EAN_EXTENSION",t[t.PDF417_EXTRA_METADATA=8]="PDF417_EXTRA_METADATA",t[t.STRUCTURED_APPEND_SEQUENCE=9]="STRUCTURED_APPEND_SEQUENCE",t[t.STRUCTURED_APPEND_PARITY=10]="STRUCTURED_APPEND_PARITY"}(k||(k={}));var H,V,z,G,Y,X,W=k;class j{constructor(t,e,r,n,i=-1,o=-1){this.rawBytes=t,this.text=e,this.byteSegments=r,this.ecLevel=n,this.structuredAppendSequenceNumber=i,this.structuredAppendParity=o,this.numBits=null==t?0:8*t.length}getRawBytes(){return this.rawBytes}getNumBits(){return this.numBits}setNumBits(t){this.numBits=t}getText(){return this.text}getByteSegments(){return this.byteSegments}getECLevel(){return this.ecLevel}getErrorsCorrected(){return this.errorsCorrected}setErrorsCorrected(t){this.errorsCorrected=t}getErasures(){return this.erasures}setErasures(t){this.erasures=t}getOther(){return this.other}setOther(t){this.other=t}hasStructuredAppend(){return this.structuredAppendParity>=0&&this.structuredAppendSequenceNumber>=0}getStructuredAppendParity(){return this.structuredAppendParity}getStructuredAppendSequenceNumber(){return this.structuredAppendSequenceNumber}}class Z{exp(t){return this.expTable[t]}log(t){if(0===t)throw new c;return this.logTable[t]}static addOrSubtract(t,e){return t^e}}class Q{constructor(t,e){if(0===e.length)throw new c;this.field=t;const r=e.length;if(r>1&&0===e[0]){let t=1;for(;tr.length){const t=e;e=r,r=t}let n=new Int32Array(r.length);const i=r.length-e.length;d.arraycopy(r,0,n,0,i);for(let t=i;t=t.getDegree()&&!n.isZero();){const i=n.getDegree()-t.getDegree(),s=e.multiply(n.getCoefficient(n.getDegree()),o),a=t.multiplyByMonomial(i,s),c=e.buildMonomial(i,s);r=r.addOrSubtract(c),n=n.addOrSubtract(a)}return[r,n]}toString(){let t="";for(let e=this.getDegree();e>=0;e--){let r=this.getCoefficient(e);if(0!==r){if(r<0?(t+=" - ",r=-r):t.length>0&&(t+=" + "),0===e||1!==r){const e=this.field.log(r);0===e?t+="1":1===e?t+="a":(t+="a^",t+=e)}0!==e&&(1===e?t+="x":(t+="x^",t+=e))}}return t}}class K extends s{}K.kind="ArithmeticException";class q extends Z{constructor(t,e,r){super(),this.primitive=t,this.size=e,this.generatorBase=r;const n=new Int32Array(e);let i=1;for(let r=0;r=e&&(i^=t,i&=e-1);this.expTable=n;const o=new Int32Array(e);for(let t=0;t=(r/2|0);){let t=i,e=s;if(i=o,s=a,i.isZero())throw new J("r_{i-1} was zero");o=t;let r=n.getZero();const c=i.getCoefficient(i.getDegree()),l=n.inverse(c);for(;o.getDegree()>=i.getDegree()&&!o.isZero();){const t=o.getDegree()-i.getDegree(),e=n.multiply(o.getCoefficient(o.getDegree()),l);r=r.addOrSubtract(n.buildMonomial(t,e)),o=o.addOrSubtract(i.multiplyByMonomial(t,e))}if(a=r.multiply(s).addOrSubtract(e),o.getDegree()>=i.getDegree())throw new $("Division algorithm failed to reduce polynomial?")}const c=a.getCoefficient(0);if(0===c)throw new J("sigmaTilde(0) was zero");const l=n.inverse(c);return[a.multiplyScalar(l),o.multiplyScalar(l)]}findErrorLocations(t){const e=t.getDegree();if(1===e)return Int32Array.from([t.getCoefficient(1)]);const r=new Int32Array(e);let n=0;const i=this.field;for(let o=1;o1,h,h+r-1),h+=r-1;else for(let t=r-1;t>=0;--t)l[h++]=0!=(e&1<=8?et.readCode(t,e,8):et.readCode(t,e,r)<<8-r}static convertBoolArrayToByteArray(t){let e=new Uint8Array((t.length+7)/8);for(let r=0;r","?","[","]","{","}","CTRL_UL"],et.DIGIT_TABLE=["CTRL_PS"," ","0","1","2","3","4","5","6","7","8","9",",",".","CTRL_UL","CTRL_US"];class rt{constructor(){}static round(t){return NaN===t?0:t<=Number.MIN_SAFE_INTEGER?Number.MIN_SAFE_INTEGER:t>=Number.MAX_SAFE_INTEGER?Number.MAX_SAFE_INTEGER:t+(t<0?-.5:.5)|0}static distance(t,e,r,n){const i=t-r,o=e-n;return Math.sqrt(i*i+o*o)}static sum(t){let e=0;for(let r=0,n=t.length;r!==n;r++)e+=t[r];return e}}class nt{static floatToIntBits(t){return t}}nt.MAX_VALUE=Number.MAX_SAFE_INTEGER;class it{constructor(t,e){this.x=t,this.y=e}getX(){return this.x}getY(){return this.y}equals(t){if(t instanceof it){const e=t;return this.x===e.x&&this.y===e.y}return!1}hashCode(){return 31*nt.floatToIntBits(this.x)+nt.floatToIntBits(this.y)}toString(){return"("+this.x+","+this.y+")"}static orderBestPatterns(t){const e=this.distance(t[0],t[1]),r=this.distance(t[1],t[2]),n=this.distance(t[0],t[2]);let i,o,s;if(r>=e&&r>=n?(o=t[0],i=t[1],s=t[2]):n>=r&&n>=e?(o=t[1],i=t[0],s=t[2]):(o=t[2],i=t[0],s=t[1]),this.crossProductZ(i,o,s)<0){const t=i;i=s,s=t}t[0]=i,t[1]=o,t[2]=s}static distance(t,e){return rt.distance(t.x,t.y,e.x,e.y)}static crossProductZ(t,e,r){const n=e.x,i=e.y;return(r.x-n)*(t.y-i)-(r.y-i)*(t.x-n)}}class ot{constructor(t,e){this.bits=t,this.points=e}getBits(){return this.bits}getPoints(){return this.points}}class st extends ot{constructor(t,e,r,n,i){super(t,e),this.compact=r,this.nbDatablocks=n,this.nbLayers=i}getNbLayers(){return this.nbLayers}getNbDatablocks(){return this.nbDatablocks}isCompact(){return this.compact}}class at{constructor(t,e,r,n){this.image=t,this.height=t.getHeight(),this.width=t.getWidth(),null==e&&(e=at.INIT_SIZE),null==r&&(r=t.getWidth()/2|0),null==n&&(n=t.getHeight()/2|0);const i=e/2|0;if(this.leftInit=r-i,this.rightInit=r+i,this.upInit=n-i,this.downInit=n+i,this.upInit<0||this.leftInit<0||this.downInit>=this.height||this.rightInit>=this.width)throw new D}detect(){let t=this.leftInit,e=this.rightInit,r=this.upInit,n=this.downInit,i=!1,o=!0,s=!1,a=!1,c=!1,l=!1,h=!1;const u=this.width,d=this.height;for(;o;){o=!1;let f=!0;for(;(f||!a)&&e=u){i=!0;break}let g=!0;for(;(g||!c)&&n=d){i=!0;break}let w=!0;for(;(w||!l)&&t>=0;)w=this.containsBlackPoint(r,n,t,!1),w?(t--,o=!0,l=!0):l||t--;if(t<0){i=!0;break}let m=!0;for(;(m||!h)&&r>=0;)m=this.containsBlackPoint(t,e,r,!0),m?(r--,o=!0,h=!0):h||r--;if(r<0){i=!0;break}o&&(s=!0)}if(!i&&s){const i=e-t;let o=null;for(let e=1;null===o&&er||s<-1||s>n)throw new D;i=!1,-1===o?(e[t]=0,i=!0):o===r&&(e[t]=r-1,i=!0),-1===s?(e[t+1]=0,i=!0):s===n&&(e[t+1]=n-1,i=!0)}i=!0;for(let t=e.length-2;t>=0&&i;t-=2){const o=Math.floor(e[t]),s=Math.floor(e[t+1]);if(o<-1||o>r||s<-1||s>n)throw new D;i=!1,-1===o?(e[t]=0,i=!0):o===r&&(e[t]=r-1,i=!0),-1===s?(e[t+1]=0,i=!0):s===n&&(e[t+1]=n-1,i=!0)}}}class lt{constructor(t,e,r,n,i,o,s,a,c){this.a11=t,this.a21=e,this.a31=r,this.a12=n,this.a22=i,this.a32=o,this.a13=s,this.a23=a,this.a33=c}static quadrilateralToQuadrilateral(t,e,r,n,i,o,s,a,c,l,h,u,d,f,g,w){const m=lt.quadrilateralToSquare(t,e,r,n,i,o,s,a);return lt.squareToQuadrilateral(c,l,h,u,d,f,g,w).times(m)}transformPoints(t){const e=t.length,r=this.a11,n=this.a12,i=this.a13,o=this.a21,s=this.a22,a=this.a23,c=this.a31,l=this.a32,h=this.a33;for(let u=0;u>1&127):(n<<=10,n+=(e>>2&992)+(e>>1&31))}let i=this.getCorrectedParameterData(n,this.compact);this.compact?(this.nbLayers=1+(i>>6),this.nbDataBlocks=1+(63&i)):(this.nbLayers=1+(i>>11),this.nbDataBlocks=1+(2047&i))}getRotation(t,e){let r=0;t.forEach(((t,n,i)=>{r=(t>>e-2<<1)+(1&t)+(r<<3)})),r=((1&r)<<11)+(r>>1);for(let t=0;t<4;t++)if(m.bitCount(r^this.EXPECTED_CORNER_BITS[t])<=2)return t;throw new D}getCorrectedParameterData(t,e){let r,n;e?(r=7,n=2):(r=10,n=4);let i=r-n,o=new Int32Array(r);for(let e=r-1;e>=0;--e)o[e]=15&t,t>>=4;try{new tt(q.AZTEC_PARAM).decode(o,i)}catch(t){throw new D}let s=0;for(let t=0;t2){let r=this.distancePoint(c,t)*this.nbCenterLayers/(this.distancePoint(i,e)*(this.nbCenterLayers+2));if(r<.75||r>1.25||!this.isWhiteOrBlackRectangle(t,s,a,c))break}e=t,r=s,n=a,i=c,o=!o}if(5!==this.nbCenterLayers&&7!==this.nbCenterLayers)throw new D;this.compact=5===this.nbCenterLayers;let s=new it(e.getX()+.5,e.getY()-.5),a=new it(r.getX()+.5,r.getY()+.5),c=new it(n.getX()-.5,n.getY()+.5),l=new it(i.getX()-.5,i.getY()-.5);return this.expandSquare([s,a,c,l],2*this.nbCenterLayers-3,2*this.nbCenterLayers)}getMatrixCenter(){let t,e,r,n;try{let i=new at(this.image).detect();t=i[0],e=i[1],r=i[2],n=i[3]}catch(i){let o=this.image.getWidth()/2,s=this.image.getHeight()/2;t=this.getFirstDifferent(new dt(o+7,s-7),!1,1,-1).toResultPoint(),e=this.getFirstDifferent(new dt(o+7,s+7),!1,1,1).toResultPoint(),r=this.getFirstDifferent(new dt(o-7,s+7),!1,-1,1).toResultPoint(),n=this.getFirstDifferent(new dt(o-7,s-7),!1,-1,-1).toResultPoint()}let i=rt.round((t.getX()+n.getX()+e.getX()+r.getX())/4),o=rt.round((t.getY()+n.getY()+e.getY()+r.getY())/4);try{let s=new at(this.image,15,i,o).detect();t=s[0],e=s[1],r=s[2],n=s[3]}catch(s){t=this.getFirstDifferent(new dt(i+7,o-7),!1,1,-1).toResultPoint(),e=this.getFirstDifferent(new dt(i+7,o+7),!1,1,1).toResultPoint(),r=this.getFirstDifferent(new dt(i-7,o+7),!1,-1,1).toResultPoint(),n=this.getFirstDifferent(new dt(i-7,o-7),!1,-1,-1).toResultPoint()}return i=rt.round((t.getX()+n.getX()+e.getX()+r.getX())/4),o=rt.round((t.getY()+n.getY()+e.getY()+r.getY())/4),new dt(i,o)}getMatrixCornerPoints(t){return this.expandSquare(t,2*this.nbCenterLayers,this.getDimension())}sampleGrid(t,e,r,n,i){let o=ut.getInstance(),s=this.getDimension(),a=s/2-this.nbCenterLayers,c=s/2+this.nbCenterLayers;return o.sampleGrid(t,s,s,a,a,c,a,c,c,a,c,e.getX(),e.getY(),r.getX(),r.getY(),n.getX(),n.getY(),i.getX(),i.getY())}sampleLine(t,e,r){let n=0,i=this.distanceResultPoint(t,e),o=i/r,s=t.getX(),a=t.getY(),c=o*(e.getX()-t.getX())/i,l=o*(e.getY()-t.getY())/i;for(let t=0;t.1&&h<.9?0:h<=.1===c?1:-1}getFirstDifferent(t,e,r,n){let i=t.getX()+r,o=t.getY()+n;for(;this.isValid(i,o)&&this.image.get(i,o)===e;)i+=r,o+=n;for(i-=r,o-=n;this.isValid(i,o)&&this.image.get(i,o)===e;)i+=r;for(i-=r;this.isValid(i,o)&&this.image.get(i,o)===e;)o+=n;return o-=n,new dt(i,o)}expandSquare(t,e,r){let n=r/(2*e),i=t[0].getX()-t[2].getX(),o=t[0].getY()-t[2].getY(),s=(t[0].getX()+t[2].getX())/2,a=(t[0].getY()+t[2].getY())/2,c=new it(s+n*i,a+n*o),l=new it(s-n*i,a-n*o);return i=t[1].getX()-t[3].getX(),o=t[1].getY()-t[3].getY(),s=(t[1].getX()+t[3].getX())/2,a=(t[1].getY()+t[3].getY())/2,[c,new it(s+n*i,a+n*o),l,new it(s-n*i,a-n*o)]}isValid(t,e){return t>=0&&t0&&e{r.foundPossibleResultPoint(t)}))}}reset(){}}class wt{decode(t,e){try{return this.doDecode(t,e)}catch(r){if(e&&!0===e.get(C.TRY_HARDER)&&t.isRotateSupported()){const r=t.rotateCounterClockwise(),n=this.doDecode(r,e),i=n.getResultMetadata();let o=270;null!==i&&!0===i.get(W.ORIENTATION)&&(o+=i.get(W.ORIENTATION)%360),n.putMetadata(W.ORIENTATION,o);const s=n.getResultPoints();if(null!==s){const t=r.getHeight();for(let e=0;e>(o?8:5));let a;a=o?n:15;const c=Math.trunc(n/2);for(let o=0;o=n)break;try{i=t.getBlackRow(l,i)}catch(t){continue}for(let t=0;t<2;t++){if(1===t&&(i.reverse(),e&&!0===e.get(C.NEED_RESULT_POINT_CALLBACK))){const t=new Map;e.forEach(((e,r)=>t.set(r,e))),t.delete(C.NEED_RESULT_POINT_CALLBACK),e=t}try{const n=this.decodeRow(l,i,e);if(1===t){n.putMetadata(W.ORIENTATION,180);const t=n.getResultPoints();null!==t&&(t[0]=new it(r-t[0].getX()-1,t[0].getY()),t[1]=new it(r-t[1].getX()-1,t[1].getY()))}return n}catch(t){}}}throw new D}static recordPattern(t,e,r){const n=r.length;for(let t=0;t=i)throw new D;let o=!t.get(e),s=0,a=e;for(;a0&&n>=0;)t.get(--e)!==i&&(n--,i=!i);if(n>=0)throw new D;wt.recordPattern(t,e+1,r)}static patternMatchVariance(t,e,r){const n=t.length;let i=0,o=0;for(let r=0;ro?n-o:o-n;if(c>r)return Number.POSITIVE_INFINITY;a+=c}return a/i}}class mt extends wt{static findStartPattern(t){const e=t.getSize(),r=t.getNextSet(0);let n=0,i=Int32Array.from([0,0,0,0,0,0]),o=r,s=!1;for(let a=r;a=0&&t.isRange(Math.max(0,o-(a-o)/2),o,!1))return Int32Array.from([o,a,r]);o+=i[0]+i[1],i=i.slice(2,i.length-1),i[n-1]=0,i[n]=0,n--}else n++;i[n]=1,s=!s}throw new D}static decodeCode(t,e,r){wt.recordPattern(t,r,e);let n=mt.MAX_AVG_VARIANCE,i=-1;for(let t=0;t=0)return i;throw new D}decodeRow(t,e,r){const n=r&&!0===r.get(C.ASSUME_GS1),i=mt.findStartPattern(e),o=i[2];let s=0;const a=new Uint8Array(20);let c;switch(a[s++]=o,o){case mt.CODE_START_A:c=mt.CODE_CODE_A;break;case mt.CODE_START_B:c=mt.CODE_CODE_B;break;case mt.CODE_START_C:c=mt.CODE_CODE_C;break;default:throw new E}let l=!1,u=!1,d="",f=i[0],g=i[1];const w=Int32Array.from([0,0,0,0,0,0]);let m=0,p=0,A=o,I=0,S=!0,_=!1,T=!1;for(;!l;){const t=u;switch(u=!1,m=p,p=mt.decodeCode(e,w,g),a[s++]=p,p!==mt.CODE_STOP&&(S=!0),p!==mt.CODE_STOP&&(I++,A+=I*p),f=g,g+=w.reduce(((t,e)=>t+e),0),p){case mt.CODE_START_A:case mt.CODE_START_B:case mt.CODE_START_C:throw new E}switch(c){case mt.CODE_CODE_A:if(p<64)d+=T===_?String.fromCharCode(" ".charCodeAt(0)+p):String.fromCharCode(" ".charCodeAt(0)+p+128),T=!1;else if(p<96)d+=T===_?String.fromCharCode(p-64):String.fromCharCode(p+64),T=!1;else switch(p!==mt.CODE_STOP&&(S=!1),p){case mt.CODE_FNC_1:n&&(0===d.length?d+="]C1":d+=String.fromCharCode(29));break;case mt.CODE_FNC_2:case mt.CODE_FNC_3:break;case mt.CODE_FNC_4_A:!_&&T?(_=!0,T=!1):_&&T?(_=!1,T=!1):T=!0;break;case mt.CODE_SHIFT:u=!0,c=mt.CODE_CODE_B;break;case mt.CODE_CODE_B:c=mt.CODE_CODE_B;break;case mt.CODE_CODE_C:c=mt.CODE_CODE_C;break;case mt.CODE_STOP:l=!0}break;case mt.CODE_CODE_B:if(p<96)d+=T===_?String.fromCharCode(" ".charCodeAt(0)+p):String.fromCharCode(" ".charCodeAt(0)+p+128),T=!1;else switch(p!==mt.CODE_STOP&&(S=!1),p){case mt.CODE_FNC_1:n&&(0===d.length?d+="]C1":d+=String.fromCharCode(29));break;case mt.CODE_FNC_2:case mt.CODE_FNC_3:break;case mt.CODE_FNC_4_B:!_&&T?(_=!0,T=!1):_&&T?(_=!1,T=!1):T=!0;break;case mt.CODE_SHIFT:u=!0,c=mt.CODE_CODE_A;break;case mt.CODE_CODE_A:c=mt.CODE_CODE_A;break;case mt.CODE_CODE_C:c=mt.CODE_CODE_C;break;case mt.CODE_STOP:l=!0}break;case mt.CODE_CODE_C:if(p<100)p<10&&(d+="0"),d+=p;else switch(p!==mt.CODE_STOP&&(S=!1),p){case mt.CODE_FNC_1:n&&(0===d.length?d+="]C1":d+=String.fromCharCode(29));break;case mt.CODE_CODE_A:c=mt.CODE_CODE_A;break;case mt.CODE_CODE_B:c=mt.CODE_CODE_B;break;case mt.CODE_STOP:l=!0}}t&&(c=c===mt.CODE_CODE_A?mt.CODE_CODE_B:mt.CODE_CODE_A)}const y=g-f;if(g=e.getNextUnset(g),!e.isRange(g,Math.min(e.getSize(),g+(g-f)/2),!1))throw new D;if(A-=I*m,A%103!==m)throw new h;const N=d.length;if(0===N)throw new D;N>0&&S&&(d=c===mt.CODE_CODE_C?d.substring(0,N-2):d.substring(0,N-1));const M=(i[1]+i[0])/2,R=f+y/2,O=a.length,b=new Uint8Array(O);for(let t=0;tn&&(i=e);n=i,e=0;let o=0,s=0;for(let i=0;in&&(s|=1<0;i++){let r=t[i];if(r>n&&(e--,2*r>=o))return-1}return s}}while(e>3);return-1}static patternToChar(t){for(let e=0;e="A"&&i<="Z"))throw new E;o=String.fromCharCode(i.charCodeAt(0)+32);break;case"$":if(!(i>="A"&&i<="Z"))throw new E;o=String.fromCharCode(i.charCodeAt(0)-64);break;case"%":if(i>="A"&&i<="E")o=String.fromCharCode(i.charCodeAt(0)-38);else if(i>="F"&&i<="J")o=String.fromCharCode(i.charCodeAt(0)-11);else if(i>="K"&&i<="O")o=String.fromCharCode(i.charCodeAt(0)+16);else if(i>="P"&&i<="T")o=String.fromCharCode(i.charCodeAt(0)+43);else if("U"===i)o="\0";else if("V"===i)o="@";else if("W"===i)o="`";else{if("X"!==i&&"Y"!==i&&"Z"!==i)throw new E;o=""}break;case"/":if(i>="A"&&i<="O")o=String.fromCharCode(i.charCodeAt(0)-32);else{if("Z"!==i)throw new E;o=":"}}r+=o,n++}else r+=e}return r}}pt.ALPHABET_STRING="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-. $/+%",pt.CHARACTER_ENCODINGS=[52,289,97,352,49,304,112,37,292,100,265,73,328,25,280,88,13,268,76,28,259,67,322,19,274,82,7,262,70,22,385,193,448,145,400,208,133,388,196,168,162,138,42],pt.ASTERISK_ENCODING=148;class At extends wt{constructor(){super(...arguments),this.narrowLineWidth=-1}decodeRow(t,e,r){let n=this.decodeStart(e),i=this.decodeEnd(e),o=new y;At.decodeMiddle(e,n[1],i[0],o);let s=o.toString(),a=null;null!=r&&(a=r.get(C.ALLOWED_LENGTHS)),null==a&&(a=At.DEFAULT_ALLOWED_LENGTHS);let c=s.length,l=!1,h=0;for(let t of a){if(c===t){l=!0;break}t>h&&(h=t)}if(!l&&c>h&&(l=!0),!l)throw new E;const u=[new it(n[1],t),new it(i[0],t)];return new x(s,null,0,u,U.ITF,(new Date).getTime())}static decodeMiddle(t,e,r,n){let i=new Int32Array(10),o=new Int32Array(5),s=new Int32Array(5);for(i.fill(0),o.fill(0),s.fill(0);e0&&n>=0&&!t.get(n);n--)r--;if(0!==r)throw new D}static skipWhiteSpace(t){const e=t.getSize(),r=t.getNextSet(0);if(r===e)throw new D;return r}decodeEnd(t){t.reverse();try{let e,r=At.skipWhiteSpace(t);try{e=At.findGuardPattern(t,r,At.END_PATTERN_REVERSED[0])}catch(n){n instanceof D&&(e=At.findGuardPattern(t,r,At.END_PATTERN_REVERSED[1]))}this.validateQuietZone(t,e[0]);let n=e[0];return e[0]=t.getSize()-e[1],e[1]=t.getSize()-n,e}finally{t.reverse()}}static findGuardPattern(t,e,r){let n=r.length,i=new Int32Array(n),o=t.getSize(),s=!1,a=0,c=e;i.fill(0);for(let l=e;l=0)return r%10;throw new D}}At.PATTERNS=[Int32Array.from([1,1,2,2,1]),Int32Array.from([2,1,1,1,2]),Int32Array.from([1,2,1,1,2]),Int32Array.from([2,2,1,1,1]),Int32Array.from([1,1,2,1,2]),Int32Array.from([2,1,2,1,1]),Int32Array.from([1,2,2,1,1]),Int32Array.from([1,1,1,2,2]),Int32Array.from([2,1,1,2,1]),Int32Array.from([1,2,1,2,1]),Int32Array.from([1,1,3,3,1]),Int32Array.from([3,1,1,1,3]),Int32Array.from([1,3,1,1,3]),Int32Array.from([3,3,1,1,1]),Int32Array.from([1,1,3,1,3]),Int32Array.from([3,1,3,1,1]),Int32Array.from([1,3,3,1,1]),Int32Array.from([1,1,1,3,3]),Int32Array.from([3,1,1,3,1]),Int32Array.from([1,3,1,3,1])],At.MAX_AVG_VARIANCE=.38,At.MAX_INDIVIDUAL_VARIANCE=.5,At.DEFAULT_ALLOWED_LENGTHS=[6,8,10,12,14],At.START_PATTERN=Int32Array.from([1,1,1,1]),At.END_PATTERN_REVERSED=[Int32Array.from([1,1,2]),Int32Array.from([1,1,3])];class Ct extends wt{constructor(){super(...arguments),this.decodeRowStringBuffer=""}static findStartGuardPattern(t){let e,r=!1,n=0,i=Int32Array.from([0,0,0]);for(;!r;){i=Int32Array.from([0,0,0]),e=Ct.findGuardPattern(t,n,!1,this.START_END_PATTERN,i);let o=e[0];n=e[1];let s=o-(n-o);s>=0&&(r=t.isRange(s,o,!1))}return e}static checkChecksum(t){return Ct.checkStandardUPCEANChecksum(t)}static checkStandardUPCEANChecksum(t){let e=t.length;if(0===e)return!1;let r=parseInt(t.charAt(e-1),10);return Ct.getStandardUPCEANChecksum(t.substring(0,e-1))===r}static getStandardUPCEANChecksum(t){let e=t.length,r=0;for(let n=e-1;n>=0;n-=2){let e=t.charAt(n).charCodeAt(0)-"0".charCodeAt(0);if(e<0||e>9)throw new E;r+=e}r*=3;for(let n=e-2;n>=0;n-=2){let e=t.charAt(n).charCodeAt(0)-"0".charCodeAt(0);if(e<0||e>9)throw new E;r+=e}return(1e3-r)%10}static decodeEnd(t,e){return Ct.findGuardPattern(t,e,!1,Ct.START_END_PATTERN,new Int32Array(Ct.START_END_PATTERN.length).fill(0))}static findGuardPatternWithoutCounters(t,e,r,n){return this.findGuardPattern(t,e,r,n,new Int32Array(n.length))}static findGuardPattern(t,e,r,n,i){let o=t.getSize(),s=0,a=e=r?t.getNextUnset(e):t.getNextSet(e),c=n.length,l=r;for(let r=e;r=0)return o;throw new D}}Ct.MAX_AVG_VARIANCE=.48,Ct.MAX_INDIVIDUAL_VARIANCE=.7,Ct.START_END_PATTERN=Int32Array.from([1,1,1]),Ct.MIDDLE_PATTERN=Int32Array.from([1,1,1,1,1]),Ct.END_PATTERN=Int32Array.from([1,1,1,1,1,1]),Ct.L_PATTERNS=[Int32Array.from([3,2,1,1]),Int32Array.from([2,2,2,1]),Int32Array.from([2,1,2,2]),Int32Array.from([1,4,1,1]),Int32Array.from([1,1,3,2]),Int32Array.from([1,2,3,1]),Int32Array.from([1,1,1,4]),Int32Array.from([1,3,1,2]),Int32Array.from([1,2,1,3]),Int32Array.from([3,1,1,2])];class Et{constructor(){this.CHECK_DIGIT_ENCODINGS=[24,20,18,17,12,6,3,10,9,5],this.decodeMiddleCounters=Int32Array.from([0,0,0,0]),this.decodeRowStringBuffer=""}decodeRow(t,e,r){let n=this.decodeRowStringBuffer,i=this.decodeMiddle(e,r,n),o=n.toString(),s=Et.parseExtensionString(o),a=[new it((r[0]+r[1])/2,t),new it(i,t)],c=new x(o,null,0,a,U.UPC_EAN_EXTENSION,(new Date).getTime());return null!=s&&c.putAllMetadata(s),c}decodeMiddle(t,e,r){let n=this.decodeMiddleCounters;n[0]=0,n[1]=0,n[2]=0,n[3]=0;let i=t.getSize(),o=e[1],s=0;for(let e=0;e<5&&o=10&&(s|=1<<4-e),4!==e&&(o=t.getNextSet(o),o=t.getNextUnset(o))}if(5!==r.length)throw new D;let a=this.determineCheckDigit(s);if(Et.extensionChecksum(r.toString())!==a)throw new D;return o}static extensionChecksum(t){let e=t.length,r=0;for(let n=e-2;n>=0;n-=2)r+=t.charAt(n).charCodeAt(0)-"0".charCodeAt(0);r*=3;for(let n=e-1;n>=0;n-=2)r+=t.charAt(n).charCodeAt(0)-"0".charCodeAt(0);return r*=3,r%10}determineCheckDigit(t){for(let e=0;e<10;e++)if(t===this.CHECK_DIGIT_ENCODINGS[e])return e;throw new D}static parseExtensionString(t){if(5!==t.length)return null;let e=Et.parseExtension5String(t);return null==e?null:new Map([[W.SUGGESTED_PRICE,e]])}static parseExtension5String(t){let e;switch(t.charAt(0)){case"0":e="£";break;case"5":e="$";break;case"9":switch(t){case"90000":return null;case"99991":return"0.00";case"99990":return"Used"}e="";break;default:e=""}let r=parseInt(t.substring(1)),n=r%100;return e+(r/100).toString()+"."+(n<10?"0"+n:n.toString())}}class It{constructor(){this.decodeMiddleCounters=Int32Array.from([0,0,0,0]),this.decodeRowStringBuffer=""}decodeRow(t,e,r){let n=this.decodeRowStringBuffer,i=this.decodeMiddle(e,r,n),o=n.toString(),s=It.parseExtensionString(o),a=[new it((r[0]+r[1])/2,t),new it(i,t)],c=new x(o,null,0,a,U.UPC_EAN_EXTENSION,(new Date).getTime());return null!=s&&c.putAllMetadata(s),c}decodeMiddle(t,e,r){let n=this.decodeMiddleCounters;n[0]=0,n[1]=0,n[2]=0,n[3]=0;let i=t.getSize(),o=e[1],s=0;for(let e=0;e<2&&o=10&&(s|=1<<1-e),1!==e&&(o=t.getNextSet(o),o=t.getNextUnset(o))}if(2!==r.length)throw new D;if(parseInt(r.toString())%4!==s)throw new D;return o}static parseExtensionString(t){return 2!==t.length?null:new Map([[W.ISSUE_NUMBER,parseInt(t)]])}}class St{static decodeRow(t,e,r){let n=Ct.findGuardPattern(e,r,!1,this.EXTENSION_START_PATTERN,new Int32Array(this.EXTENSION_START_PATTERN.length).fill(0));try{return(new Et).decodeRow(t,e,n)}catch(r){return(new It).decodeRow(t,e,n)}}}St.EXTENSION_START_PATTERN=Int32Array.from([1,1,2]);class _t extends Ct{constructor(){super(),this.decodeRowStringBuffer="",_t.L_AND_G_PATTERNS=_t.L_PATTERNS.map((t=>Int32Array.from(t)));for(let t=10;t<20;t++){let e=_t.L_PATTERNS[t-10],r=new Int32Array(e.length);for(let t=0;t=e.getSize()||!e.isRange(l,u,!1))throw new D;let d=a.toString();if(d.length<8)throw new E;if(!_t.checkChecksum(d))throw new h;let f=(n[1]+n[0])/2,g=(c[1]+c[0])/2,w=this.getBarcodeFormat(),m=[new it(f,t),new it(g,t)],p=new x(d,null,0,m,w,(new Date).getTime()),A=0;try{let r=St.decodeRow(t,e,c[1]);p.putMetadata(W.UPC_EAN_EXTENSION,r.getText()),p.putAllMetadata(r.getResultMetadata()),p.addResultPoints(r.getResultPoints()),A=r.getText().length}catch(t){}let I=null==r?null:r.get(C.ALLOWED_EAN_EXTENSIONS);if(null!=I){let t=!1;for(let e in I)if(A.toString()===e){t=!0;break}if(!t)throw new D}return p}decodeEnd(t,e){return _t.findGuardPattern(t,e,!1,_t.START_END_PATTERN,new Int32Array(_t.START_END_PATTERN.length).fill(0))}static checkChecksum(t){return _t.checkStandardUPCEANChecksum(t)}static checkStandardUPCEANChecksum(t){let e=t.length;if(0===e)return!1;let r=parseInt(t.charAt(e-1),10);return _t.getStandardUPCEANChecksum(t.substring(0,e-1))===r}static getStandardUPCEANChecksum(t){let e=t.length,r=0;for(let n=e-1;n>=0;n-=2){let e=t.charAt(n).charCodeAt(0)-"0".charCodeAt(0);if(e<0||e>9)throw new E;r+=e}r*=3;for(let n=e-2;n>=0;n-=2){let e=t.charAt(n).charCodeAt(0)-"0".charCodeAt(0);if(e<0||e>9)throw new E;r+=e}return(1e3-r)%10}}class Tt extends _t{constructor(){super(),this.decodeMiddleCounters=Int32Array.from([0,0,0,0])}decodeMiddle(t,e,r){let n=this.decodeMiddleCounters;n[0]=0,n[1]=0,n[2]=0,n[3]=0;let i=t.getSize(),o=e[1],s=0;for(let e=0;e<6&&o=10&&(s|=1<<5-e)}r=Tt.determineFirstDigit(r,s),o=_t.findGuardPattern(t,o,!0,_t.MIDDLE_PATTERN,new Int32Array(_t.MIDDLE_PATTERN.length).fill(0))[1];for(let e=0;e<6&&ot));n[0]=0,n[1]=0,n[2]=0,n[3]=0;const i=t.getSize();let o=e[1],s=0;for(let e=0;e<6&&o=10&&(s|=1<<5-e)}return{rowOffset:o,resultString:Dt.determineNumSysAndCheckDigit(r,s)}}decodeEnd(t,e){return Dt.findGuardPatternWithoutCounters(t,e,!0,Dt.MIDDLE_END_PATTERN)}checkChecksum(t){return _t.checkChecksum(Dt.convertUPCEtoUPCA(t))}static determineNumSysAndCheckDigit(t,e){for(let r=0;r<=1;r++)for(let n=0;n<10;n++)if(e===this.NUMSYS_AND_CHECK_DIGIT_PATTERNS[r][n])return String.fromCharCode("0".charCodeAt(0)+r)+t+String.fromCharCode("0".charCodeAt(0)+n);throw D.getNotFoundInstance()}getBarcodeFormat(){return U.UPC_E}static convertUPCEtoUPCA(t){const e=t.slice(1,7).split("").map((t=>t.charCodeAt(0))),r=new y;r.append(t.charAt(0));let n=e[5];switch(n){case 0:case 1:case 2:r.appendChars(e,0,2),r.append(n),r.append("0000"),r.appendChars(e,2,3);break;case 3:r.appendChars(e,0,3),r.append("00000"),r.appendChars(e,3,2);break;case 4:r.appendChars(e,0,4),r.append("00000"),r.append(e[4]);break;default:r.appendChars(e,0,5),r.append("0000"),r.append(n)}return t.length>=8&&r.append(t.charAt(7)),r.toString()}}Dt.MIDDLE_END_PATTERN=Int32Array.from([1,1,1,1,1,1]),Dt.NUMSYS_AND_CHECK_DIGIT_PATTERNS=[Int32Array.from([56,52,50,49,44,38,35,42,41,37]),Int32Array.from([7,11,13,14,19,25,28,21,22,26])];class Mt extends wt{constructor(t){super();let r=null==t?null:t.get(C.POSSIBLE_FORMATS),n=[];e(r)?(n.push(new Tt),n.push(new Nt),n.push(new yt),n.push(new Dt)):(r.indexOf(U.EAN_13)>-1&&n.push(new Tt),r.indexOf(U.UPC_A)>-1&&n.push(new Nt),r.indexOf(U.EAN_8)>-1&&n.push(new yt),r.indexOf(U.UPC_E)>-1&&n.push(new Dt)),this.readers=n}decodeRow(t,e,r){for(let n of this.readers)try{const i=n.decodeRow(t,e,r),o=i.getBarcodeFormat()===U.EAN_13&&"0"===i.getText().charAt(0),s=null==r?null:r.get(C.POSSIBLE_FORMATS),a=null==s||s.includes(U.UPC_A);if(o&&a){const t=i.getRawBytes(),e=new x(i.getText().substring(1),t,t?t.length:null,i.getResultPoints(),U.UPC_A);return e.putAllMetadata(i.getResultMetadata()),e}return i}catch(t){}throw new D}reset(){for(let t of this.readers)t.reset()}}class Rt extends wt{constructor(){super(),this.decodeFinderCounters=new Int32Array(4),this.dataCharacterCounters=new Int32Array(8),this.oddRoundingErrors=new Array(4),this.evenRoundingErrors=new Array(4),this.oddCounts=new Array(this.dataCharacterCounters.length/2),this.evenCounts=new Array(this.dataCharacterCounters.length/2)}getDecodeFinderCounters(){return this.decodeFinderCounters}getDataCharacterCounters(){return this.dataCharacterCounters}getOddRoundingErrors(){return this.oddRoundingErrors}getEvenRoundingErrors(){return this.evenRoundingErrors}getOddCounts(){return this.oddCounts}getEvenCounts(){return this.evenCounts}parseFinderValue(t,e){for(let r=0;rn&&(n=e[i],r=i);t[r]++}static decrement(t,e){let r=0,n=e[0];for(let i=1;i=Rt.MIN_FINDER_PATTERN_RATIO&&r<=Rt.MAX_FINDER_PATTERN_RATIO){let e=Number.MAX_SAFE_INTEGER,r=Number.MIN_SAFE_INTEGER;for(let n of t)n>r&&(r=n),n=s-a-1&&(t-=Bt.combins(n-c-(s-a),s-a-2)),s-a-1>1){let r=0;for(let t=n-c-(s-a-2);t>e;t--)r+=Bt.combins(n-c-t-1,s-a-3);t-=r*(s-1-a)}else n-c>e&&t--;i+=t}n-=c}return i}static combins(t,e){let r,n;t-e>e?(n=e,r=t-e):(n=t-e,r=e);let i=1,o=1;for(let e=t;e>r;e--)i*=e,o<=n&&(i/=o,o++);for(;o<=n;)i/=o,o++;return i}}class Lt{static buildBitArray(t){let e=2*t.length-1;null==t[t.length-1].getRightChar()&&(e-=1);let r=new p(12*e),n=0,i=t[0].getRightChar().getValue();for(let t=11;t>=0;--t)0!=(i&1<=0;--t)0!=(o&1<=0;--e)0!=(t&1<10||r<0||r>10)throw new E;this.firstDigit=e,this.secondDigit=r}getFirstDigit(){return this.firstDigit}getSecondDigit(){return this.secondDigit}getValue(){return 10*this.firstDigit+this.secondDigit}isFirstDigitFNC1(){return this.firstDigit===kt.FNC1}isSecondDigitFNC1(){return this.secondDigit===kt.FNC1}isAnyFNC1(){return this.firstDigit===kt.FNC1||this.secondDigit===kt.FNC1}}kt.FNC1=10;class Ut{constructor(){}static parseFieldsInGeneralPurpose(t){if(!t)return null;if(t.length<2)throw new D;let e=t.substring(0,2);for(let r of Ut.TWO_DIGIT_DATA_LENGTH)if(r[0]===e)return r[1]===Ut.VARIABLE_LENGTH?Ut.processVariableAI(2,r[2],t):Ut.processFixedAI(2,r[1],t);if(t.length<3)throw new D;let r=t.substring(0,3);for(let e of Ut.THREE_DIGIT_DATA_LENGTH)if(e[0]===r)return e[1]===Ut.VARIABLE_LENGTH?Ut.processVariableAI(3,e[2],t):Ut.processFixedAI(3,e[1],t);for(let e of Ut.THREE_DIGIT_PLUS_DIGIT_DATA_LENGTH)if(e[0]===r)return e[1]===Ut.VARIABLE_LENGTH?Ut.processVariableAI(4,e[2],t):Ut.processFixedAI(4,e[1],t);if(t.length<4)throw new D;let n=t.substring(0,4);for(let e of Ut.FOUR_DIGIT_DATA_LENGTH)if(e[0]===n)return e[1]===Ut.VARIABLE_LENGTH?Ut.processVariableAI(4,e[2],t):Ut.processFixedAI(4,e[1],t);throw new D}static processFixedAI(t,e,r){if(r.lengththis.information.getSize())return t+4<=this.information.getSize();for(let e=t;ethis.information.getSize()){let e=this.extractNumericValueFromBitArray(t,4);return new kt(this.information.getSize(),0===e?kt.FNC1:e-1,kt.FNC1)}let e=this.extractNumericValueFromBitArray(t,7);return new kt(t+7,(e-8)/11,(e-8)%11)}extractNumericValueFromBitArray(t,e){return Ht.extractNumericValueFromBitArray(this.information,t,e)}static extractNumericValueFromBitArray(t,e,r){let n=0;for(let i=0;ithis.information.getSize())return!1;let e=this.extractNumericValueFromBitArray(t,5);if(e>=5&&e<16)return!0;if(t+7>this.information.getSize())return!1;let r=this.extractNumericValueFromBitArray(t,7);if(r>=64&&r<116)return!0;if(t+8>this.information.getSize())return!1;let n=this.extractNumericValueFromBitArray(t,8);return n>=232&&n<253}decodeIsoIec646(t){let e=this.extractNumericValueFromBitArray(t,5);if(15===e)return new Ft(t+5,Ft.FNC1);if(e>=5&&e<15)return new Ft(t+5,"0"+(e-5));let r,n=this.extractNumericValueFromBitArray(t,7);if(n>=64&&n<90)return new Ft(t+7,""+(n+1));if(n>=90&&n<116)return new Ft(t+7,""+(n+7));switch(this.extractNumericValueFromBitArray(t,8)){case 232:r="!";break;case 233:r='"';break;case 234:r="%";break;case 235:r="&";break;case 236:r="'";break;case 237:r="(";break;case 238:r=")";break;case 239:r="*";break;case 240:r="+";break;case 241:r=",";break;case 242:r="-";break;case 243:r=".";break;case 244:r="/";break;case 245:r=":";break;case 246:r=";";break;case 247:r="<";break;case 248:r="=";break;case 249:r=">";break;case 250:r="?";break;case 251:r="_";break;case 252:r=" ";break;default:throw new E}return new Ft(t+8,r)}isStillAlpha(t){if(t+5>this.information.getSize())return!1;let e=this.extractNumericValueFromBitArray(t,5);if(e>=5&&e<16)return!0;if(t+6>this.information.getSize())return!1;let r=this.extractNumericValueFromBitArray(t,6);return r>=16&&r<63}decodeAlphanumeric(t){let e=this.extractNumericValueFromBitArray(t,5);if(15===e)return new Ft(t+5,Ft.FNC1);if(e>=5&&e<15)return new Ft(t+5,"0"+(e-5));let r,n=this.extractNumericValueFromBitArray(t,6);if(n>=32&&n<58)return new Ft(t+6,""+(n+33));switch(n){case 58:r="*";break;case 59:r=",";break;case 60:r="-";break;case 61:r=".";break;case 62:r="/";break;default:throw new $("Decoding invalid alphanumeric value: "+n)}return new Ft(t+6,r)}isAlphaTo646ToAlphaLatch(t){if(t+1>this.information.getSize())return!1;for(let e=0;e<5&&e+tthis.information.getSize())return!1;for(let e=t;ethis.information.getSize())return!1;for(let e=0;e<4&&e+t{e.forEach((e=>{t.getLeftChar().getValue()===e.getLeftChar().getValue()&&t.getRightChar().getValue()===e.getRightChar().getValue()&&t.getFinderPatter().getValue()===e.getFinderPatter().getValue()&&(r=!0)}))})),r}}class ee extends Rt{constructor(t){super(...arguments),this.pairs=new Array(ee.MAX_PAIRS),this.rows=new Array,this.startEnd=[2],this.verbose=!0===t}decodeRow(t,e,r){this.pairs.length=0,this.startFromEven=!1;try{return ee.constructResult(this.decodeRow2pairs(t,e))}catch(t){this.verbose&&console.log(t)}return this.pairs.length=0,this.startFromEven=!0,ee.constructResult(this.decodeRow2pairs(t,e))}reset(){this.pairs.length=0,this.rows.length=0}decodeRow2pairs(t,e){let r,n=!1;for(;!n;)try{this.pairs.push(this.retrieveNextPair(e,this.pairs,t))}catch(t){if(t instanceof D){if(!this.pairs.length)throw new D;n=!0}}if(this.checkChecksum())return this.pairs;if(r=!!this.rows.length,this.storeRow(t,!1),r){let t=this.checkRowsBoolean(!1);if(null!=t)return t;if(t=this.checkRowsBoolean(!0),null!=t)return t}throw new D}checkRowsBoolean(t){if(this.rows.length>25)return this.rows.length=0,null;this.pairs.length=0,t&&(this.rows=this.rows.reverse());let e=null;try{e=this.checkRows(new Array,0)}catch(t){this.verbose&&console.log(t)}return t&&(this.rows=this.rows.reverse()),e}checkRows(t,e){for(let r=e;re.length)continue;let r=!0;for(let n=0;nt){i=e.isEquivalent(this.pairs);break}n=e.isEquivalent(this.pairs),r++}i||n||ee.isPartialRow(this.pairs,this.rows)||(this.rows.push(r,new te(this.pairs,t,e)),this.removePartialRows(this.pairs,this.rows))}removePartialRows(t,e){for(let r of e)if(r.getPairs().length!==t.length)for(let e of r.getPairs())for(let r of t)if($t.equals(e,r))break}static isPartialRow(t,e){for(let r of e){let e=!0;for(let n of t){let t=!1;for(let e of r.getPairs())if(n.equals(e)){t=!0;break}if(!t){e=!1;break}}if(e)return!0}return!1}getRows(){return this.rows}static constructResult(t){let e=Jt(Lt.buildBitArray(t)).parseInformation(),r=t[0].getFinderPattern().getResultPoints(),n=t[t.length-1].getFinderPattern().getResultPoints(),i=[r[0],r[1],n[0],n[1]];return new x(e,null,null,i,U.RSS_EXPANDED,null)}checkChecksum(){let t=this.pairs.get(0),e=t.getLeftChar(),r=t.getRightChar();if(null==r)return!1;let n=r.getChecksumPortion(),i=2;for(let t=1;t=0?r:this.isEmptyPair(e)?0:e[e.length-1].getFinderPattern().getStartEnd()[1];let s=e.length%2!=0;this.startFromEven&&(s=!s);let a=!1;for(;i=0&&!t.get(e);)e--;e++,n=this.startEnd[0]-e,i=e,o=this.startEnd[1]}else i=this.startEnd[0],o=t.getNextUnset(this.startEnd[1]+1),n=o-this.startEnd[1];let s,a=this.getDecodeFinderCounters();d.arraycopy(a,0,a,1,a.length-1),a[0]=n;try{s=this.parseFinderValue(a,ee.FINDER_PATTERNS)}catch(t){return null}return new bt(s,[i,o],i,o,e)}decodeDataCharacter(t,e,r,n){let i=this.getDataCharacterCounters();for(let t=0;t.3)throw new D;let a=this.getOddCounts(),c=this.getEvenCounts(),l=this.getOddRoundingErrors(),h=this.getEvenRoundingErrors();for(let t=0;t8){if(e>8.7)throw new D;r=8}let n=t/2;0==(1&t)?(a[n]=r,l[n]=e-r):(c[n]=r,h[n]=e-r)}this.adjustOddEvenCounts(17);let u=4*e.getValue()+(r?0:2)+(n?0:1)-1,d=0,f=0;for(let t=a.length-1;t>=0;t--){if(ee.isNotA1left(e,r,n)){let e=ee.WEIGHTS[u][2*t];f+=a[t]*e}d+=a[t]}let g=0;for(let t=c.length-1;t>=0;t--)if(ee.isNotA1left(e,r,n)){let e=ee.WEIGHTS[u][2*t+1];g+=c[t]*e}let w=f+g;if(0!=(1&d)||d>13||d<4)throw new D;let m=(13-d)/2,p=ee.SYMBOL_WIDEST[m],A=9-p,C=Bt.getRSSvalue(a,p,!0),E=Bt.getRSSvalue(c,A,!1),I=ee.EVEN_TOTAL_SUBSET[m],S=ee.GSUM[m];return new Ot(C*I+E+S,w)}static isNotA1left(t,e,r){return!(0==t.getValue()&&e&&r)}adjustOddEvenCounts(t){let e=rt.sum(new Int32Array(this.getOddCounts())),r=rt.sum(new Int32Array(this.getEvenCounts())),n=!1,i=!1;e>13?i=!0:e<4&&(n=!0);let o=!1,s=!1;r>13?s=!0:r<4&&(o=!0);let a=e+r-t,c=1==(1&e),l=0==(1&r);if(1==a)if(c){if(l)throw new D;i=!0}else{if(!l)throw new D;s=!0}else if(-1==a)if(c){if(l)throw new D;n=!0}else{if(!l)throw new D;o=!0}else{if(0!=a)throw new D;if(c){if(!l)throw new D;e1)for(let e of this.possibleRightPairs)if(e.getCount()>1&&ne.checkChecksum(t,e))return ne.constructResult(t,e);throw new D}static addOrTally(t,e){if(null==e)return;let r=!1;for(let n of t)if(n.getValue()===e.getValue()){n.incrementCount(),r=!0;break}r||t.push(e)}reset(){this.possibleLeftPairs.length=0,this.possibleRightPairs.length=0}static constructResult(t,e){let r=4537077*t.getValue()+e.getValue(),n=new String(r).toString(),i=new y;for(let t=13-n.length;t>0;t--)i.append("0");i.append(n);let o=0;for(let t=0;t<13;t++){let e=i.charAt(t).charCodeAt(0)-"0".charCodeAt(0);o+=0==(1&t)?3*e:e}o=10-o%10,10===o&&(o=0),i.append(o.toString());let s=t.getFinderPattern().getResultPoints(),a=e.getFinderPattern().getResultPoints();return new x(i.toString(),null,0,[s[0],s[1],a[0],a[1]],U.RSS_14,(new Date).getTime())}static checkChecksum(t,e){let r=(t.getChecksumPortion()+16*e.getChecksumPortion())%79,n=9*t.getFinderPattern().getValue()+e.getFinderPattern().getValue();return n>72&&n--,n>8&&n--,r===n}decodePair(t,e,r,n){try{let i=this.findFinderPattern(t,e),o=this.parseFoundFinderPattern(t,r,e,i),s=null==n?null:n.get(C.NEED_RESULT_POINT_CALLBACK);if(null!=s){let n=(i[0]+i[1])/2;e&&(n=t.getSize()-1-n),s.foundPossibleResultPoint(new it(n,r))}let a=this.decodeDataCharacter(t,o,!0),c=this.decodeDataCharacter(t,o,!1);return new re(1597*a.getValue()+c.getValue(),a.getChecksumPortion()+4*c.getChecksumPortion(),o)}catch(t){return null}}decodeDataCharacter(t,e,r){let n=this.getDataCharacterCounters();for(let t=0;t8&&(r=8);let i=Math.floor(t/2);0==(1&t)?(s[i]=r,c[i]=e-r):(a[i]=r,l[i]=e-r)}this.adjustOddEvenCounts(r,i);let h=0,u=0;for(let t=s.length-1;t>=0;t--)u*=9,u+=s[t],h+=s[t];let d=0,f=0;for(let t=a.length-1;t>=0;t--)d*=9,d+=a[t],f+=a[t];let g=u+3*d;if(r){if(0!=(1&h)||h>12||h<4)throw new D;let t=(12-h)/2,e=ne.OUTSIDE_ODD_WIDEST[t],r=9-e,n=Bt.getRSSvalue(s,e,!1),i=Bt.getRSSvalue(a,r,!0),o=ne.OUTSIDE_EVEN_TOTAL_SUBSET[t],c=ne.OUTSIDE_GSUM[t];return new Ot(n*o+i+c,g)}{if(0!=(1&f)||f>10||f<4)throw new D;let t=(10-f)/2,e=ne.INSIDE_ODD_WIDEST[t],r=9-e,n=Bt.getRSSvalue(s,e,!0),i=Bt.getRSSvalue(a,r,!1),o=ne.INSIDE_ODD_TOTAL_SUBSET[t],c=ne.INSIDE_GSUM[t];return new Ot(i*o+n+c,g)}}findFinderPattern(t,e){let r=this.getDecodeFinderCounters();r[0]=0,r[1]=0,r[2]=0,r[3]=0;let n=t.getSize(),i=!1,o=0;for(;o=0&&i!==t.get(o);)o--;o++;const s=n[0]-o,a=this.getDecodeFinderCounters(),c=new Int32Array(a.length);d.arraycopy(a,0,c,1,a.length-1),c[0]=s;const l=this.parseFinderValue(c,ne.FINDER_PATTERNS);let h=o,u=n[1];return r&&(h=t.getSize()-1-h,u=t.getSize()-1-u),new bt(l,[o,n[1]],h,u,e)}adjustOddEvenCounts(t,e){let r=rt.sum(new Int32Array(this.getOddCounts())),n=rt.sum(new Int32Array(this.getEvenCounts())),i=!1,o=!1,s=!1,a=!1;t?(r>12?o=!0:r<4&&(i=!0),n>12?a=!0:n<4&&(s=!0)):(r>11?o=!0:r<5&&(i=!0),n>10?a=!0:n<4&&(s=!0));let c=r+n-e,l=(1&r)==(t?1:0),h=1==(1&n);if(1===c)if(l){if(h)throw new D;o=!0}else{if(!h)throw new D;a=!0}else if(-1===c)if(l){if(h)throw new D;i=!0}else{if(!h)throw new D;s=!0}else{if(0!==c)throw new D;if(l){if(!h)throw new D;rt.reset()))}}class oe{constructor(t,e,r){this.ecCodewords=t,this.ecBlocks=[e],r&&this.ecBlocks.push(r)}getECCodewords(){return this.ecCodewords}getECBlocks(){return this.ecBlocks}}class se{constructor(t,e){this.count=t,this.dataCodewords=e}getCount(){return this.count}getDataCodewords(){return this.dataCodewords}}class ae{constructor(t,e,r,n,i,o){this.versionNumber=t,this.symbolSizeRows=e,this.symbolSizeColumns=r,this.dataRegionSizeRows=n,this.dataRegionSizeColumns=i,this.ecBlocks=o;let s=0;const a=o.getECCodewords(),c=o.getECBlocks();for(let t of c)s+=t.getCount()*(t.getDataCodewords()+a);this.totalCodewords=s}getVersionNumber(){return this.versionNumber}getSymbolSizeRows(){return this.symbolSizeRows}getSymbolSizeColumns(){return this.symbolSizeColumns}getDataRegionSizeRows(){return this.dataRegionSizeRows}getDataRegionSizeColumns(){return this.dataRegionSizeColumns}getTotalCodewords(){return this.totalCodewords}getECBlocks(){return this.ecBlocks}static getVersionForDimensions(t,e){if(0!=(1&t)||0!=(1&e))throw new E;for(let r of ae.VERSIONS)if(r.symbolSizeRows===t&&r.symbolSizeColumns===e)return r;throw new E}toString(){return""+this.versionNumber}static buildVersions(){return[new ae(1,10,10,8,8,new oe(5,new se(1,3))),new ae(2,12,12,10,10,new oe(7,new se(1,5))),new ae(3,14,14,12,12,new oe(10,new se(1,8))),new ae(4,16,16,14,14,new oe(12,new se(1,12))),new ae(5,18,18,16,16,new oe(14,new se(1,18))),new ae(6,20,20,18,18,new oe(18,new se(1,22))),new ae(7,22,22,20,20,new oe(20,new se(1,30))),new ae(8,24,24,22,22,new oe(24,new se(1,36))),new ae(9,26,26,24,24,new oe(28,new se(1,44))),new ae(10,32,32,14,14,new oe(36,new se(1,62))),new ae(11,36,36,16,16,new oe(42,new se(1,86))),new ae(12,40,40,18,18,new oe(48,new se(1,114))),new ae(13,44,44,20,20,new oe(56,new se(1,144))),new ae(14,48,48,22,22,new oe(68,new se(1,174))),new ae(15,52,52,24,24,new oe(42,new se(2,102))),new ae(16,64,64,14,14,new oe(56,new se(2,140))),new ae(17,72,72,16,16,new oe(36,new se(4,92))),new ae(18,80,80,18,18,new oe(48,new se(4,114))),new ae(19,88,88,20,20,new oe(56,new se(4,144))),new ae(20,96,96,22,22,new oe(68,new se(4,174))),new ae(21,104,104,24,24,new oe(56,new se(6,136))),new ae(22,120,120,18,18,new oe(68,new se(6,175))),new ae(23,132,132,20,20,new oe(62,new se(8,163))),new ae(24,144,144,22,22,new oe(62,new se(8,156),new se(2,155))),new ae(25,8,18,6,16,new oe(7,new se(1,5))),new ae(26,8,32,6,14,new oe(11,new se(1,10))),new ae(27,12,26,10,24,new oe(14,new se(1,16))),new ae(28,12,36,10,16,new oe(18,new se(1,22))),new ae(29,16,36,14,16,new oe(24,new se(1,32))),new ae(30,16,48,14,22,new oe(28,new se(1,49)))]}}ae.VERSIONS=ae.buildVersions();class ce{constructor(t){const e=t.getHeight();if(e<8||e>144||0!=(1&e))throw new E;this.version=ce.readVersion(t),this.mappingBitMatrix=this.extractDataRegion(t),this.readMappingMatrix=new N(this.mappingBitMatrix.getWidth(),this.mappingBitMatrix.getHeight())}getVersion(){return this.version}static readVersion(t){const e=t.getHeight(),r=t.getWidth();return ae.getVersionForDimensions(e,r)}readCodewords(){const t=new Int8Array(this.version.getTotalCodewords());let e=0,r=4,n=0;const i=this.mappingBitMatrix.getHeight(),o=this.mappingBitMatrix.getWidth();let s=!1,a=!1,c=!1,l=!1;do{if(r!==i||0!==n||s)if(r!==i-2||0!==n||0==(3&o)||a)if(r!==i+4||2!==n||0!=(7&o)||c)if(r!==i-2||0!==n||4!=(7&o)||l){do{r=0&&!this.readMappingMatrix.get(n,r)&&(t[e++]=255&this.readUtah(r,n,i,o)),r-=2,n+=2}while(r>=0&&n=0&&n=0);r+=3,n+=1}else t[e++]=255&this.readCorner4(i,o),r-=2,n+=2,l=!0;else t[e++]=255&this.readCorner3(i,o),r-=2,n+=2,c=!0;else t[e++]=255&this.readCorner2(i,o),r-=2,n+=2,a=!0;else t[e++]=255&this.readCorner1(i,o),r-=2,n+=2,s=!0}while(r7?e-1:e;o[n].codewords[i]=t[h++]}if(h!==t.length)throw new c;return o}getNumDataCodewords(){return this.numDataCodewords}getCodewords(){return this.codewords}}class he{constructor(t){this.bytes=t,this.byteOffset=0,this.bitOffset=0}getBitOffset(){return this.bitOffset}getByteOffset(){return this.byteOffset}readBits(t){if(t<1||t>32||t>this.available())throw new c(""+t);let e=0,r=this.bitOffset,n=this.byteOffset;const i=this.bytes;if(r>0){const o=8-r,s=t>8-s<>a,t-=s,r+=s,8===r&&(r=0,n++)}if(t>0){for(;t>=8;)e=e<<8|255&i[n],n++,t-=8;if(t>0){const o=8-t,s=255>>o<>o,r+=t}}return this.bitOffset=r,this.byteOffset=n,e}available(){return 8*(this.bytes.length-this.byteOffset)-this.bitOffset}}!function(t){t[t.PAD_ENCODE=0]="PAD_ENCODE",t[t.ASCII_ENCODE=1]="ASCII_ENCODE",t[t.C40_ENCODE=2]="C40_ENCODE",t[t.TEXT_ENCODE=3]="TEXT_ENCODE",t[t.ANSIX12_ENCODE=4]="ANSIX12_ENCODE",t[t.EDIFACT_ENCODE=5]="EDIFACT_ENCODE",t[t.BASE256_ENCODE=6]="BASE256_ENCODE"}(V||(V={}));class ue{static decode(t){const e=new he(t),r=new y,n=new y,i=new Array;let o=V.ASCII_ENCODE;do{if(o===V.ASCII_ENCODE)o=this.decodeAsciiSegment(e,r,n);else{switch(o){case V.C40_ENCODE:this.decodeC40Segment(e,r);break;case V.TEXT_ENCODE:this.decodeTextSegment(e,r);break;case V.ANSIX12_ENCODE:this.decodeAnsiX12Segment(e,r);break;case V.EDIFACT_ENCODE:this.decodeEdifactSegment(e,r);break;case V.BASE256_ENCODE:this.decodeBase256Segment(e,r,i);break;default:throw new E}o=V.ASCII_ENCODE}}while(o!==V.PAD_ENCODE&&e.available()>0);return n.length()>0&&r.append(n.toString()),new j(t,r.toString(),0===i.length?null:i,null)}static decodeAsciiSegment(t,e,r){let n=!1;do{let i=t.readBits(8);if(0===i)throw new E;if(i<=128)return n&&(i+=128),e.append(String.fromCharCode(i-1)),V.ASCII_ENCODE;if(129===i)return V.PAD_ENCODE;if(i<=229){const t=i-130;t<10&&e.append("0"),e.append(""+t)}else switch(i){case 230:return V.C40_ENCODE;case 231:return V.BASE256_ENCODE;case 232:e.append(String.fromCharCode(29));break;case 233:case 234:case 241:break;case 235:n=!0;break;case 236:e.append("[)>05"),r.insert(0,"");break;case 237:e.append("[)>06"),r.insert(0,"");break;case 238:return V.ANSIX12_ENCODE;case 239:return V.TEXT_ENCODE;case 240:return V.EDIFACT_ENCODE;default:if(254!==i||0!==t.available())throw new E}}while(t.available()>0);return V.ASCII_ENCODE}static decodeC40Segment(t,e){let r=!1;const n=[];let i=0;do{if(8===t.available())return;const o=t.readBits(8);if(254===o)return;this.parseTwoBytes(o,t.readBits(8),n);for(let t=0;t<3;t++){const o=n[t];switch(i){case 0:if(o<3)i=o+1;else{if(!(o0)}static decodeTextSegment(t,e){let r=!1,n=[],i=0;do{if(8===t.available())return;const o=t.readBits(8);if(254===o)return;this.parseTwoBytes(o,t.readBits(8),n);for(let t=0;t<3;t++){const o=n[t];switch(i){case 0:if(o<3)i=o+1;else{if(!(o0)}static decodeAnsiX12Segment(t,e){const r=[];do{if(8===t.available())return;const n=t.readBits(8);if(254===n)return;this.parseTwoBytes(n,t.readBits(8),r);for(let t=0;t<3;t++){const n=r[t];switch(n){case 0:e.append("\r");break;case 1:e.append("*");break;case 2:e.append(">");break;case 3:e.append(" ");break;default:if(n<14)e.append(String.fromCharCode(n+44));else{if(!(n<40))throw new E;e.append(String.fromCharCode(n+51))}}}}while(t.available()>0)}static parseTwoBytes(t,e,r){let n=(t<<8)+e-1,i=Math.floor(n/1600);r[0]=i,n-=1600*i,i=Math.floor(n/40),r[1]=i,r[2]=n-40*i}static decodeEdifactSegment(t,e){do{if(t.available()<=16)return;for(let r=0;r<4;r++){let r=t.readBits(6);if(31===r){const e=8-t.getBitOffset();return void(8!==e&&t.readBits(e))}0==(32&r)&&(r|=64),e.append(String.fromCharCode(r))}}while(t.available()>0)}static decodeBase256Segment(t,e,r){let n=1+t.getByteOffset();const i=this.unrandomize255State(t.readBits(8),n++);let o;if(o=0===i?t.available()/8|0:i<250?i:250*(i-249)+this.unrandomize255State(t.readBits(8),n++),o<0)throw new E;const s=new Uint8Array(o);for(let e=0;e=0?r:r+256}}ue.C40_BASIC_SET_CHARS=["*","*","*"," ","0","1","2","3","4","5","6","7","8","9","A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z"],ue.C40_SHIFT2_SET_CHARS=["!",'"',"#","$","%","&","'","(",")","*","+",",","-",".","/",":",";","<","=",">","?","@","[","\\","]","^","_"],ue.TEXT_BASIC_SET_CHARS=["*","*","*"," ","0","1","2","3","4","5","6","7","8","9","a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z"],ue.TEXT_SHIFT2_SET_CHARS=ue.C40_SHIFT2_SET_CHARS,ue.TEXT_SHIFT3_SET_CHARS=["`","A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z","{","|","}","~",String.fromCharCode(127)];class de{constructor(){this.rsDecoder=new tt(q.DATA_MATRIX_FIELD_256)}decode(t){const e=new ce(t),r=e.getVersion(),n=e.readCodewords(),i=le.getDataBlocks(n,r);let o=0;for(let t of i)o+=t.getNumDataCodewords();const s=new Uint8Array(o),a=i.length;for(let t=0;ts&&(l=s,h[0]=e,h[1]=r,h[2]=n,h[3]=i),l>a&&(l=a,h[0]=r,h[1]=n,h[2]=i,h[3]=e),l>c&&(h[0]=n,h[1]=i,h[2]=e,h[3]=r),h}detectSolid2(t){let e=t[0],r=t[1],n=t[2],i=t[3],o=this.transitionsBetween(e,i),s=fe.shiftPoint(r,n,4*(o+1)),a=fe.shiftPoint(n,r,4*(o+1));return this.transitionsBetween(s,e)this.transitionsBetween(a,h)+this.transitionsBetween(c,h)?l:h:l:this.isValid(h)?h:null}shiftToModuleCenter(t){let e=t[0],r=t[1],n=t[2],i=t[3],o=this.transitionsBetween(e,i)+1,s=this.transitionsBetween(n,i)+1,a=fe.shiftPoint(e,r,4*s),c=fe.shiftPoint(n,r,4*o);o=this.transitionsBetween(a,i)+1,s=this.transitionsBetween(c,i)+1,1==(1&o)&&(o+=1),1==(1&s)&&(s+=1);let l,h,u=(e.getX()+r.getX()+n.getX()+i.getX())/4,d=(e.getY()+r.getY()+n.getY()+i.getY())/4;return e=fe.moveAway(e,u,d),r=fe.moveAway(r,u,d),n=fe.moveAway(n,u,d),i=fe.moveAway(i,u,d),a=fe.shiftPoint(e,r,4*s),a=fe.shiftPoint(a,i,4*o),l=fe.shiftPoint(r,e,4*s),l=fe.shiftPoint(l,n,4*o),c=fe.shiftPoint(n,i,4*s),c=fe.shiftPoint(c,r,4*o),h=fe.shiftPoint(i,n,4*s),h=fe.shiftPoint(h,e,4*o),[a,l,c,h]}isValid(t){return t.getX()>=0&&t.getX()0&&t.getY()Math.abs(i-r);if(s){let t=r;r=n,n=t,t=i,i=o,o=t}let a=Math.abs(i-r),c=Math.abs(o-n),l=-a/2,h=n0){if(e===o)break;e+=h,l-=a}}return d}}class ge{constructor(){this.decoder=new de}decode(t,e=null){let r,n;if(null!=e&&e.has(C.PURE_BARCODE)){const e=ge.extractPureBits(t.getBlackMatrix());r=this.decoder.decode(e),n=ge.NO_POINTS}else{const e=new fe(t.getBlackMatrix()).detect();r=this.decoder.decode(e.getBits()),n=e.getPoints()}const i=r.getRawBytes(),o=new x(r.getText(),i,8*i.length,n,U.DATA_MATRIX,d.currentTimeMillis()),s=r.getByteSegments();null!=s&&o.putMetadata(W.BYTE_SEGMENTS,s);const a=r.getECLevel();return null!=a&&o.putMetadata(W.ERROR_CORRECTION_LEVEL,a),o}reset(){}static extractPureBits(t){const e=t.getTopLeftOnBit(),r=t.getBottomRightOnBit();if(null==e||null==r)throw new D;const n=this.moduleSize(e,t);let i=e[1];const o=r[1];let s=e[0];const a=(r[0]-s+1)/n,c=(o-i+1)/n;if(a<=0||c<=0)throw new D;const l=n/2;i+=l,s+=l;const h=new N(a,c);for(let e=0;e=we.FOR_BITS.size)throw new c;return we.FOR_BITS.get(t)}}we.FOR_BITS=new Map,we.FOR_VALUE=new Map,we.L=new we(z.L,"L",1),we.M=new we(z.M,"M",0),we.Q=new we(z.Q,"Q",3),we.H=new we(z.H,"H",2);class me{constructor(t){this.errorCorrectionLevel=we.forBits(t>>3&3),this.dataMask=7&t}static numBitsDiffering(t,e){return m.bitCount(t^e)}static decodeFormatInformation(t,e){const r=me.doDecodeFormatInformation(t,e);return null!==r?r:me.doDecodeFormatInformation(t^me.FORMAT_INFO_MASK_QR,e^me.FORMAT_INFO_MASK_QR)}static doDecodeFormatInformation(t,e){let r=Number.MAX_SAFE_INTEGER,n=0;for(const i of me.FORMAT_INFO_DECODE_LOOKUP){const o=i[0];if(o===t||o===e)return new me(i[1]);let s=me.numBitsDiffering(t,o);s40)throw new c;return Ce.VERSIONS[t-1]}static decodeVersionInformation(t){let e=Number.MAX_SAFE_INTEGER,r=0;for(let n=0;n6&&(e.setRegion(t-11,0,3,6),e.setRegion(0,t-11,6,3)),e}toString(){return""+this.versionNumber}}Ce.VERSION_DECODE_INFO=Int32Array.from([31892,34236,39577,42195,48118,51042,55367,58893,63784,68472,70749,76311,79154,84390,87683,92361,96236,102084,102881,110507,110734,117786,119615,126325,127568,133589,136944,141498,145311,150283,152622,158308,161089,167017]),Ce.VERSIONS=[new Ce(1,new Int32Array(0),new pe(7,new Ae(1,19)),new pe(10,new Ae(1,16)),new pe(13,new Ae(1,13)),new pe(17,new Ae(1,9))),new Ce(2,Int32Array.from([6,18]),new pe(10,new Ae(1,34)),new pe(16,new Ae(1,28)),new pe(22,new Ae(1,22)),new pe(28,new Ae(1,16))),new Ce(3,Int32Array.from([6,22]),new pe(15,new Ae(1,55)),new pe(26,new Ae(1,44)),new pe(18,new Ae(2,17)),new pe(22,new Ae(2,13))),new Ce(4,Int32Array.from([6,26]),new pe(20,new Ae(1,80)),new pe(18,new Ae(2,32)),new pe(26,new Ae(2,24)),new pe(16,new Ae(4,9))),new Ce(5,Int32Array.from([6,30]),new pe(26,new Ae(1,108)),new pe(24,new Ae(2,43)),new pe(18,new Ae(2,15),new Ae(2,16)),new pe(22,new Ae(2,11),new Ae(2,12))),new Ce(6,Int32Array.from([6,34]),new pe(18,new Ae(2,68)),new pe(16,new Ae(4,27)),new pe(24,new Ae(4,19)),new pe(28,new Ae(4,15))),new Ce(7,Int32Array.from([6,22,38]),new pe(20,new Ae(2,78)),new pe(18,new Ae(4,31)),new pe(18,new Ae(2,14),new Ae(4,15)),new pe(26,new Ae(4,13),new Ae(1,14))),new Ce(8,Int32Array.from([6,24,42]),new pe(24,new Ae(2,97)),new pe(22,new Ae(2,38),new Ae(2,39)),new pe(22,new Ae(4,18),new Ae(2,19)),new pe(26,new Ae(4,14),new Ae(2,15))),new Ce(9,Int32Array.from([6,26,46]),new pe(30,new Ae(2,116)),new pe(22,new Ae(3,36),new Ae(2,37)),new pe(20,new Ae(4,16),new Ae(4,17)),new pe(24,new Ae(4,12),new Ae(4,13))),new Ce(10,Int32Array.from([6,28,50]),new pe(18,new Ae(2,68),new Ae(2,69)),new pe(26,new Ae(4,43),new Ae(1,44)),new pe(24,new Ae(6,19),new Ae(2,20)),new pe(28,new Ae(6,15),new Ae(2,16))),new Ce(11,Int32Array.from([6,30,54]),new pe(20,new Ae(4,81)),new pe(30,new Ae(1,50),new Ae(4,51)),new pe(28,new Ae(4,22),new Ae(4,23)),new pe(24,new Ae(3,12),new Ae(8,13))),new Ce(12,Int32Array.from([6,32,58]),new pe(24,new Ae(2,92),new Ae(2,93)),new pe(22,new Ae(6,36),new Ae(2,37)),new pe(26,new Ae(4,20),new Ae(6,21)),new pe(28,new Ae(7,14),new Ae(4,15))),new Ce(13,Int32Array.from([6,34,62]),new pe(26,new Ae(4,107)),new pe(22,new Ae(8,37),new Ae(1,38)),new pe(24,new Ae(8,20),new Ae(4,21)),new pe(22,new Ae(12,11),new Ae(4,12))),new Ce(14,Int32Array.from([6,26,46,66]),new pe(30,new Ae(3,115),new Ae(1,116)),new pe(24,new Ae(4,40),new Ae(5,41)),new pe(20,new Ae(11,16),new Ae(5,17)),new pe(24,new Ae(11,12),new Ae(5,13))),new Ce(15,Int32Array.from([6,26,48,70]),new pe(22,new Ae(5,87),new Ae(1,88)),new pe(24,new Ae(5,41),new Ae(5,42)),new pe(30,new Ae(5,24),new Ae(7,25)),new pe(24,new Ae(11,12),new Ae(7,13))),new Ce(16,Int32Array.from([6,26,50,74]),new pe(24,new Ae(5,98),new Ae(1,99)),new pe(28,new Ae(7,45),new Ae(3,46)),new pe(24,new Ae(15,19),new Ae(2,20)),new pe(30,new Ae(3,15),new Ae(13,16))),new Ce(17,Int32Array.from([6,30,54,78]),new pe(28,new Ae(1,107),new Ae(5,108)),new pe(28,new Ae(10,46),new Ae(1,47)),new pe(28,new Ae(1,22),new Ae(15,23)),new pe(28,new Ae(2,14),new Ae(17,15))),new Ce(18,Int32Array.from([6,30,56,82]),new pe(30,new Ae(5,120),new Ae(1,121)),new pe(26,new Ae(9,43),new Ae(4,44)),new pe(28,new Ae(17,22),new Ae(1,23)),new pe(28,new Ae(2,14),new Ae(19,15))),new Ce(19,Int32Array.from([6,30,58,86]),new pe(28,new Ae(3,113),new Ae(4,114)),new pe(26,new Ae(3,44),new Ae(11,45)),new pe(26,new Ae(17,21),new Ae(4,22)),new pe(26,new Ae(9,13),new Ae(16,14))),new Ce(20,Int32Array.from([6,34,62,90]),new pe(28,new Ae(3,107),new Ae(5,108)),new pe(26,new Ae(3,41),new Ae(13,42)),new pe(30,new Ae(15,24),new Ae(5,25)),new pe(28,new Ae(15,15),new Ae(10,16))),new Ce(21,Int32Array.from([6,28,50,72,94]),new pe(28,new Ae(4,116),new Ae(4,117)),new pe(26,new Ae(17,42)),new pe(28,new Ae(17,22),new Ae(6,23)),new pe(30,new Ae(19,16),new Ae(6,17))),new Ce(22,Int32Array.from([6,26,50,74,98]),new pe(28,new Ae(2,111),new Ae(7,112)),new pe(28,new Ae(17,46)),new pe(30,new Ae(7,24),new Ae(16,25)),new pe(24,new Ae(34,13))),new Ce(23,Int32Array.from([6,30,54,78,102]),new pe(30,new Ae(4,121),new Ae(5,122)),new pe(28,new Ae(4,47),new Ae(14,48)),new pe(30,new Ae(11,24),new Ae(14,25)),new pe(30,new Ae(16,15),new Ae(14,16))),new Ce(24,Int32Array.from([6,28,54,80,106]),new pe(30,new Ae(6,117),new Ae(4,118)),new pe(28,new Ae(6,45),new Ae(14,46)),new pe(30,new Ae(11,24),new Ae(16,25)),new pe(30,new Ae(30,16),new Ae(2,17))),new Ce(25,Int32Array.from([6,32,58,84,110]),new pe(26,new Ae(8,106),new Ae(4,107)),new pe(28,new Ae(8,47),new Ae(13,48)),new pe(30,new Ae(7,24),new Ae(22,25)),new pe(30,new Ae(22,15),new Ae(13,16))),new Ce(26,Int32Array.from([6,30,58,86,114]),new pe(28,new Ae(10,114),new Ae(2,115)),new pe(28,new Ae(19,46),new Ae(4,47)),new pe(28,new Ae(28,22),new Ae(6,23)),new pe(30,new Ae(33,16),new Ae(4,17))),new Ce(27,Int32Array.from([6,34,62,90,118]),new pe(30,new Ae(8,122),new Ae(4,123)),new pe(28,new Ae(22,45),new Ae(3,46)),new pe(30,new Ae(8,23),new Ae(26,24)),new pe(30,new Ae(12,15),new Ae(28,16))),new Ce(28,Int32Array.from([6,26,50,74,98,122]),new pe(30,new Ae(3,117),new Ae(10,118)),new pe(28,new Ae(3,45),new Ae(23,46)),new pe(30,new Ae(4,24),new Ae(31,25)),new pe(30,new Ae(11,15),new Ae(31,16))),new Ce(29,Int32Array.from([6,30,54,78,102,126]),new pe(30,new Ae(7,116),new Ae(7,117)),new pe(28,new Ae(21,45),new Ae(7,46)),new pe(30,new Ae(1,23),new Ae(37,24)),new pe(30,new Ae(19,15),new Ae(26,16))),new Ce(30,Int32Array.from([6,26,52,78,104,130]),new pe(30,new Ae(5,115),new Ae(10,116)),new pe(28,new Ae(19,47),new Ae(10,48)),new pe(30,new Ae(15,24),new Ae(25,25)),new pe(30,new Ae(23,15),new Ae(25,16))),new Ce(31,Int32Array.from([6,30,56,82,108,134]),new pe(30,new Ae(13,115),new Ae(3,116)),new pe(28,new Ae(2,46),new Ae(29,47)),new pe(30,new Ae(42,24),new Ae(1,25)),new pe(30,new Ae(23,15),new Ae(28,16))),new Ce(32,Int32Array.from([6,34,60,86,112,138]),new pe(30,new Ae(17,115)),new pe(28,new Ae(10,46),new Ae(23,47)),new pe(30,new Ae(10,24),new Ae(35,25)),new pe(30,new Ae(19,15),new Ae(35,16))),new Ce(33,Int32Array.from([6,30,58,86,114,142]),new pe(30,new Ae(17,115),new Ae(1,116)),new pe(28,new Ae(14,46),new Ae(21,47)),new pe(30,new Ae(29,24),new Ae(19,25)),new pe(30,new Ae(11,15),new Ae(46,16))),new Ce(34,Int32Array.from([6,34,62,90,118,146]),new pe(30,new Ae(13,115),new Ae(6,116)),new pe(28,new Ae(14,46),new Ae(23,47)),new pe(30,new Ae(44,24),new Ae(7,25)),new pe(30,new Ae(59,16),new Ae(1,17))),new Ce(35,Int32Array.from([6,30,54,78,102,126,150]),new pe(30,new Ae(12,121),new Ae(7,122)),new pe(28,new Ae(12,47),new Ae(26,48)),new pe(30,new Ae(39,24),new Ae(14,25)),new pe(30,new Ae(22,15),new Ae(41,16))),new Ce(36,Int32Array.from([6,24,50,76,102,128,154]),new pe(30,new Ae(6,121),new Ae(14,122)),new pe(28,new Ae(6,47),new Ae(34,48)),new pe(30,new Ae(46,24),new Ae(10,25)),new pe(30,new Ae(2,15),new Ae(64,16))),new Ce(37,Int32Array.from([6,28,54,80,106,132,158]),new pe(30,new Ae(17,122),new Ae(4,123)),new pe(28,new Ae(29,46),new Ae(14,47)),new pe(30,new Ae(49,24),new Ae(10,25)),new pe(30,new Ae(24,15),new Ae(46,16))),new Ce(38,Int32Array.from([6,32,58,84,110,136,162]),new pe(30,new Ae(4,122),new Ae(18,123)),new pe(28,new Ae(13,46),new Ae(32,47)),new pe(30,new Ae(48,24),new Ae(14,25)),new pe(30,new Ae(42,15),new Ae(32,16))),new Ce(39,Int32Array.from([6,26,54,82,110,138,166]),new pe(30,new Ae(20,117),new Ae(4,118)),new pe(28,new Ae(40,47),new Ae(7,48)),new pe(30,new Ae(43,24),new Ae(22,25)),new pe(30,new Ae(10,15),new Ae(67,16))),new Ce(40,Int32Array.from([6,30,58,86,114,142,170]),new pe(30,new Ae(19,118),new Ae(6,119)),new pe(28,new Ae(18,47),new Ae(31,48)),new pe(30,new Ae(34,24),new Ae(34,25)),new pe(30,new Ae(20,15),new Ae(61,16)))],function(t){t[t.DATA_MASK_000=0]="DATA_MASK_000",t[t.DATA_MASK_001=1]="DATA_MASK_001",t[t.DATA_MASK_010=2]="DATA_MASK_010",t[t.DATA_MASK_011=3]="DATA_MASK_011",t[t.DATA_MASK_100=4]="DATA_MASK_100",t[t.DATA_MASK_101=5]="DATA_MASK_101",t[t.DATA_MASK_110=6]="DATA_MASK_110",t[t.DATA_MASK_111=7]="DATA_MASK_111"}(G||(G={}));class Ee{constructor(t,e){this.value=t,this.isMasked=e}unmaskBitMatrix(t,e){for(let r=0;r0==(t+e&1)))],[G.DATA_MASK_001,new Ee(G.DATA_MASK_001,((t,e)=>0==(1&t)))],[G.DATA_MASK_010,new Ee(G.DATA_MASK_010,((t,e)=>e%3==0))],[G.DATA_MASK_011,new Ee(G.DATA_MASK_011,((t,e)=>(t+e)%3==0))],[G.DATA_MASK_100,new Ee(G.DATA_MASK_100,((t,e)=>0==(Math.floor(t/2)+Math.floor(e/3)&1)))],[G.DATA_MASK_101,new Ee(G.DATA_MASK_101,((t,e)=>t*e%6==0))],[G.DATA_MASK_110,new Ee(G.DATA_MASK_110,((t,e)=>t*e%6<3))],[G.DATA_MASK_111,new Ee(G.DATA_MASK_111,((t,e)=>0==(t+e+t*e%3&1)))]]);class Ie{constructor(t){const e=t.getHeight();if(e<21||1!=(3&e))throw new E;this.bitMatrix=t}readFormatInformation(){if(null!==this.parsedFormatInfo&&void 0!==this.parsedFormatInfo)return this.parsedFormatInfo;let t=0;for(let e=0;e<6;e++)t=this.copyBit(e,8,t);t=this.copyBit(7,8,t),t=this.copyBit(8,8,t),t=this.copyBit(8,7,t);for(let e=5;e>=0;e--)t=this.copyBit(8,e,t);const e=this.bitMatrix.getHeight();let r=0;const n=e-7;for(let t=e-1;t>=n;t--)r=this.copyBit(8,t,r);for(let t=e-8;t=0;e--)for(let i=t-9;i>=n;i--)r=this.copyBit(i,e,r);let i=Ce.decodeVersionInformation(r);if(null!==i&&i.getDimensionForVersion()===t)return this.parsedVersion=i,i;r=0;for(let e=5;e>=0;e--)for(let i=t-9;i>=n;i--)r=this.copyBit(e,i,r);if(i=Ce.decodeVersionInformation(r),null!==i&&i.getDimensionForVersion()===t)return this.parsedVersion=i,i;throw new E}copyBit(t,e,r){return(this.isMirror?this.bitMatrix.get(e,t):this.bitMatrix.get(t,e))?r<<1|1:r<<1}readCodewords(){const t=this.readFormatInformation(),e=this.readVersion(),r=Ee.values.get(t.getDataMask()),n=this.bitMatrix.getHeight();r.unmaskBitMatrix(this.bitMatrix,n);const i=e.buildFunctionPattern();let o=!0;const s=new Uint8Array(e.getTotalCodewords());let a=0,c=0,l=0;for(let t=n-1;t>0;t-=2){6===t&&t--;for(let e=0;e=0&&s[h].codewords.length!==l;)h--;h++;const u=l-n.getECCodewordsPerBlock();let d=0;for(let e=0;et.available())throw new E;const n=new Uint8Array(2*r);let i=0;for(;r>0;){const e=t.readBits(13);let o=e/96<<8&4294967295|e%96;o+=o<959?41377:42657,n[i]=o>>8&255,n[i+1]=255&o,i+=2,r--}try{e.append(_.decode(n,T.GB2312))}catch(t){throw new E(t)}}static decodeKanjiSegment(t,e,r){if(13*r>t.available())throw new E;const n=new Uint8Array(2*r);let i=0;for(;r>0;){const e=t.readBits(13);let o=e/192<<8&4294967295|e%192;o+=o<7936?33088:49472,n[i]=o>>8,n[i+1]=o,i+=2,r--}try{e.append(_.decode(n,T.SHIFT_JIS))}catch(t){throw new E(t)}}static decodeByteSegment(t,e,r,n,i,o){if(8*r>t.available())throw new E;const s=new Uint8Array(r);for(let e=0;e=Te.ALPHANUMERIC_CHARS.length)throw new E;return Te.ALPHANUMERIC_CHARS[t]}static decodeAlphanumericSegment(t,e,r,n){const i=e.length();for(;r>1;){if(t.available()<11)throw new E;const n=t.readBits(11);e.append(Te.toAlphaNumericChar(Math.floor(n/45))),e.append(Te.toAlphaNumericChar(n%45)),r-=2}if(1===r){if(t.available()<6)throw new E;e.append(Te.toAlphaNumericChar(t.readBits(6)))}if(n)for(let t=i;t=3;){if(t.available()<10)throw new E;const n=t.readBits(10);if(n>=1e3)throw new E;e.append(Te.toAlphaNumericChar(Math.floor(n/100))),e.append(Te.toAlphaNumericChar(Math.floor(n/10)%10)),e.append(Te.toAlphaNumericChar(n%10)),r-=3}if(2===r){if(t.available()<7)throw new E;const r=t.readBits(7);if(r>=100)throw new E;e.append(Te.toAlphaNumericChar(Math.floor(r/10))),e.append(Te.toAlphaNumericChar(r%10))}else if(1===r){if(t.available()<4)throw new E;const r=t.readBits(4);if(r>=10)throw new E;e.append(Te.toAlphaNumericChar(r))}}static parseECIValue(t){const e=t.readBits(8);if(0==(128&e))return 127&e;if(128==(192&e))return(63&e)<<8&4294967295|t.readBits(8);if(192==(224&e))return(31&e)<<16&4294967295|t.readBits(16);throw new E}}Te.ALPHANUMERIC_CHARS="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./:",Te.GB2312_SUBSET=1;class ye{constructor(t){this.mirrored=t}isMirrored(){return this.mirrored}applyMirroredCorrection(t){if(!this.mirrored||null===t||t.length<3)return;const e=t[0];t[0]=t[2],t[2]=e}}class Ne{constructor(){this.rsDecoder=new tt(q.QR_CODE_FIELD_256)}decodeBooleanArray(t,e){return this.decodeBitMatrix(N.parseFromBooleanArray(t),e)}decodeBitMatrix(t,e){const r=new Ie(t);let n=null;try{return this.decodeBitMatrixParser(r,e)}catch(t){n=t}try{r.remask(),r.setMirror(!0),r.readVersion(),r.readFormatInformation(),r.mirror();const t=this.decodeBitMatrixParser(r,e);return t.setOther(new ye(!0)),t}catch(t){if(null!==n)throw n;throw t}}decodeBitMatrixParser(t,e){const r=t.readVersion(),n=t.readFormatInformation().getErrorCorrectionLevel(),i=t.readCodewords(),o=Se.getDataBlocks(i,r,n);let s=0;for(const t of o)s+=t.getNumDataCodewords();const a=new Uint8Array(s);let c=0;for(const t of o){const e=t.getCodewords(),r=t.getNumDataCodewords();this.correctErrors(e,r);for(let t=0;t=r)return!1;return!0}crossCheckVertical(t,e,r,n){const i=this.image,o=i.getHeight(),s=this.crossCheckStateCount;s[0]=0,s[1]=0,s[2]=0;let a=t;for(;a>=0&&i.get(e,a)&&s[1]<=r;)s[1]++,a--;if(a<0||s[1]>r)return NaN;for(;a>=0&&!i.get(e,a)&&s[0]<=r;)s[0]++,a--;if(s[0]>r)return NaN;for(a=t+1;ar)return NaN;for(;ar)return NaN;const c=s[0]+s[1]+s[2];return 5*Math.abs(c-n)>=2*n?NaN:this.foundPatternCross(s)?Me.centerFromEnd(s,a):NaN}handlePossibleCenter(t,e,r){const n=t[0]+t[1]+t[2],i=Me.centerFromEnd(t,r),o=this.crossCheckVertical(e,i,2*t[1],n);if(!isNaN(o)){const e=(t[0]+t[1]+t[2])/3;for(const t of this.possibleCenters)if(t.aboutEquals(e,o,i))return t.combineEstimate(o,i,e);const r=new De(i,o,e);this.possibleCenters.push(r),null!==this.resultPointCallback&&void 0!==this.resultPointCallback&&this.resultPointCallback.foundPossibleResultPoint(r)}return null}}class Re extends it{constructor(t,e,r,n){super(t,e),this.estimatedModuleSize=r,this.count=n,void 0===n&&(this.count=1)}getEstimatedModuleSize(){return this.estimatedModuleSize}getCount(){return this.count}aboutEquals(t,e,r){if(Math.abs(e-this.getY())<=t&&Math.abs(r-this.getX())<=t){const e=Math.abs(t-this.estimatedModuleSize);return e<=1||e<=this.estimatedModuleSize}return!1}combineEstimate(t,e,r){const n=this.count+1,i=(this.count*this.getX()+e)/n,o=(this.count*this.getY()+t)/n,s=(this.count*this.estimatedModuleSize+r)/n;return new Re(i,o,s,n)}}class Oe{constructor(t){this.bottomLeft=t[0],this.topLeft=t[1],this.topRight=t[2]}getBottomLeft(){return this.bottomLeft}getTopLeft(){return this.topLeft}getTopRight(){return this.topRight}}class be{constructor(t,e){this.image=t,this.resultPointCallback=e,this.possibleCenters=[],this.crossCheckStateCount=new Int32Array(5),this.resultPointCallback=e}getImage(){return this.image}getPossibleCenters(){return this.possibleCenters}find(t){const e=null!=t&&void 0!==t.get(C.TRY_HARDER),r=null!=t&&void 0!==t.get(C.PURE_BARCODE),n=this.image,i=n.getHeight(),o=n.getWidth();let s=Math.floor(3*i/(4*be.MAX_MODULES));(sc[2]&&(t+=e-c[2]-s,i=o-1)}e=0,c[0]=0,c[1]=0,c[2]=0,c[3]=0,c[4]=0}else c[0]=c[2],c[1]=c[3],c[2]=c[4],c[3]=1,c[4]=0,e=3;else c[++e]++;else c[e]++;be.foundPatternCross(c)&&!0===this.handlePossibleCenter(c,t,o,r)&&(s=c[0],this.hasSkipped&&(a=this.haveMultiplyConfirmedCenters()))}const l=this.selectBestPatterns();return it.orderBestPatterns(l),new Oe(l)}static centerFromEnd(t,e){return e-t[4]-t[3]-t[2]/2}static foundPatternCross(t){let e=0;for(let r=0;r<5;r++){const n=t[r];if(0===n)return!1;e+=n}if(e<7)return!1;const r=e/7,n=r/2;return Math.abs(r-t[0])=o&&e>=o&&s.get(e-o,t-o);)i[2]++,o++;if(t=o&&e>=o&&!s.get(e-o,t-o)&&i[1]<=r;)i[1]++,o++;if(tr)return!1;for(;t>=o&&e>=o&&s.get(e-o,t-o)&&i[0]<=r;)i[0]++,o++;if(i[0]>r)return!1;const a=s.getHeight(),c=s.getWidth();for(o=1;t+o=a||e+o>=c)return!1;for(;t+o=a||e+o>=c||i[3]>=r)return!1;for(;t+o=r)return!1;const l=i[0]+i[1]+i[2]+i[3]+i[4];return Math.abs(l-n)<2*n&&be.foundPatternCross(i)}crossCheckVertical(t,e,r,n){const i=this.image,o=i.getHeight(),s=this.getCrossCheckStateCount();let a=t;for(;a>=0&&i.get(e,a);)s[2]++,a--;if(a<0)return NaN;for(;a>=0&&!i.get(e,a)&&s[1]<=r;)s[1]++,a--;if(a<0||s[1]>r)return NaN;for(;a>=0&&i.get(e,a)&&s[0]<=r;)s[0]++,a--;if(s[0]>r)return NaN;for(a=t+1;a=r)return NaN;for(;a=r)return NaN;const c=s[0]+s[1]+s[2]+s[3]+s[4];return 5*Math.abs(c-n)>=2*n?NaN:be.foundPatternCross(s)?be.centerFromEnd(s,a):NaN}crossCheckHorizontal(t,e,r,n){const i=this.image,o=i.getWidth(),s=this.getCrossCheckStateCount();let a=t;for(;a>=0&&i.get(a,e);)s[2]++,a--;if(a<0)return NaN;for(;a>=0&&!i.get(a,e)&&s[1]<=r;)s[1]++,a--;if(a<0||s[1]>r)return NaN;for(;a>=0&&i.get(a,e)&&s[0]<=r;)s[0]++,a--;if(s[0]>r)return NaN;for(a=t+1;a=r)return NaN;for(;a=r)return NaN;const c=s[0]+s[1]+s[2]+s[3]+s[4];return 5*Math.abs(c-n)>=n?NaN:be.foundPatternCross(s)?be.centerFromEnd(s,a):NaN}handlePossibleCenter(t,e,r,n){const i=t[0]+t[1]+t[2]+t[3]+t[4];let o=be.centerFromEnd(t,r),s=this.crossCheckVertical(e,Math.floor(o),t[2],i);if(!isNaN(s)&&(o=this.crossCheckHorizontal(Math.floor(o),Math.floor(s),t[2],i),!isNaN(o)&&(!n||this.crossCheckDiagonal(Math.floor(s),Math.floor(o),t[2],i)))){const t=i/7;let e=!1;const r=this.possibleCenters;for(let n=0,i=r.length;n=be.CENTER_QUORUM){if(null!=t)return this.hasSkipped=!0,Math.floor((Math.abs(t.getX()-e.getX())-Math.abs(t.getY()-e.getY()))/2);t=e}return 0}haveMultiplyConfirmedCenters(){let t=0,e=0;const r=this.possibleCenters.length;for(const r of this.possibleCenters)r.getCount()>=be.CENTER_QUORUM&&(t++,e+=r.getEstimatedModuleSize());if(t<3)return!1;const n=e/r;let i=0;for(const t of this.possibleCenters)i+=Math.abs(t.getEstimatedModuleSize()-n);return i<=.05*e}selectBestPatterns(){const t=this.possibleCenters.length;if(t<3)throw new D;const e=this.possibleCenters;let r;if(t>3){let n=0,i=0;for(const t of this.possibleCenters){const e=t.getEstimatedModuleSize();n+=e,i+=e*e}r=n/t;let o=Math.sqrt(i/t-r*r);e.sort(((t,e)=>{const n=Math.abs(e.getEstimatedModuleSize()-r),i=Math.abs(t.getEstimatedModuleSize()-r);return ni?1:0}));const s=Math.max(.2*r,o);for(let t=0;t3;t++){const n=e[t];Math.abs(n.getEstimatedModuleSize()-r)>s&&(e.splice(t,1),t--)}}if(e.length>3){let t=0;for(const r of e)t+=r.getEstimatedModuleSize();r=t/e.length,e.sort(((t,e)=>{if(e.getCount()===t.getCount()){const n=Math.abs(e.getEstimatedModuleSize()-r),i=Math.abs(t.getEstimatedModuleSize()-r);return ni?-1:0}return e.getCount()-t.getCount()})),e.splice(3)}return[e[0],e[1],e[2]]}}be.CENTER_QUORUM=2,be.MIN_SKIP=3,be.MAX_MODULES=57;class Be{constructor(t){this.image=t}getImage(){return this.image}getResultPointCallback(){return this.resultPointCallback}detect(t){this.resultPointCallback=null==t?null:t.get(C.NEED_RESULT_POINT_CALLBACK);const e=new be(this.image,this.resultPointCallback).find(t);return this.processFinderPatternInfo(e)}processFinderPatternInfo(t){const e=t.getTopLeft(),r=t.getTopRight(),n=t.getBottomLeft(),i=this.calculateModuleSize(e,r,n);if(i<1)throw new D("No pattern found in proccess finder.");const o=Be.computeDimension(e,r,n,i),s=Ce.getProvisionalVersionForDimension(o),a=s.getDimensionForVersion()-7;let c=null;if(s.getAlignmentPatternCenters().length>0){const t=r.getX()-e.getX()+n.getX(),o=r.getY()-e.getY()+n.getY(),s=1-3/a,l=Math.floor(e.getX()+s*(t-e.getX())),h=Math.floor(e.getY()+s*(o-e.getY()));for(let t=4;t<=16;t<<=1)try{c=this.findAlignmentInRegion(i,l,h,t);break}catch(t){if(!(t instanceof D))throw t}}const l=Be.createTransform(e,r,n,c,o),h=Be.sampleGrid(this.image,l,o);let u;return u=null===c?[n,e,r]:[n,e,r,c],new ot(h,u)}static createTransform(t,e,r,n,i){const o=i-3.5;let s,a,c,l;return null!==n?(s=n.getX(),a=n.getY(),c=o-3,l=c):(s=e.getX()-t.getX()+r.getX(),a=e.getY()-t.getY()+r.getY(),c=o,l=o),lt.quadrilateralToQuadrilateral(3.5,3.5,o,3.5,c,l,3.5,o,t.getX(),t.getY(),e.getX(),e.getY(),s,a,r.getX(),r.getY())}static sampleGrid(t,e,r){return ut.getInstance().sampleGridWithTransform(t,r,r,e)}static computeDimension(t,e,r,n){const i=rt.round(it.distance(t,e)/n),o=rt.round(it.distance(t,r)/n);let s=Math.floor((i+o)/2)+7;switch(3&s){case 0:s++;break;case 2:s--;break;case 3:throw new D("Dimensions could be not found.")}return s}calculateModuleSize(t,e,r){return(this.calculateModuleSizeOneWay(t,e)+this.calculateModuleSizeOneWay(t,r))/2}calculateModuleSizeOneWay(t,e){const r=this.sizeOfBlackWhiteBlackRunBothWays(Math.floor(t.getX()),Math.floor(t.getY()),Math.floor(e.getX()),Math.floor(e.getY())),n=this.sizeOfBlackWhiteBlackRunBothWays(Math.floor(e.getX()),Math.floor(e.getY()),Math.floor(t.getX()),Math.floor(t.getY()));return isNaN(r)?n/7:isNaN(n)?r/7:(r+n)/14}sizeOfBlackWhiteBlackRunBothWays(t,e,r,n){let i=this.sizeOfBlackWhiteBlackRun(t,e,r,n),o=1,s=t-(r-t);s<0?(o=t/(t-s),s=0):s>=this.image.getWidth()&&(o=(this.image.getWidth()-1-t)/(s-t),s=this.image.getWidth()-1);let a=Math.floor(e-(n-e)*o);return o=1,a<0?(o=e/(e-a),a=0):a>=this.image.getHeight()&&(o=(this.image.getHeight()-1-e)/(a-e),a=this.image.getHeight()-1),s=Math.floor(t+(s-t)*o),i+=this.sizeOfBlackWhiteBlackRun(t,e,s,a),i-1}sizeOfBlackWhiteBlackRun(t,e,r,n){const i=Math.abs(n-e)>Math.abs(r-t);if(i){let i=t;t=e,e=i,i=r,r=n,n=i}const o=Math.abs(r-t),s=Math.abs(n-e);let a=-o/2;const c=t0){if(d===n)break;d+=l,a-=o}}return 2===h?rt.distance(r+c,n,t,e):NaN}findAlignmentInRegion(t,e,r,n){const i=Math.floor(n*t),o=Math.max(0,e-i),s=Math.min(this.image.getWidth()-1,e+i);if(s-o<3*t)throw new D("Alignment top exceeds estimated module size.");const a=Math.max(0,r-i),c=Math.min(this.image.getHeight()-1,r+i);if(c-a<3*t)throw new D("Alignment bottom exceeds estimated module size.");return new Me(this.image,o,a,s-o,c-a,t,this.resultPointCallback).find()}}class Le{constructor(){this.decoder=new Ne}getDecoder(){return this.decoder}decode(t,e){let r,n;if(null!=e&&void 0!==e.get(C.PURE_BARCODE)){const i=Le.extractPureBits(t.getBlackMatrix());r=this.decoder.decodeBitMatrix(i,e),n=Le.NO_POINTS}else{const i=new Be(t.getBlackMatrix()).detect(e);r=this.decoder.decodeBitMatrix(i.getBits(),e),n=i.getPoints()}r.getOther()instanceof ye&&r.getOther().applyMirroredCorrection(n);const i=new x(r.getText(),r.getRawBytes(),void 0,n,U.QR_CODE,void 0),o=r.getByteSegments();null!==o&&i.putMetadata(W.BYTE_SEGMENTS,o);const s=r.getECLevel();return null!==s&&i.putMetadata(W.ERROR_CORRECTION_LEVEL,s),r.hasStructuredAppend()&&(i.putMetadata(W.STRUCTURED_APPEND_SEQUENCE,r.getStructuredAppendSequenceNumber()),i.putMetadata(W.STRUCTURED_APPEND_PARITY,r.getStructuredAppendParity())),i}reset(){}static extractPureBits(t){const e=t.getTopLeftOnBit(),r=t.getBottomRightOnBit();if(null===e||null===r)throw new D;const n=this.moduleSize(e,t);let i=e[1],o=r[1],s=e[0],a=r[0];if(s>=a||i>=o)throw new D;if(o-i!=a-s&&(a=s+(o-i),a>=t.getWidth()))throw new D;const c=Math.round((a-s+1)/n),l=Math.round((o-i+1)/n);if(c<=0||l<=0)throw new D;if(l!==c)throw new D;const h=Math.floor(n/2);i+=h,s+=h;const u=s+Math.floor((c-1)*n)-a;if(u>0){if(u>h)throw new D;s-=u}const d=i+Math.floor((l-1)*n)-o;if(d>0){if(d>h)throw new D;i-=d}const f=new N(c,l);for(let e=0;e0;){const s=Fe.findGuardPattern(t,i,--n,r,!1,o,c);if(null==s){n++;break}e=s}s[0]=new it(e[0],n),s[1]=new it(e[1],n),a=!0;break}}let l=n+1;if(a){let n=0,i=Int32Array.from([Math.trunc(s[0].getX()),Math.trunc(s[1].getX())]);for(;lFe.SKIPPED_ROW_COUNT_MAX)break;n++}}l-=n+1,s[2]=new it(i[0],l),s[3]=new it(i[1],l)}return l-n0&&c++o?n-o:o-n;if(c>r)return 1/0;a+=c}return a/i}}Fe.INDEXES_START_PATTERN=Int32Array.from([0,4,1,5]),Fe.INDEXES_STOP_PATTERN=Int32Array.from([6,2,7,3]),Fe.MAX_AVG_VARIANCE=.42,Fe.MAX_INDIVIDUAL_VARIANCE=.8,Fe.START_PATTERN=Int32Array.from([8,1,1,1,1,1,1,3]),Fe.STOP_PATTERN=Int32Array.from([7,1,1,3,1,1,1,2,1]),Fe.MAX_PIXEL_DRIFT=3,Fe.MAX_PATTERN_DRIFT=5,Fe.SKIPPED_ROW_COUNT_MAX=25,Fe.ROW_STEP=5,Fe.BARCODE_MIN_HEIGHT=10;class xe{constructor(t,e){if(0===e.length)throw new c;this.field=t;let r=e.length;if(r>1&&0===e[0]){let t=1;for(;tr.length){let t=e;e=r,r=t}let n=new Int32Array(r.length),i=r.length-e.length;d.arraycopy(r,0,n,0,i);for(let t=i;t=0;e--){let r=this.getCoefficient(e);0!==r&&(r<0?(t.append(" - "),r=-r):t.length()>0&&t.append(" + "),0!==e&&1===r||t.append(r),0!==e&&(1===e?t.append("x"):(t.append("x^"),t.append(e))))}return t.toString()}}class ke{add(t,e){return(t+e)%this.modulus}subtract(t,e){return(this.modulus+t-e)%this.modulus}exp(t){return this.expTable[t]}log(t){if(0===t)throw new c;return this.logTable[t]}inverse(t){if(0===t)throw new K;return this.expTable[this.modulus-this.logTable[t]-1]}multiply(t,e){return 0===t||0===e?0:this.expTable[(this.logTable[t]+this.logTable[e])%(this.modulus-1)]}getSize(){return this.modulus}equals(t){return t===this}}class Ue extends ke{constructor(t,e){super(),this.modulus=t,this.expTable=new Int32Array(t),this.logTable=new Int32Array(t);let r=1;for(let n=0;n0;t--){let r=n.evaluateAt(this.field.exp(t));i[e-t]=r,0!==r&&(o=!0)}if(!o)return 0;let s=this.field.getOne();if(null!=r)for(const e of r){let r=this.field.exp(t.length-1-e),n=new xe(this.field,new Int32Array([this.field.subtract(0,r),1]));s=s.multiply(n)}let a=new xe(this.field,i),c=this.runEuclideanAlgorithm(this.field.buildMonomial(e,1),a,e),l=c[0],u=c[1],d=this.findErrorLocations(l),f=this.findErrorMagnitudes(u,l,d);for(let e=0;e=Math.round(r/2);){let t=n,e=o;if(n=i,o=s,n.isZero())throw h.getChecksumInstance();i=t;let r=this.field.getZero(),a=n.getCoefficient(n.getDegree()),c=this.field.inverse(a);for(;i.getDegree()>=n.getDegree()&&!i.isZero();){let t=i.getDegree()-n.getDegree(),e=this.field.multiply(i.getCoefficient(i.getDegree()),c);r=r.add(this.field.buildMonomial(t,e)),i=i.subtract(n.multiplyByMonomial(t,e))}s=r.multiply(o).subtract(e).negative()}let a=s.getCoefficient(0);if(0===a)throw h.getChecksumInstance();let c=this.field.inverse(a);return[s.multiply(c),i.multiply(c)]}findErrorLocations(t){let e=t.getDegree(),r=new Int32Array(e),n=0;for(let i=1;i0){let e=r?this.topLeft:this.topRight,i=Math.trunc(e.getY()-t);i<0&&(i=0);let s=new it(e.getX(),i);r?n=s:o=s}if(e>0){let t=r?this.bottomLeft:this.bottomRight,n=Math.trunc(t.getY()+e);n>=this.image.getHeight()&&(n=this.image.getHeight()-1);let o=new it(t.getX(),n);r?i=o:s=o}return new Ve(this.image,n,i,o,s)}getMinX(){return this.minX}getMaxX(){return this.maxX}getMinY(){return this.minY}getMaxY(){return this.maxY}getTopLeft(){return this.topLeft}getTopRight(){return this.topRight}getBottomLeft(){return this.bottomLeft}getBottomRight(){return this.bottomRight}}class ze{constructor(t,e,r,n){this.columnCount=t,this.errorCorrectionLevel=n,this.rowCountUpperPart=e,this.rowCountLowerPart=r,this.rowCount=e+r}getColumnCount(){return this.columnCount}getErrorCorrectionLevel(){return this.errorCorrectionLevel}getRowCount(){return this.rowCount}getRowCountUpperPart(){return this.rowCountUpperPart}getRowCountLowerPart(){return this.rowCountLowerPart}}class Ge{constructor(){this.buffer=""}static form(t,e){let r=-1;return t.replace(/%(-)?(0?[0-9]+)?([.][0-9]+)?([#][0-9]+)?([scfpexd%])/g,(function(t,n,i,o,s,a){if("%%"===t)return"%";if(void 0===e[++r])return;t=o?parseInt(o.substr(1)):void 0;let c,l=s?parseInt(s.substr(1)):void 0;switch(a){case"s":c=e[r];break;case"c":c=e[r][0];break;case"f":c=parseFloat(e[r]).toFixed(t);break;case"p":c=parseFloat(e[r]).toPrecision(t);break;case"e":c=parseFloat(e[r]).toExponential(t);break;case"x":c=parseInt(e[r]).toString(l||16);break;case"d":c=parseFloat(parseInt(e[r],l||10).toPrecision(t)).toFixed(0)}c="object"==typeof c?JSON.stringify(c):(+c).toString(l);let h=parseInt(i),u=i&&i[0]+""=="0"?"0":" ";for(;c.length=0&&(e=this.codewords[n],null!=e))return e;if(n=this.imageRowToCodewordIndex(t)+r,nr,getValue:()=>n};i.getValue()>t?(t=i.getValue(),e=[],e.push(i.getKey())):i.getValue()===t&&e.push(i.getKey())}return Pe.toIntArray(e)}getConfidence(t){return this.values.get(t)}}class We extends Ye{constructor(t,e){super(t),this._isLeft=e}setRowNumbers(){for(let t of this.getCodewords())null!=t&&t.setRowNumberAsRowIndicatorColumn()}adjustCompleteIndicatorColumnRowNumbers(t){let e=this.getCodewords();this.setRowNumbers(),this.removeIncorrectCodewords(e,t);let r=this.getBoundingBox(),n=this._isLeft?r.getTopLeft():r.getTopRight(),i=this._isLeft?r.getBottomLeft():r.getBottomRight(),o=this.imageRowToCodewordIndex(Math.trunc(n.getY())),s=this.imageRowToCodewordIndex(Math.trunc(i.getY())),a=-1,c=1,l=0;for(let r=o;r=t.getRowCount()||i>r)e[r]=null;else{let t;t=c>2?(c-2)*i:i;let o=t>=r;for(let n=1;n<=t&&!o;n++)o=null!=e[r-n];o?e[r]=null:(a=n.getRowNumber(),l=1)}}}getRowHeights(){let t=this.getBarcodeMetadata();if(null==t)return null;this.adjustIncompleteIndicatorColumnRowNumbers(t);let e=new Int32Array(t.getRowCount());for(let t of this.getCodewords())if(null!=t){let r=t.getRowNumber();if(r>=e.length)continue;e[r]++}return e}adjustIncompleteIndicatorColumnRowNumbers(t){let e=this.getBoundingBox(),r=this._isLeft?e.getTopLeft():e.getTopRight(),n=this._isLeft?e.getBottomLeft():e.getBottomRight(),i=this.imageRowToCodewordIndex(Math.trunc(r.getY())),o=this.imageRowToCodewordIndex(Math.trunc(n.getY())),s=this.getCodewords(),a=-1;for(let e=i;e=t.getRowCount()?s[e]=null:a=r.getRowNumber())}}getBarcodeMetadata(){let t=this.getCodewords(),e=new Xe,r=new Xe,n=new Xe,i=new Xe;for(let o of t){if(null==o)continue;o.setRowNumberAsRowIndicatorColumn();let t=o.getValue()%30,s=o.getRowNumber();switch(this._isLeft||(s+=2),s%3){case 0:r.setValue(3*t+1);break;case 1:i.setValue(t/3),n.setValue(t%3);break;case 2:e.setValue(t+1)}}if(0===e.getValue().length||0===r.getValue().length||0===n.getValue().length||0===i.getValue().length||e.getValue()[0]<1||r.getValue()[0]+n.getValue()[0]Pe.MAX_ROWS_IN_BARCODE)return null;let o=new ze(e.getValue()[0],r.getValue()[0],n.getValue()[0],i.getValue()[0]);return this.removeIncorrectCodewords(t,o),o}removeIncorrectCodewords(t,e){for(let r=0;re.getRowCount())t[r]=null;else switch(this._isLeft||(o+=2),o%3){case 0:3*i+1!==e.getRowCountUpperPart()&&(t[r]=null);break;case 1:Math.trunc(i/3)===e.getErrorCorrectionLevel()&&i%3===e.getRowCountLowerPart()||(t[r]=null);break;case 2:i+1!==e.getColumnCount()&&(t[r]=null)}}}isLeft(){return this._isLeft}toString(){return"IsLeft: "+this._isLeft+"\n"+super.toString()}}class je{constructor(t,e){this.ADJUST_ROW_NUMBER_SKIP=2,this.barcodeMetadata=t,this.barcodeColumnCount=t.getColumnCount(),this.boundingBox=e,this.detectionResultColumns=new Array(this.barcodeColumnCount+2)}getDetectionResultColumns(){this.adjustIndicatorColumnRowNumbers(this.detectionResultColumns[0]),this.adjustIndicatorColumnRowNumbers(this.detectionResultColumns[this.barcodeColumnCount+1]);let t,e=Pe.MAX_CODEWORDS_IN_BARCODE;do{t=e,e=this.adjustRowNumbersAndGetCount()}while(e>0&&e0&&i0&&(s[0]=r[e-1],s[4]=i[e-1],s[5]=o[e-1]),e>1&&(s[8]=r[e-2],s[10]=i[e-2],s[11]=o[e-2]),e>=1;r=1&e,Qe.RATIOS_TABLE[t]||(Qe.RATIOS_TABLE[t]=new Array(Pe.BARS_IN_MODULE)),Qe.RATIOS_TABLE[t][Pe.BARS_IN_MODULE-n-1]=Math.fround(i/Pe.MODULES_IN_CODEWORD)}}this.bSymbolTableReady=!0}static getDecodedValue(t){let e=Qe.getDecodedCodewordValue(Qe.sampleBitCounts(t));return-1!==e?e:Qe.getClosestDecodedValue(t)}static sampleBitCounts(t){let e=rt.sum(t),r=new Int32Array(Pe.BARS_IN_MODULE),n=0,i=0;for(let o=0;o1)for(let n=0;n=n)break}enew Array(Pe.BARS_IN_MODULE)));class Ke{constructor(){this.segmentCount=-1,this.fileSize=-1,this.timestamp=-1,this.checksum=-1}getSegmentIndex(){return this.segmentIndex}setSegmentIndex(t){this.segmentIndex=t}getFileId(){return this.fileId}setFileId(t){this.fileId=t}getOptionalData(){return this.optionalData}setOptionalData(t){this.optionalData=t}isLastSegment(){return this.lastSegment}setLastSegment(t){this.lastSegment=t}getSegmentCount(){return this.segmentCount}setSegmentCount(t){this.segmentCount=t}getSender(){return this.sender||null}setSender(t){this.sender=t}getAddressee(){return this.addressee||null}setAddressee(t){this.addressee=t}getFileName(){return this.fileName}setFileName(t){this.fileName=t}getFileSize(){return this.fileSize}setFileSize(t){this.fileSize=t}getChecksum(){return this.checksum}setChecksum(t){this.checksum=t}getTimestamp(){return this.timestamp}setTimestamp(t){this.timestamp=t}}class qe{static parseLong(t,e=undefined){return parseInt(t,e)}}class Je extends s{}Je.kind="NullPointerException";class $e{writeBytes(t){this.writeBytesOffset(t,0,t.length)}writeBytesOffset(t,e,r){if(null==t)throw new Je;if(e<0||e>t.length||r<0||e+r>t.length||e+r<0)throw new f;if(0!==r)for(let n=0;n0&&this.grow(t)}grow(t){let e=this.buf.length<<1;if(e-t<0&&(e=t),e<0){if(t<0)throw new tr;e=m.MAX_VALUE}this.buf=w.copyOfUint8Array(this.buf,e)}write(t){this.ensureCapacity(this.count+1),this.buf[this.count]=t,this.count+=1}writeBytesOffset(t,e,r){if(e<0||e>t.length||r<0||e+r-t.length>0)throw new f;this.ensureCapacity(this.count+r),d.arraycopy(t,e,this.buf,this.count,r),this.count+=r}writeTo(t){t.writeBytesOffset(this.buf,0,this.count)}reset(){this.count=0}toByteArray(){return w.copyOfUint8Array(this.buf,this.count)}size(){return this.count}toString(t){return t?"string"==typeof t?this.toString_string(t):this.toString_number(t):this.toString_void()}toString_void(){return new String(this.buf).toString()}toString_string(t){return new String(this.buf).toString()}toString_number(t){return new String(this.buf).toString()}close(){}}function rr(){if("undefined"!=typeof window)return window.BigInt||null;if(void 0!==r.g)return r.g.BigInt||null;if("undefined"!=typeof self)return self.BigInt||null;throw new Error("Can't search globals for BigInt!")}let nr;function ir(t){if(void 0===nr&&(nr=rr()),null===nr)throw new Error("BigInt is not supported!");return nr(t)}!function(t){t[t.ALPHA=0]="ALPHA",t[t.LOWER=1]="LOWER",t[t.MIXED=2]="MIXED",t[t.PUNCT=3]="PUNCT",t[t.ALPHA_SHIFT=4]="ALPHA_SHIFT",t[t.PUNCT_SHIFT=5]="PUNCT_SHIFT"}(X||(X={}));class or{static decode(t,e){let r=new y(""),n=I.ISO8859_1;r.enableDecoding(n);let i=1,o=t[i++],s=new Ke;for(;it[0])throw E.getFormatInstance();let n=new Int32Array(or.NUMBER_OF_SEQUENCE_CODEWORDS);for(let r=0;r0){for(let t=0;t<6;++t)o.write(Number(ir(a)>>ir(8*(5-t))));a=0,s=0}}n===e[0]&&r0){for(let t=0;t<6;++t)o.write(Number(ir(a)>>ir(8*(5-t))));a=0,s=0}}}return i.append(_.decode(o.toByteArray(),r)),n}static numericCompaction(t,e,r){let n=0,i=!1,o=new Int32Array(or.MAX_NUMERIC_CODEWORDS);for(;e0&&(r.append(or.decodeBase900toBase10(o,n)),n=0)}return e}static decodeBase900toBase10(t,e){let r=ir(0);for(let n=0;n@[\\]_`~!\r\t,:\n-.$/\"|*()?{}'",or.MIXED_CHARS="0123456789&\r\t,:#-.$/+%*=^",or.EXP900=rr()?function(){let t=[];t[0]=ir(1);let e=ir(900);t[1]=e;for(let r=2;r<16;r++)t[r]=t[r-1]*e;return t}():[],or.NUMBER_OF_SEQUENCE_CODEWORDS=2;class sr{constructor(){}static decode(t,e,r,n,i,o,s){let a,c=new Ve(t,e,r,n,i),l=null,h=null;for(let r=!0;;r=!1){if(null!=e&&(l=sr.getRowIndicatorColumn(t,c,e,!0,o,s)),null!=n&&(h=sr.getRowIndicatorColumn(t,c,n,!1,o,s)),a=sr.merge(l,h),null==a)throw D.getNotFoundInstance();let i=a.getBoundingBox();if(!r||null==i||!(i.getMinY()c.getMaxY()))break;c=i}a.setBoundingBox(c);let u=a.getBarcodeColumnCount()+1;a.setDetectionResultColumn(0,l),a.setDetectionResultColumn(u,h);let d=null!=l;for(let e=1;e<=u;e++){let r,n=d?e:u-e;if(void 0!==a.getDetectionResultColumn(n))continue;r=0===n||n===u?new We(c,0===n):new Ye(c),a.setDetectionResultColumn(n,r);let i=-1,l=i;for(let e=c.getMinY();e<=c.getMaxY();e++){if(i=sr.getStartColumn(a,n,e,d),i<0||i>c.getMaxX()){if(-1===l)continue;i=l}let h=sr.detectCodeword(t,c.getMinX(),c.getMaxX(),d,i,e,o,s);null!=h&&(r.setCodeword(e,h),l=i,o=Math.min(o,h.getWidth()),s=Math.max(s,h.getWidth()))}}return sr.createDecoderResult(a)}static merge(t,e){if(null==t&&null==e)return null;let r=sr.getBarcodeMetadata(t,e);if(null==r)return null;let n=Ve.merge(sr.adjustBoundingBox(t),sr.adjustBoundingBox(e));return new je(r,n)}static adjustBoundingBox(t){if(null==t)return null;let e=t.getRowHeights();if(null==e)return null;let r=sr.getMax(e),n=0;for(let t of e)if(n+=r-t,t>0)break;let i=t.getCodewords();for(let t=0;n>0&&null==i[t];t++)n--;let o=0;for(let t=e.length-1;t>=0&&(o+=r-e[t],!(e[t]>0));t--);for(let t=i.length-1;o>0&&null==i[t];t--)o--;return t.getBoundingBox().addMissingRows(n,o,t.isLeft())}static getMax(t){let e=-1;for(let r of t)e=Math.max(e,r);return e}static getBarcodeMetadata(t,e){let r,n;return null==t||null==(r=t.getBarcodeMetadata())?null==e?null:e.getBarcodeMetadata():null==e||null==(n=e.getBarcodeMetadata())?r:r.getColumnCount()!==n.getColumnCount()&&r.getErrorCorrectionLevel()!==n.getErrorCorrectionLevel()&&r.getRowCount()!==n.getRowCount()?null:r}static getRowIndicatorColumn(t,e,r,n,i,o){let s=new We(e,n);for(let a=0;a<2;a++){let c=0===a?1:-1,l=Math.trunc(Math.trunc(r.getX()));for(let a=Math.trunc(Math.trunc(r.getY()));a<=e.getMaxY()&&a>=e.getMinY();a+=c){let e=sr.detectCodeword(t,0,t.getWidth(),n,l,a,i,o);null!=e&&(s.setCodeword(a,e),l=n?e.getStartX():e.getEndX())}}return s}static adjustCodewordCount(t,e){let r=e[0][1],n=r.getValue(),i=t.getBarcodeColumnCount()*t.getBarcodeRowCount()-sr.getNumberOfECCodeWords(t.getBarcodeECLevel());if(0===n.length){if(i<1||i>Pe.MAX_CODEWORDS_IN_BARCODE)throw D.getNotFoundInstance();r.setValue(i)}else n[0]!==i&&r.setValue(i)}static createDecoderResult(t){let e=sr.createBarcodeMatrix(t);sr.adjustCodewordCount(t,e);let r=new Array,n=new Int32Array(t.getBarcodeRowCount()*t.getBarcodeColumnCount()),i=[],o=new Array;for(let s=0;s0;){for(let t=0;tnew Array(t.getBarcodeColumnCount()+2)));for(let t=0;t=0){if(n>=e.length)continue;e[n][r].setValue(t.getValue())}}r++}return e}static isValidBarcodeColumn(t,e){return e>=0&&e<=t.getBarcodeColumnCount()+1}static getStartColumn(t,e,r,n){let i=n?1:-1,o=null;if(sr.isValidBarcodeColumn(t,e-i)&&(o=t.getDetectionResultColumn(e-i).getCodeword(r)),null!=o)return n?o.getEndX():o.getStartX();if(o=t.getDetectionResultColumn(e).getCodewordNearby(r),null!=o)return n?o.getStartX():o.getEndX();if(sr.isValidBarcodeColumn(t,e-i)&&(o=t.getDetectionResultColumn(e-i).getCodewordNearby(r)),null!=o)return n?o.getEndX():o.getStartX();let s=0;for(;sr.isValidBarcodeColumn(t,e-i);){e-=i;for(let r of t.getDetectionResultColumn(e).getCodewords())if(null!=r)return(n?r.getEndX():r.getStartX())+i*s*(r.getEndX()-r.getStartX());s++}return n?t.getBoundingBox().getMinX():t.getBoundingBox().getMaxX()}static detectCodeword(t,e,r,n,i,o,s,a){i=sr.adjustCodewordStartColumn(t,e,r,n,i,o);let c,l=sr.getModuleBitCount(t,e,r,n,i,o);if(null==l)return null;let h=rt.sum(l);if(n)c=i+h;else{for(let t=0;t=e)&&c=e:ssr.CODEWORD_SKEW_SIZE)return i;s+=a}a=-a,n=!n}return s}static checkCodewordSkew(t,e,r){return e-sr.CODEWORD_SKEW_SIZE<=t&&t<=r+sr.CODEWORD_SKEW_SIZE}static decodeCodewords(t,e,r){if(0===t.length)throw E.getFormatInstance();let n=1<r/2+sr.MAX_ERRORS||r<0||r>sr.MAX_EC_CODEWORDS)throw h.getChecksumInstance();return sr.errorCorrection.decode(t,r,e)}static verifyCodewordCount(t,e){if(t.length<4)throw E.getFormatInstance();let r=t[0];if(r>t.length)throw E.getFormatInstance();if(0===r){if(!(e>=1;return e}static getCodewordBucketNumber(t){return t instanceof Int32Array?this.getCodewordBucketNumber_Int32Array(t):this.getCodewordBucketNumber_number(t)}static getCodewordBucketNumber_number(t){return sr.getCodewordBucketNumber(sr.getBitCountForCodeword(t))}static getCodewordBucketNumber_Int32Array(t){return(t[0]-t[2]+t[4]-t[6]+9)%9}static toString(t){let e=new Ge;for(let r=0;rt))}static getMaxWidth(t,e){return null==t||null==e?0:Math.trunc(Math.abs(t.getX()-e.getX()))}static getMinWidth(t,e){return null==t||null==e?m.MAX_VALUE:Math.trunc(Math.abs(t.getX()-e.getX()))}static getMaxCodewordWidth(t){return Math.floor(Math.max(Math.max(ar.getMaxWidth(t[0],t[4]),ar.getMaxWidth(t[6],t[2])*Pe.MODULES_IN_CODEWORD/Pe.MODULES_IN_STOP_PATTERN),Math.max(ar.getMaxWidth(t[1],t[5]),ar.getMaxWidth(t[7],t[3])*Pe.MODULES_IN_CODEWORD/Pe.MODULES_IN_STOP_PATTERN)))}static getMinCodewordWidth(t){return Math.floor(Math.min(Math.min(ar.getMinWidth(t[0],t[4]),ar.getMinWidth(t[6],t[2])*Pe.MODULES_IN_CODEWORD/Pe.MODULES_IN_STOP_PATTERN),Math.min(ar.getMinWidth(t[1],t[5]),ar.getMinWidth(t[7],t[3])*Pe.MODULES_IN_CODEWORD/Pe.MODULES_IN_STOP_PATTERN)))}reset(){}}class cr extends s{}cr.kind="ReaderException";class lr{constructor(t,e){this.verbose=!0===t,e&&this.setHints(e)}decode(t,e){return e&&this.setHints(e),this.decodeInternal(t)}decodeWithState(t){return null!==this.readers&&void 0!==this.readers||this.setHints(null),this.decodeInternal(t)}setHints(t){this.hints=t;const r=!e(t)&&!0===t.get(C.TRY_HARDER),n=e(t)?null:t.get(C.POSSIBLE_FORMATS),i=new Array;if(!e(n)){const e=n.some((t=>t===U.UPC_A||t===U.UPC_E||t===U.EAN_13||t===U.EAN_8||t===U.CODABAR||t===U.CODE_39||t===U.CODE_93||t===U.CODE_128||t===U.ITF||t===U.RSS_14||t===U.RSS_EXPANDED));e&&!r&&i.push(new ie(t,this.verbose)),n.includes(U.QR_CODE)&&i.push(new Le),n.includes(U.DATA_MATRIX)&&i.push(new ge),n.includes(U.AZTEC)&&i.push(new gt),n.includes(U.PDF_417)&&i.push(new ar),e&&r&&i.push(new ie(t,this.verbose))}0===i.length&&(r||i.push(new ie(t,this.verbose)),i.push(new Le),i.push(new ge),i.push(new gt),i.push(new ar),r&&i.push(new ie(t,this.verbose))),this.readers=i}reset(){if(null!==this.readers)for(const t of this.readers)t.reset()}decodeInternal(t){if(null===this.readers)throw new cr("No readers where selected, nothing can be read.");for(const e of this.readers)try{return e.decode(t,this.hints)}catch(t){if(t instanceof cr)continue}throw new D("No MultiFormat Readers were able to detect the code.")}}var hr;!function(t){t[t.ERROR_CORRECTION=0]="ERROR_CORRECTION",t[t.CHARACTER_SET=1]="CHARACTER_SET",t[t.DATA_MATRIX_SHAPE=2]="DATA_MATRIX_SHAPE",t[t.MIN_SIZE=3]="MIN_SIZE",t[t.MAX_SIZE=4]="MAX_SIZE",t[t.MARGIN=5]="MARGIN",t[t.PDF417_COMPACT=6]="PDF417_COMPACT",t[t.PDF417_COMPACTION=7]="PDF417_COMPACTION",t[t.PDF417_DIMENSIONS=8]="PDF417_DIMENSIONS",t[t.AZTEC_LAYERS=9]="AZTEC_LAYERS",t[t.QR_VERSION=10]="QR_VERSION"}(hr||(hr={}));var ur=hr;class dr{constructor(t){this.field=t,this.cachedGenerators=[],this.cachedGenerators.push(new Q(t,Int32Array.from([1])))}buildGenerator(t){const e=this.cachedGenerators;if(t>=e.length){let r=e[e.length-1];const n=this.field;for(let i=e.length;i<=t;i++){const t=r.multiply(new Q(n,Int32Array.from([1,n.exp(i-1+n.getGeneratorBase())])));e.push(t),r=t}}return e[t]}encode(t,e){if(0===e)throw new c("No error correction bytes");const r=t.length-e;if(r<=0)throw new c("No data bytes provided");const n=this.buildGenerator(e),i=new Int32Array(r);d.arraycopy(t,0,i,0,r);let o=new Q(this.field,i);o=o.multiplyByMonomial(e,1);const s=o.divide(n)[1].getCoefficients(),a=e-s.length;for(let e=0;e=5&&(r+=fr.N1+(n-5)),n=1,s=i)}n>=5&&(r+=fr.N1+(n-5))}return r}}fr.N1=3,fr.N2=3,fr.N3=40,fr.N4=10;class gr{constructor(t,e){this.width=t,this.height=e;const r=new Array(e);for(let n=0;n!==e;n++)r[n]=new Uint8Array(t);this.bytes=r}getHeight(){return this.height}getWidth(){return this.width}get(t,e){return this.bytes[e][t]}getArray(){return this.bytes}setNumber(t,e,r){this.bytes[e][t]=r}setBoolean(t,e,r){this.bytes[e][t]=r?1:0}clear(t){for(const e of this.bytes)w.fill(e,t)}equals(t){if(!(t instanceof gr))return!1;const e=t;if(this.width!==e.width)return!1;if(this.height!==e.height)return!1;for(let t=0,r=this.height;t>\n"),t.toString()}setMode(t){this.mode=t}setECLevel(t){this.ecLevel=t}setVersion(t){this.version=t}setMaskPattern(t){this.maskPattern=t}setMatrix(t){this.matrix=t}static isValidMaskPattern(t){return t>=0&&t0;){for(6===o&&(o-=1);s>=0&&s=r;)t^=e<=0)for(let t=0;t!==r;t++){const r=n[t];r>=0&&pr.isEmpty(e.get(r,i))&&pr.embedPositionAdjustmentPattern(r-2,i-2,e)}}}}pr.POSITION_DETECTION_PATTERN=Array.from([Int32Array.from([1,1,1,1,1,1,1]),Int32Array.from([1,0,0,0,0,0,1]),Int32Array.from([1,0,1,1,1,0,1]),Int32Array.from([1,0,1,1,1,0,1]),Int32Array.from([1,0,1,1,1,0,1]),Int32Array.from([1,0,0,0,0,0,1]),Int32Array.from([1,1,1,1,1,1,1])]),pr.POSITION_ADJUSTMENT_PATTERN=Array.from([Int32Array.from([1,1,1,1,1]),Int32Array.from([1,0,0,0,1]),Int32Array.from([1,0,1,0,1]),Int32Array.from([1,0,0,0,1]),Int32Array.from([1,1,1,1,1])]),pr.POSITION_ADJUSTMENT_PATTERN_COORDINATE_TABLE=Array.from([Int32Array.from([-1,-1,-1,-1,-1,-1,-1]),Int32Array.from([6,18,-1,-1,-1,-1,-1]),Int32Array.from([6,22,-1,-1,-1,-1,-1]),Int32Array.from([6,26,-1,-1,-1,-1,-1]),Int32Array.from([6,30,-1,-1,-1,-1,-1]),Int32Array.from([6,34,-1,-1,-1,-1,-1]),Int32Array.from([6,22,38,-1,-1,-1,-1]),Int32Array.from([6,24,42,-1,-1,-1,-1]),Int32Array.from([6,26,46,-1,-1,-1,-1]),Int32Array.from([6,28,50,-1,-1,-1,-1]),Int32Array.from([6,30,54,-1,-1,-1,-1]),Int32Array.from([6,32,58,-1,-1,-1,-1]),Int32Array.from([6,34,62,-1,-1,-1,-1]),Int32Array.from([6,26,46,66,-1,-1,-1]),Int32Array.from([6,26,48,70,-1,-1,-1]),Int32Array.from([6,26,50,74,-1,-1,-1]),Int32Array.from([6,30,54,78,-1,-1,-1]),Int32Array.from([6,30,56,82,-1,-1,-1]),Int32Array.from([6,30,58,86,-1,-1,-1]),Int32Array.from([6,34,62,90,-1,-1,-1]),Int32Array.from([6,28,50,72,94,-1,-1]),Int32Array.from([6,26,50,74,98,-1,-1]),Int32Array.from([6,30,54,78,102,-1,-1]),Int32Array.from([6,28,54,80,106,-1,-1]),Int32Array.from([6,32,58,84,110,-1,-1]),Int32Array.from([6,30,58,86,114,-1,-1]),Int32Array.from([6,34,62,90,118,-1,-1]),Int32Array.from([6,26,50,74,98,122,-1]),Int32Array.from([6,30,54,78,102,126,-1]),Int32Array.from([6,26,52,78,104,130,-1]),Int32Array.from([6,30,56,82,108,134,-1]),Int32Array.from([6,34,60,86,112,138,-1]),Int32Array.from([6,30,58,86,114,142,-1]),Int32Array.from([6,34,62,90,118,146,-1]),Int32Array.from([6,30,54,78,102,126,150]),Int32Array.from([6,24,50,76,102,128,154]),Int32Array.from([6,28,54,80,106,132,158]),Int32Array.from([6,32,58,84,110,136,162]),Int32Array.from([6,26,54,82,110,138,166]),Int32Array.from([6,30,58,86,114,142,170])]),pr.TYPE_INFO_COORDINATES=Array.from([Int32Array.from([8,0]),Int32Array.from([8,1]),Int32Array.from([8,2]),Int32Array.from([8,3]),Int32Array.from([8,4]),Int32Array.from([8,5]),Int32Array.from([8,7]),Int32Array.from([8,8]),Int32Array.from([7,8]),Int32Array.from([5,8]),Int32Array.from([4,8]),Int32Array.from([3,8]),Int32Array.from([2,8]),Int32Array.from([1,8]),Int32Array.from([0,8])]),pr.VERSION_INFO_POLY=7973,pr.TYPE_INFO_POLY=1335,pr.TYPE_INFO_MASK_PATTERN=21522;class Ar{constructor(t,e){this.dataBytes=t,this.errorCorrectionBytes=e}getDataBytes(){return this.dataBytes}getErrorCorrectionBytes(){return this.errorCorrectionBytes}}class Cr{constructor(){}static calculateMaskPenalty(t){return fr.applyMaskPenaltyRule1(t)+fr.applyMaskPenaltyRule2(t)+fr.applyMaskPenaltyRule3(t)+fr.applyMaskPenaltyRule4(t)}static encode(t,e,r=null){let n=Cr.DEFAULT_BYTE_MODE_ENCODING;const i=null!==r&&void 0!==r.get(ur.CHARACTER_SET);i&&(n=r.get(ur.CHARACTER_SET).toString());const o=this.chooseMode(t,n),s=new p;if(o===_e.BYTE&&(i||Cr.DEFAULT_BYTE_MODE_ENCODING!==n)){const t=I.getCharacterSetECIByName(n);void 0!==t&&this.appendECI(t,s)}this.appendModeInfo(o,s);const a=new p;let c;if(this.appendBytes(t,o,a,n),null!==r&&void 0!==r.get(ur.QR_VERSION)){const t=Number.parseInt(r.get(ur.QR_VERSION).toString(),10);c=Ce.getVersionForNumber(t);const n=this.calculateBitsNeeded(o,s,a,c);if(!this.willFit(n,c,e))throw new mr("Data too big for requested version")}else c=this.recommendVersion(e,o,s,a);const l=new p;l.appendBitArray(s);const h=o===_e.BYTE?a.getSizeInBytes():t.length;this.appendLengthInfo(h,c,o,l),l.appendBitArray(a);const u=c.getECBlocksForLevel(e),d=c.getTotalCodewords()-u.getTotalECCodewords();this.terminateBits(d,l);const f=this.interleaveWithECBytes(l,c.getTotalCodewords(),d,u.getNumBlocks()),g=new wr;g.setECLevel(e),g.setMode(o),g.setVersion(c);const w=c.getDimensionForVersion(),m=new gr(w,w),A=this.chooseMaskPattern(f,e,c,m);return g.setMaskPattern(A),pr.buildMatrix(f,e,c,A,m),g.setMatrix(m),g}static recommendVersion(t,e,r,n){const i=this.calculateBitsNeeded(e,r,n,Ce.getVersionForNumber(1)),o=this.chooseVersion(i,t),s=this.calculateBitsNeeded(e,r,n,o);return this.chooseVersion(s,t)}static calculateBitsNeeded(t,e,r,n){return e.getSize()+t.getCharacterCountBits(n)+r.getSize()}static getAlphanumericCode(t){return t159)&&(r<224||r>235))return!1}return!0}static chooseMaskPattern(t,e,r,n){let i=Number.MAX_SAFE_INTEGER,o=-1;for(let s=0;s=(t+7)/8}static terminateBits(t,e){const r=8*t;if(e.getSize()>r)throw new mr("data bits cannot fit in the QR Code"+e.getSize()+" > "+r);for(let t=0;t<4&&e.getSize()0)for(let t=n;t<8;t++)e.appendBit(!1);const i=t-e.getSizeInBytes();for(let t=0;t=r)throw new mr("Block ID too large");const s=t%r,a=r-s,c=Math.floor(t/r),l=c+1,h=Math.floor(e/r),u=h+1,d=c-h,f=l-u;if(d!==f)throw new mr("EC bytes mismatch");if(r!==a+s)throw new mr("RS blocks mismatch");if(t!==(h+d)*a+(u+f)*s)throw new mr("Total bytes mismatch");n=1<=0&&e<=9}static appendNumericBytes(t,e){const r=t.length;let n=0;for(;n=33088&&n<=40956?i=n-33088:n>=57408&&n<=60351&&(i=n-49472),-1===i)throw new mr("Invalid byte sequence");const o=192*(i>>8)+(255&i);e.appendBits(o,13)}}static appendECI(t,e){e.appendBits(_e.ECI.getBits(),4),e.appendBits(t.getValue(),8)}}Cr.ALPHANUMERIC_TABLE=Int32Array.from([-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,36,-1,-1,-1,37,38,-1,-1,-1,-1,39,40,-1,41,42,43,0,1,2,3,4,5,6,7,8,9,44,-1,-1,-1,-1,-1,-1,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,-1,-1,-1,-1,-1]),Cr.DEFAULT_BYTE_MODE_ENCODING=I.UTF8.getName();class Er{write(t,e,r,n=null){if(0===t.length)throw new c("Found empty contents");if(e<0||r<0)throw new c("Requested dimensions are too small: "+e+"x"+r);let i=we.L,o=Er.QUIET_ZONE_SIZE;null!==n&&(void 0!==n.get(ur.ERROR_CORRECTION)&&(i=we.fromString(n.get(ur.ERROR_CORRECTION).toString())),void 0!==n.get(ur.MARGIN)&&(o=Number.parseInt(n.get(ur.MARGIN).toString(),10)));const s=Cr.encode(t,i,n);return this.renderResult(s,e,r,o)}writeToDom(t,e,r,n,i=null){"string"==typeof t&&(t=document.querySelector(t));const o=this.write(e,r,n,i);t&&t.appendChild(o)}renderResult(t,e,r,n){const i=t.getMatrix();if(null===i)throw new $;const o=i.getWidth(),s=i.getHeight(),a=o+2*n,c=s+2*n,l=Math.max(e,a),h=Math.max(r,c),u=Math.min(Math.floor(l/a),Math.floor(h/c)),d=Math.floor((l-o*u)/2),f=Math.floor((h-s*u)/2),g=this.createSVGElement(l,h);for(let t=0,e=f;te||i+s>r)throw new c("Crop rectangle does not fit within image data.");a&&this.reverseHorizontal(o,s)}getRow(t,e){if(t<0||t>=this.getHeight())throw new c("Requested row is outside the image: "+t);const r=this.getWidth();(null==e||e.length>16&255,o=r>>7&510,s=255&r;i[e]=(n+o+s)/4&255}this.luminances=i}else this.luminances=t;if(void 0===n&&(this.dataWidth=e),void 0===i&&(this.dataHeight=r),void 0===o&&(this.left=0),void 0===s&&(this.top=0),this.left+e>this.dataWidth||this.top+r>this.dataHeight)throw new c("Crop rectangle does not fit within image data.")}getRow(t,e){if(t<0||t>=this.getHeight())throw new c("Requested row is outside the image: "+t);const r=this.getWidth();(null==e||e.length"}}class Or extends Rr{constructor(t,e,r){super(t,0,0),this.binaryShiftStart=e,this.binaryShiftByteCount=r}appendTo(t,e){for(let r=0;r62?t.appendBits(this.binaryShiftByteCount-31,16):0===r?t.appendBits(Math.min(this.binaryShiftByteCount,31),5):t.appendBits(this.binaryShiftByteCount-31,5)),t.appendBits(e[this.binaryShiftStart+r],8)}addBinaryShift(t,e){return new Or(this,t,e)}toString(){return"<"+this.binaryShiftStart+"::"+(this.binaryShiftStart+this.binaryShiftByteCount-1)+">"}}function br(t,e,r){return new Rr(t,e,r)}const Br=["UPPER","LOWER","DIGIT","MIXED","PUNCT"],Lr=0,Pr=1,vr=2,Fr=3,xr=4,kr=new Rr(null,0,0),Ur=[Int32Array.from([0,327708,327710,327709,656318]),Int32Array.from([590318,0,327710,327709,656318]),Int32Array.from([262158,590300,0,590301,932798]),Int32Array.from([327709,327708,656318,0,327710]),Int32Array.from([327711,656380,656382,656381,0])];const Hr=function(t){for(let e of t)w.fill(e,-1);return t[Lr][xr]=0,t[Pr][xr]=0,t[Pr][Lr]=28,t[Fr][xr]=0,t[vr][xr]=0,t[vr][Lr]=15,t}(w.createInt32Array(6,6));class Vr{constructor(t,e,r,n){this.token=t,this.mode=e,this.binaryShiftByteCount=r,this.bitCount=n}getMode(){return this.mode}getToken(){return this.token}getBinaryShiftByteCount(){return this.binaryShiftByteCount}getBitCount(){return this.bitCount}latchAndAppend(t,e){let r=this.bitCount,n=this.token;if(t!==this.mode){let e=Ur[this.mode][t];n=br(n,65535&e,e>>16),r+=e>>16}let i=t===vr?4:5;return n=br(n,e,i),new Vr(n,t,0,r+i)}shiftAndAppend(t,e){let r=this.token,n=this.mode===vr?4:5;return r=br(r,Hr[this.mode][t],n),r=br(r,e,5),new Vr(r,this.mode,0,this.bitCount+n+5)}addBinaryShiftChar(t){let e=this.token,r=this.mode,n=this.bitCount;if(this.mode===xr||this.mode===vr){let t=Ur[r][Lr];e=br(e,65535&t,t>>16),n+=t>>16,r=Lr}let i=0===this.binaryShiftByteCount||31===this.binaryShiftByteCount?18:62===this.binaryShiftByteCount?9:8,o=new Vr(e,r,this.binaryShiftByteCount+1,n+i);return 2078===o.binaryShiftByteCount&&(o=o.endBinaryShift(t+1)),o}endBinaryShift(t){if(0===this.binaryShiftByteCount)return this;let e=this.token;return e=function(t,e,r){return new Or(t,e,r)}(e,t-this.binaryShiftByteCount,this.binaryShiftByteCount),new Vr(e,this.mode,0,this.bitCount)}isBetterThanOrEqualTo(t){let e=this.bitCount+(Ur[this.mode][t.mode]>>16);return this.binaryShiftByteCountt.binaryShiftByteCount&&t.binaryShiftByteCount>0&&(e+=10),e<=t.bitCount}toBitArray(t){let e=[];for(let r=this.endBinaryShift(t.length).token;null!==r;r=r.getPrevious())e.unshift(r);let r=new p;for(const n of e)n.appendTo(r,t);return r}toString(){return T.format("%s bits=%d bytes=%d",Br[this.mode],this.bitCount,this.binaryShiftByteCount)}static calculateBinaryShiftCost(t){return t.binaryShiftByteCount>62?21:t.binaryShiftByteCount>31?20:t.binaryShiftByteCount>0?10:0}}Vr.INITIAL_STATE=new Vr(kr,Lr,0,0);const zr=function(t){const e=T.getCharCode(" "),r=T.getCharCode("."),n=T.getCharCode(",");t[Lr][e]=1;const i=T.getCharCode("Z"),o=T.getCharCode("A");for(let e=o;e<=i;e++)t[Lr][e]=e-o+2;t[Pr][e]=1;const s=T.getCharCode("z"),a=T.getCharCode("a");for(let e=a;e<=s;e++)t[Pr][e]=e-a+2;t[vr][e]=1;const c=T.getCharCode("9"),l=T.getCharCode("0");for(let e=l;e<=c;e++)t[vr][e]=e-l+2;t[vr][n]=12,t[vr][r]=13;const h=["\0"," ","","","","","","","","\b","\t","\n","\v","\f","\r","","","","","","@","\\","^","_","`","|","~",""];for(let e=0;e","?","[","]","{","}"];for(let e=0;e0&&(t[xr][T.getCharCode(u[e])]=e);return t}(w.createInt32Array(5,256));class Gr{constructor(t){this.text=t}encode(){const t=T.getCharCode(" "),e=T.getCharCode("\n");let r=Dr.singletonList(Vr.INITIAL_STATE);for(let n=0;n0?(r=Gr.updateStateListForPair(r,n,i),n++):r=this.updateStateListForChar(r,n)}return Dr.min(r,((t,e)=>t.getBitCount()-e.getBitCount())).toBitArray(this.text)}updateStateListForChar(t,e){const r=[];for(let n of t)this.updateStateForChar(n,e,r);return Gr.simplifyStates(r)}updateStateForChar(t,e,r){let n=255&this.text[e],i=zr[t.getMode()][n]>0,o=null;for(let s=0;s<=xr;s++){let a=zr[s][n];if(a>0){if(null==o&&(o=t.endBinaryShift(e)),!i||s===t.getMode()||s===vr){const t=o.latchAndAppend(s,a);r.push(t)}if(!i&&Hr[t.getMode()][s]>=0){const t=o.shiftAndAppend(s,a);r.push(t)}}}if(t.getBinaryShiftByteCount()>0||0===zr[t.getMode()][n]){let n=t.addBinaryShiftChar(e);r.push(n)}}static updateStateListForPair(t,e,r){const n=[];for(let i of t)this.updateStateForPair(i,e,r,n);return this.simplifyStates(n)}static updateStateForPair(t,e,r,n){let i=t.endBinaryShift(e);if(n.push(i.latchAndAppend(xr,r)),t.getMode()!==xr&&n.push(i.shiftAndAppend(xr,r)),3===r||4===r){let t=i.latchAndAppend(vr,16-r).latchAndAppend(vr,1);n.push(t)}if(t.getBinaryShiftByteCount()>0){let r=t.addBinaryShiftChar(e).addBinaryShiftChar(e+1);n.push(r)}}static simplifyStates(t){let e=[];for(const r of t){let t=!0;for(const n of e){if(n.isBetterThanOrEqualTo(r)){t=!1;break}r.isBetterThanOrEqualTo(n)&&(e=e.filter((t=>t!==n)))}t&&e.push(r)}return e}}class Yr{constructor(){}static encodeBytes(t){return Yr.encode(t,Yr.DEFAULT_EC_PERCENT,Yr.DEFAULT_AZTEC_LAYERS)}static encode(t,e,r){let n,i,o,s,a,l=new Gr(t).encode(),h=m.truncDivision(l.getSize()*e,100)+11,u=l.getSize()+h;if(r!==Yr.DEFAULT_AZTEC_LAYERS){if(n=r<0,i=Math.abs(r),i>(n?Yr.MAX_NB_BITS_COMPACT:Yr.MAX_NB_BITS))throw new c(T.format("Illegal value %s for layers",r));o=Yr.totalBitsInLayer(i,n),s=Yr.WORD_SIZE[i];let t=o-o%s;if(a=Yr.stuffBits(l,s),a.getSize()+h>t)throw new c("Data to large for user specified layer");if(n&&a.getSize()>64*s)throw new c("Data to large for user specified layer")}else{s=0,a=null;for(let t=0;;t++){if(t>Yr.MAX_NB_BITS)throw new c("Data too large for an Aztec code");if(n=t<=3,i=n?t+1:t,o=Yr.totalBitsInLayer(i,n),u>o)continue;null!=a&&s===Yr.WORD_SIZE[i]||(s=Yr.WORD_SIZE[i],a=Yr.stuffBits(l,s));let e=o-o%s;if(!(n&&a.getSize()>64*s)&&a.getSize()+h<=e)break}}let d,f=Yr.generateCheckWords(a,o,s),g=a.getSize()/s,w=Yr.generateModeMessage(n,i,g),p=(n?11:14)+4*i,A=new Int32Array(p);if(n){d=p;for(let t=0;t=n||t.get(o+r))&&(s|=1<{for(var n in e)r.o(e,n)&&!r.o(t,n)&&Object.defineProperty(t,n,{enumerable:!0,get:e[n]})},r.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(t){if("object"==typeof window)return window}}(),r.o=(t,e)=>Object.prototype.hasOwnProperty.call(t,e),r.r=t=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})};var n={};(()=>{"use strict";var t;r.r(n),r.d(n,{Html5Qrcode:()=>W,Html5QrcodeScanType:()=>i,Html5QrcodeScanner:()=>ft,Html5QrcodeScannerState:()=>w,Html5QrcodeSupportedFormats:()=>t}),function(t){t[t.QR_CODE=0]="QR_CODE",t[t.AZTEC=1]="AZTEC",t[t.CODABAR=2]="CODABAR",t[t.CODE_39=3]="CODE_39",t[t.CODE_93=4]="CODE_93",t[t.CODE_128=5]="CODE_128",t[t.DATA_MATRIX=6]="DATA_MATRIX",t[t.MAXICODE=7]="MAXICODE",t[t.ITF=8]="ITF",t[t.EAN_13=9]="EAN_13",t[t.EAN_8=10]="EAN_8",t[t.PDF_417=11]="PDF_417",t[t.RSS_14=12]="RSS_14",t[t.RSS_EXPANDED=13]="RSS_EXPANDED",t[t.UPC_A=14]="UPC_A",t[t.UPC_E=15]="UPC_E",t[t.UPC_EAN_EXTENSION=16]="UPC_EAN_EXTENSION"}(t||(t={}));var e,i,o=new Map([[t.QR_CODE,"QR_CODE"],[t.AZTEC,"AZTEC"],[t.CODABAR,"CODABAR"],[t.CODE_39,"CODE_39"],[t.CODE_93,"CODE_93"],[t.CODE_128,"CODE_128"],[t.DATA_MATRIX,"DATA_MATRIX"],[t.MAXICODE,"MAXICODE"],[t.ITF,"ITF"],[t.EAN_13,"EAN_13"],[t.EAN_8,"EAN_8"],[t.PDF_417,"PDF_417"],[t.RSS_14,"RSS_14"],[t.RSS_EXPANDED,"RSS_EXPANDED"],[t.UPC_A,"UPC_A"],[t.UPC_E,"UPC_E"],[t.UPC_EAN_EXTENSION,"UPC_EAN_EXTENSION"]]);function s(e){return Object.values(t).includes(e)}!function(t){t[t.UNKNOWN=0]="UNKNOWN",t[t.URL=1]="URL"}(e||(e={})),function(t){t[t.SCAN_TYPE_CAMERA=0]="SCAN_TYPE_CAMERA",t[t.SCAN_TYPE_FILE=1]="SCAN_TYPE_FILE"}(i||(i={}));var a,c=function(){function t(){}return t.GITHUB_PROJECT_URL="https://github.com/mebjas/html5-qrcode",t.SCAN_DEFAULT_FPS=2,t.DEFAULT_DISABLE_FLIP=!1,t.DEFAULT_REMEMBER_LAST_CAMERA_USED=!0,t.DEFAULT_SUPPORTED_SCAN_TYPE=[i.SCAN_TYPE_CAMERA,i.SCAN_TYPE_FILE],t}(),l=function(){function t(t,e){this.format=t,this.formatName=e}return t.prototype.toString=function(){return this.formatName},t.create=function(e){if(!o.has(e))throw"".concat(e," not in html5QrcodeSupportedFormatsTextMap");return new t(e,o.get(e))},t}(),h=function(){function t(){}return t.createFromText=function(t){return{decodedText:t,result:{text:t}}},t.createFromQrcodeResult=function(t){return{decodedText:t.text,result:t}},t}();!function(t){t[t.UNKWOWN_ERROR=0]="UNKWOWN_ERROR",t[t.IMPLEMENTATION_ERROR=1]="IMPLEMENTATION_ERROR",t[t.NO_CODE_FOUND_ERROR=2]="NO_CODE_FOUND_ERROR"}(a||(a={}));var u=function(){function t(){}return t.createFrom=function(t){return{errorMessage:t,type:a.UNKWOWN_ERROR}},t}(),d=function(){function t(t){this.verbose=t}return t.prototype.log=function(t){this.verbose&&console.log(t)},t.prototype.warn=function(t){this.verbose&&console.warn(t)},t.prototype.logError=function(t,e){(this.verbose||!0===e)&&console.error(t)},t.prototype.logErrors=function(t){if(0===t.length)throw"Logger#logError called without arguments";this.verbose&&console.error(t)},t}();function f(t){return null==t}var g,w,m=function(){function t(){}return t.codeParseError=function(t){return"QR code parse error, error = ".concat(t)},t.errorGettingUserMedia=function(t){return"Error getting userMedia, error = ".concat(t)},t.onlyDeviceSupportedError=function(){return"The device doesn't support navigator.mediaDevices , only supported cameraIdOrConfig in this case is deviceId parameter (string)."},t.cameraStreamingNotSupported=function(){return"Camera streaming not supported by the browser."},t.unableToQuerySupportedDevices=function(){return"Unable to query supported devices, unknown error."},t.insecureContextCameraQueryError=function(){return"Camera access is only supported in secure context like https or localhost."},t.scannerPaused=function(){return"Scanner paused"},t}(),p=function(){function t(){}return t.scanningStatus=function(){return"Scanning"},t.idleStatus=function(){return"Idle"},t.errorStatus=function(){return"Error"},t.permissionStatus=function(){return"Permission"},t.noCameraFoundErrorStatus=function(){return"No Cameras"},t.lastMatch=function(t){return"Last Match: ".concat(t)},t.codeScannerTitle=function(){return"Code Scanner"},t.cameraPermissionTitle=function(){return"Request Camera Permissions"},t.cameraPermissionRequesting=function(){return"Requesting camera permissions..."},t.noCameraFound=function(){return"No camera found"},t.scanButtonStopScanningText=function(){return"Stop Scanning"},t.scanButtonStartScanningText=function(){return"Start Scanning"},t.torchOnButton=function(){return"Switch On Torch"},t.torchOffButton=function(){return"Switch Off Torch"},t.torchOnFailedMessage=function(){return"Failed to turn on torch"},t.torchOffFailedMessage=function(){return"Failed to turn off torch"},t.scanButtonScanningStarting=function(){return"Launching Camera..."},t.textIfCameraScanSelected=function(){return"Scan an Image File"},t.textIfFileScanSelected=function(){return"Scan using camera directly"},t.selectCamera=function(){return"Select Camera"},t.fileSelectionChooseImage=function(){return"Choose Image"},t.fileSelectionChooseAnother=function(){return"Choose Another"},t.fileSelectionNoImageSelected=function(){return"No image choosen"},t.anonymousCameraPrefix=function(){return"Anonymous Camera"},t.dragAndDropMessage=function(){return"Or drop an image to scan"},t.dragAndDropMessageOnlyImages=function(){return"Or drop an image to scan (other files not supported)"},t.zoom=function(){return"zoom"},t.loadingImage=function(){return"Loading image..."},t.cameraScanAltText=function(){return"Camera based scan"},t.fileScanAltText=function(){return"Fule based scan"},t}(),A=function(){function t(){}return t.poweredBy=function(){return"Powered by "},t.reportIssues=function(){return"Report issues"},t}(),C=function(){function t(){}return t.isMediaStreamConstraintsValid=function(t,e){if("object"!=typeof t){var r=typeof t;return e.logError("videoConstraints should be of type object, the "+"object passed is of type ".concat(r,"."),!0),!1}for(var n=new Set(["autoGainControl","channelCount","echoCancellation","latency","noiseSuppression","sampleRate","sampleSize","volume"]),i=0,o=Object.keys(t);i0&&i[i.length-1])||6!==a[0]&&2!==a[0])){s=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]r&&(r=s,e=o)}if(!e)throw"No largest barcode found";return e},e.prototype.createBarcodeDetectorFormats=function(t){for(var e=[],r=0,n=t;r0&&i[i.length-1])||6!==a[0]&&2!==a[0])){s=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]0&&i[i.length-1])||6!==a[0]&&2!==a[0])){s=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]=n&&(t.isClosed=!0,t.parentElement.removeChild(t.surface),e())}))}))},t.prototype.getCapabilities=function(){return new B(this.getFirstTrackOrFail())},t}(),P=function(){function t(t){this.mediaStream=t}return t.prototype.render=function(t,e,r){return D(this,void 0,void 0,(function(){return M(this,(function(n){return[2,L.create(t,this.mediaStream,e,r)]}))}))},t.create=function(e){return D(this,void 0,void 0,(function(){var r;return M(this,(function(n){switch(n.label){case 0:if(!navigator.mediaDevices)throw"navigator.mediaDevices not supported";return r={audio:!1,video:e},[4,navigator.mediaDevices.getUserMedia(r)];case 1:return[2,new t(n.sent())]}}))}))},t}(),v=function(t,e,r,n){return new(r||(r=Promise))((function(i,o){function s(t){try{c(n.next(t))}catch(t){o(t)}}function a(t){try{c(n.throw(t))}catch(t){o(t)}}function c(t){var e;t.done?i(t.value):(e=t.value,e instanceof r?e:new r((function(t){t(e)}))).then(s,a)}c((n=n.apply(t,e||[])).next())}))},F=function(t,e){var r,n,i,o,s={label:0,sent:function(){if(1&i[0])throw i[1];return i[1]},trys:[],ops:[]};return o={next:a(0),throw:a(1),return:a(2)},"function"==typeof Symbol&&(o[Symbol.iterator]=function(){return this}),o;function a(a){return function(c){return function(a){if(r)throw new TypeError("Generator is already executing.");for(;o&&(o=0,a[0]&&(s=0)),s;)try{if(r=1,n&&(i=2&a[0]?n.return:a[0]?n.throw||((i=n.return)&&i.call(n),0):n.next)&&!(i=i.call(n,a[1])).done)return i;switch(n=0,i&&(a=[2&a[0],i.value]),a[0]){case 0:case 1:i=a;break;case 4:return s.label++,{value:a[1],done:!1};case 5:s.label++,n=a[1],a=[0];continue;case 7:a=s.ops.pop(),s.trys.pop();continue;default:if(!((i=(i=s.trys).length>0&&i[i.length-1])||6!==a[0]&&2!==a[0])){s=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]0&&i[i.length-1])||6!==a[0]&&2!==a[0])){s=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]t&&(this.logger.warn("`qrbox.width` or `qrbox` is larger than the width of the root element. The width will be truncated to the width of root element."),i=t),i)},e.prototype.validateQrboxConfig=function(t){if("number"!=typeof t&&"function"!=typeof t&&(void 0===t.width||void 0===t.height))throw"Invalid instance of QrDimensions passed for 'config.qrbox'. Both 'width' and 'height' should be set."},e.prototype.toQrdimensions=function(t,e,r){if("number"==typeof r)return{width:r,height:r};if("function"==typeof r)try{return r(t,e)}catch(t){throw new Error("qrbox config was passed as a function but it failed with unknown error"+t)}return r},e.prototype.setupUi=function(t,e,r){r.isShadedBoxEnabled()&&this.validateQrboxSize(t,e,r);var n=f(r.qrbox)?{width:t,height:e}:r.qrbox;this.validateQrboxConfig(n);var i=this.toQrdimensions(t,e,n);i.height>e&&this.logger.warn("[Html5Qrcode] config.qrbox has height that isgreater than the height of the video stream. Shading will be ignored");var o=r.isShadedBoxEnabled()&&i.height<=e,s={x:0,y:0,width:t,height:e},a=o?this.getShadedRegionBounds(t,e,i):s,c=this.createCanvasElement(a.width,a.height),l=c.getContext("2d",{willReadFrequently:!0});l.canvas.width=a.width,l.canvas.height=a.height,this.element.append(c),o&&this.possiblyInsertShadingElement(this.element,t,e,i),this.createScannerPausedUiElement(this.element),this.qrRegion=a,this.context=l,this.canvasElement=c},e.prototype.createScannerPausedUiElement=function(t){var e=document.createElement("div");e.innerText=m.scannerPaused(),e.style.display="none",e.style.position="absolute",e.style.top="0px",e.style.zIndex="1",e.style.background="rgba(9, 9, 9, 0.46)",e.style.color="#FFECEC",e.style.textAlign="center",e.style.width="100%",t.appendChild(e),this.scannerPausedUiElement=e},e.prototype.scanContext=function(t,e){var r=this;return this.stateManagerProxy.isPaused()?Promise.resolve(!1):this.qrcode.decodeAsync(this.canvasElement).then((function(e){return t(e.text,h.createFromQrcodeResult(e)),r.possiblyUpdateShaders(!0),!0})).catch((function(t){r.possiblyUpdateShaders(!1);var n=m.codeParseError(t);return e(n,u.createFrom(n)),!1}))},e.prototype.foreverScan=function(t,e,r){var n=this;if(this.shouldScan&&this.renderedCamera){var i=this.renderedCamera.getSurface(),o=i.videoWidth/i.clientWidth,s=i.videoHeight/i.clientHeight;if(!this.qrRegion)throw"qrRegion undefined when localMediaStream is ready.";var a=this.qrRegion.width*o,c=this.qrRegion.height*s,l=this.qrRegion.x*o,h=this.qrRegion.y*s;this.context.drawImage(i,l,h,a,c,0,0,this.qrRegion.width,this.qrRegion.height);var u=function(){n.foreverScanTimeout=setTimeout((function(){n.foreverScan(t,e,r)}),n.getTimeoutFps(t.fps))};this.scanContext(e,r).then((function(i){i||!0===t.disableFlip?u():(n.context.translate(n.context.canvas.width,0),n.context.scale(-1,1),n.scanContext(e,r).finally((function(){u()})))})).catch((function(t){n.logger.logError("Error happend while scanning context",t),u()}))}},e.prototype.createVideoConstraints=function(t){if("string"==typeof t)return{deviceId:{exact:t}};if("object"==typeof t){var e="facingMode",r="deviceId",n={user:!0,environment:!0},i="exact",o=function(t){if(t in n)return!0;throw"config has invalid 'facingMode' value = "+"'".concat(t,"'")},s=Object.keys(t);if(1!==s.length)throw"'cameraIdOrConfig' object should have exactly 1 key,"+" if passed as an object, found ".concat(s.length," keys");var a=Object.keys(t)[0];if(a!==e&&a!==r)throw"Only '".concat(e,"' and '").concat(r,"' ")+" are supported for 'cameraIdOrConfig'";if(a!==e){var c=t.deviceId;if("string"==typeof c)return{deviceId:c};if("object"==typeof c){if(i in c)return{deviceId:{exact:c["".concat(i)]}};throw"'deviceId' should be string or object with"+" ".concat(i," as key.")}throw"Invalid type of 'deviceId' = ".concat(typeof c)}var l=t.facingMode;if("string"==typeof l){if(o(l))return{facingMode:l}}else{if("object"!=typeof l)throw"Invalid type of 'facingMode' = ".concat(typeof l);if(!(i in l))throw"'facingMode' should be string or object with"+" ".concat(i," as key.");if(o(l["".concat(i)]))return{facingMode:{exact:l["".concat(i)]}}}}throw"Invalid type of 'cameraIdOrConfig' = ".concat(typeof t)},e.prototype.computeCanvasDrawConfig=function(t,e,r,n){if(t<=r&&e<=n)return{x:(r-t)/2,y:(n-e)/2,width:t,height:e};var i=t,o=e;return t>r&&(e*=r/t,t=r),e>n&&(t*=n/e,e=n),this.logger.log("Image downsampled from "+"".concat(i,"X").concat(o)+" to ".concat(t,"X").concat(e,".")),this.computeCanvasDrawConfig(t,e,r,n)},e.prototype.clearElement=function(){if(this.stateManagerProxy.isScanning())throw"Cannot clear while scan is ongoing, close it first.";var t=document.getElementById(this.elementId);t&&(t.innerHTML="")},e.prototype.possiblyUpdateShaders=function(t){this.qrMatch!==t&&(this.hasBorderShaders&&this.borderShaders&&this.borderShaders.length&&this.borderShaders.forEach((function(e){e.style.backgroundColor=t?Y.BORDER_SHADER_MATCH_COLOR:Y.BORDER_SHADER_DEFAULT_COLOR})),this.qrMatch=t)},e.prototype.possiblyCloseLastScanImageFile=function(){this.lastScanImageFile&&(URL.revokeObjectURL(this.lastScanImageFile),this.lastScanImageFile=null)},e.prototype.createCanvasElement=function(t,e,r){var n=t,i=e,o=document.createElement("canvas");return o.style.width="".concat(n,"px"),o.style.height="".concat(i,"px"),o.style.display="none",o.id=f(r)?"qr-canvas":r,o},e.prototype.getShadedRegionBounds=function(t,e,r){if(r.width>t||r.height>e)throw"'config.qrbox' dimensions should not be greater than the dimensions of the root HTML element.";return{x:(t-r.width)/2,y:(e-r.height)/2,width:r.width,height:r.height}},e.prototype.possiblyInsertShadingElement=function(t,e,r,n){if(!(e-n.width<1||r-n.height<1)){var i=document.createElement("div");i.style.position="absolute";var o=(e-n.width)/2,s=(r-n.height)/2;if(i.style.borderLeft="".concat(o,"px solid rgba(0, 0, 0, 0.48)"),i.style.borderRight="".concat(o,"px solid rgba(0, 0, 0, 0.48)"),i.style.borderTop="".concat(s,"px solid rgba(0, 0, 0, 0.48)"),i.style.borderBottom="".concat(s,"px solid rgba(0, 0, 0, 0.48)"),i.style.boxSizing="border-box",i.style.top="0px",i.style.bottom="0px",i.style.left="0px",i.style.right="0px",i.id="".concat(Y.SHADED_REGION_ELEMENT_ID),e-n.width<11||r-n.height<11)this.hasBorderShaders=!1;else{this.insertShaderBorders(i,40,5,-5,null,0,!0),this.insertShaderBorders(i,40,5,-5,null,0,!1),this.insertShaderBorders(i,40,5,null,-5,0,!0),this.insertShaderBorders(i,40,5,null,-5,0,!1),this.insertShaderBorders(i,5,45,-5,null,-5,!0),this.insertShaderBorders(i,5,45,null,-5,-5,!0),this.insertShaderBorders(i,5,45,-5,null,-5,!1),this.insertShaderBorders(i,5,45,null,-5,-5,!1),this.hasBorderShaders=!0}t.append(i)}},e.prototype.insertShaderBorders=function(t,e,r,n,i,o,s){var a=document.createElement("div");a.style.position="absolute",a.style.backgroundColor=Y.BORDER_SHADER_DEFAULT_COLOR,a.style.width="".concat(e,"px"),a.style.height="".concat(r,"px"),null!==n&&(a.style.top="".concat(n,"px")),null!==i&&(a.style.bottom="".concat(i,"px")),s?a.style.left="".concat(o,"px"):a.style.right="".concat(o,"px"),this.borderShaders||(this.borderShaders=[]),this.borderShaders.push(a),t.appendChild(a)},e.prototype.showPausedState=function(){if(!this.scannerPausedUiElement)throw"[internal error] scanner paused UI element not found";this.scannerPausedUiElement.style.display="block"},e.prototype.hidePausedState=function(){if(!this.scannerPausedUiElement)throw"[internal error] scanner paused UI element not found";this.scannerPausedUiElement.style.display="none"},e.prototype.getTimeoutFps=function(t){return 1e3/t},e}(),j="data:image/svg+xml;base64,",Z=j+"PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAzNzEuNjQzIDM3MS42NDMiIHN0eWxlPSJlbmFibGUtYmFja2dyb3VuZDpuZXcgMCAwIDM3MS42NDMgMzcxLjY0MyIgeG1sOnNwYWNlPSJwcmVzZXJ2ZSI+PHBhdGggZD0iTTEwNS4wODQgMzguMjcxaDE2My43Njh2MjBIMTA1LjA4NHoiLz48cGF0aCBkPSJNMzExLjU5NiAxOTAuMTg5Yy03LjQ0MS05LjM0Ny0xOC40MDMtMTYuMjA2LTMyLjc0My0yMC41MjJWMzBjMC0xNi41NDItMTMuNDU4LTMwLTMwLTMwSDEyNS4wODRjLTE2LjU0MiAwLTMwIDEzLjQ1OC0zMCAzMHYxMjAuMTQzaC04LjI5NmMtMTYuNTQyIDAtMzAgMTMuNDU4LTMwIDMwdjEuMzMzYTI5LjgwNCAyOS44MDQgMCAwIDAgNC42MDMgMTUuOTM5Yy03LjM0IDUuNDc0LTEyLjEwMyAxNC4yMjEtMTIuMTAzIDI0LjA2MXYxLjMzM2MwIDkuODQgNC43NjMgMTguNTg3IDEyLjEwMyAyNC4wNjJhMjkuODEgMjkuODEgMCAwIDAtNC42MDMgMTUuOTM4djEuMzMzYzAgMTYuNTQyIDEzLjQ1OCAzMCAzMCAzMGg4LjMyNGMuNDI3IDExLjYzMSA3LjUwMyAyMS41ODcgMTcuNTM0IDI2LjE3Ny45MzEgMTAuNTAzIDQuMDg0IDMwLjE4NyAxNC43NjggNDUuNTM3YTkuOTg4IDkuOTg4IDAgMCAwIDguMjE2IDQuMjg4IDkuOTU4IDkuOTU4IDAgMCAwIDUuNzA0LTEuNzkzYzQuNTMzLTMuMTU1IDUuNjUtOS4zODggMi40OTUtMTMuOTIxLTYuNzk4LTkuNzY3LTkuNjAyLTIyLjYwOC0xMC43Ni0zMS40aDgyLjY4NWMuMjcyLjQxNC41NDUuODE4LjgxNSAxLjIxIDMuMTQyIDQuNTQxIDkuMzcyIDUuNjc5IDEzLjkxMyAyLjUzNCA0LjU0Mi0zLjE0MiA1LjY3Ny05LjM3MSAyLjUzNS0xMy45MTMtMTEuOTE5LTE3LjIyOS04Ljc4Ny0zNS44ODQgOS41ODEtNTcuMDEyIDMuMDY3LTIuNjUyIDEyLjMwNy0xMS43MzIgMTEuMjE3LTI0LjAzMy0uODI4LTkuMzQzLTcuMTA5LTE3LjE5NC0xOC42NjktMjMuMzM3YTkuODU3IDkuODU3IDAgMCAwLTEuMDYxLS40ODZjLS40NjYtLjE4Mi0xMS40MDMtNC41NzktOS43NDEtMTUuNzA2IDEuMDA3LTYuNzM3IDE0Ljc2OC04LjI3MyAyMy43NjYtNy42NjYgMjMuMTU2IDEuNTY5IDM5LjY5OCA3LjgwMyA0Ny44MzYgMTguMDI2IDUuNzUyIDcuMjI1IDcuNjA3IDE2LjYyMyA1LjY3MyAyOC43MzMtLjQxMyAyLjU4NS0uODI0IDUuMjQxLTEuMjQ1IDcuOTU5LTUuNzU2IDM3LjE5NC0xMi45MTkgODMuNDgzLTQ5Ljg3IDExNC42NjEtNC4yMjEgMy41NjEtNC43NTYgOS44Ny0xLjE5NCAxNC4wOTJhOS45OCA5Ljk4IDAgMCAwIDcuNjQ4IDMuNTUxIDkuOTU1IDkuOTU1IDAgMCAwIDYuNDQ0LTIuMzU4YzQyLjY3Mi0zNi4wMDUgNTAuODAyLTg4LjUzMyA1Ni43MzctMTI2Ljg4OC40MTUtMi42ODQuODIxLTUuMzA5IDEuMjI5LTcuODYzIDIuODM0LTE3LjcyMS0uNDU1LTMyLjY0MS05Ljc3Mi00NC4zNDV6bS0yMzIuMzA4IDQyLjYyYy01LjUxNCAwLTEwLTQuNDg2LTEwLTEwdi0xLjMzM2MwLTUuNTE0IDQuNDg2LTEwIDEwLTEwaDE1djIxLjMzM2gtMTV6bS0yLjUtNTIuNjY2YzAtNS41MTQgNC40ODYtMTAgMTAtMTBoNy41djIxLjMzM2gtNy41Yy01LjUxNCAwLTEwLTQuNDg2LTEwLTEwdi0xLjMzM3ptMTcuNSA5My45OTloLTcuNWMtNS41MTQgMC0xMC00LjQ4Ni0xMC0xMHYtMS4zMzNjMC01LjUxNCA0LjQ4Ni0xMCAxMC0xMGg3LjV2MjEuMzMzem0zMC43OTYgMjguODg3Yy01LjUxNCAwLTEwLTQuNDg2LTEwLTEwdi04LjI3MWg5MS40NTdjLS44NTEgNi42NjgtLjQzNyAxMi43ODcuNzMxIDE4LjI3MWgtODIuMTg4em03OS40ODItMTEzLjY5OGMtMy4xMjQgMjAuOTA2IDEyLjQyNyAzMy4xODQgMjEuNjI1IDM3LjA0IDUuNDQxIDIuOTY4IDcuNTUxIDUuNjQ3IDcuNzAxIDcuMTg4LjIxIDIuMTUtMi41NTMgNS42ODQtNC40NzcgNy4yNTEtLjQ4Mi4zNzgtLjkyOS44LTEuMzM1IDEuMjYxLTYuOTg3IDcuOTM2LTExLjk4MiAxNS41Mi0xNS40MzIgMjIuNjg4aC05Ny41NjRWMzBjMC01LjUxNCA0LjQ4Ni0xMCAxMC0xMGgxMjMuNzY5YzUuNTE0IDAgMTAgNC40ODYgMTAgMTB2MTM1LjU3OWMtMy4wMzItLjM4MS02LjE1LS42OTQtOS4zODktLjkxNC0yNS4xNTktMS42OTQtNDIuMzcgNy43NDgtNDQuODk4IDI0LjY2NnoiLz48cGF0aCBkPSJNMTc5LjEyOSA4My4xNjdoLTI0LjA2YTUgNSAwIDAgMC01IDV2MjQuMDYxYTUgNSAwIDAgMCA1IDVoMjQuMDZhNSA1IDAgMCAwIDUtNVY4OC4xNjdhNSA1IDAgMCAwLTUtNXpNMTcyLjYyOSAxNDIuODZoLTEyLjU2VjEzMC44YTUgNSAwIDEgMC0xMCAwdjE3LjA2MWE1IDUgMCAwIDAgNSA1aDE3LjU2YTUgNSAwIDEgMCAwLTEwLjAwMXpNMjE2LjU2OCA4My4xNjdoLTI0LjA2YTUgNSAwIDAgMC01IDV2MjQuMDYxYTUgNSAwIDAgMCA1IDVoMjQuMDZhNSA1IDAgMCAwIDUtNVY4OC4xNjdhNSA1IDAgMCAwLTUtNXptLTUgMjQuMDYxaC0xNC4wNlY5My4xNjdoMTQuMDZ2MTQuMDYxek0yMTEuNjY5IDEyNS45MzZIMTk3LjQxYTUgNSAwIDAgMC01IDV2MTQuMjU3YTUgNSAwIDAgMCA1IDVoMTQuMjU5YTUgNSAwIDAgMCA1LTV2LTE0LjI1N2E1IDUgMCAwIDAtNS01eiIvPjwvc3ZnPg==",Q=j+"PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA1OS4wMTggNTkuMDE4IiBzdHlsZT0iZW5hYmxlLWJhY2tncm91bmQ6bmV3IDAgMCA1OS4wMTggNTkuMDE4IiB4bWw6c3BhY2U9InByZXNlcnZlIj48cGF0aCBkPSJtNTguNzQxIDU0LjgwOS01Ljk2OS02LjI0NGExMC43NCAxMC43NCAwIDAgMCAyLjgyLTcuMjVjMC01Ljk1My00Ljg0My0xMC43OTYtMTAuNzk2LTEwLjc5NlMzNCAzNS4zNjEgMzQgNDEuMzE0IDM4Ljg0MyA1Mi4xMSA0NC43OTYgNTIuMTFjMi40NDEgMCA0LjY4OC0uODI0IDYuNDk5LTIuMTk2bDYuMDAxIDYuMjc3YS45OTguOTk4IDAgMCAwIDEuNDE0LjAzMiAxIDEgMCAwIDAgLjAzMS0xLjQxNHpNMzYgNDEuMzE0YzAtNC44NSAzLjk0Ni04Ljc5NiA4Ljc5Ni04Ljc5NnM4Ljc5NiAzLjk0NiA4Ljc5NiA4Ljc5Ni0zLjk0NiA4Ljc5Ni04Ljc5NiA4Ljc5NlMzNiA0Ni4xNjQgMzYgNDEuMzE0ek0xMC40MzEgMTYuMDg4YzAgMy4wNyAyLjQ5OCA1LjU2OCA1LjU2OSA1LjU2OHM1LjU2OS0yLjQ5OCA1LjU2OS01LjU2OGMwLTMuMDcxLTIuNDk4LTUuNTY5LTUuNTY5LTUuNTY5cy01LjU2OSAyLjQ5OC01LjU2OSA1LjU2OXptOS4xMzggMGMwIDEuOTY4LTEuNjAyIDMuNTY4LTMuNTY5IDMuNTY4cy0zLjU2OS0xLjYwMS0zLjU2OS0zLjU2OCAxLjYwMi0zLjU2OSAzLjU2OS0zLjU2OSAzLjU2OSAxLjYwMSAzLjU2OSAzLjU2OXoiLz48cGF0aCBkPSJtMzAuODgyIDI4Ljk4NyA5LjE4LTEwLjA1NCAxMS4yNjIgMTAuMzIzYTEgMSAwIDAgMCAxLjM1MS0xLjQ3NWwtMTItMTFhMSAxIDAgMCAwLTEuNDE0LjA2M2wtOS43OTQgMTAuNzI3LTQuNzQzLTQuNzQzYTEuMDAzIDEuMDAzIDAgMCAwLTEuMzY4LS4wNDRMNi4zMzkgMzcuNzY4YTEgMSAwIDEgMCAxLjMyMiAxLjUwMWwxNi4zMTMtMTQuMzYyIDcuMzE5IDcuMzE4YS45OTkuOTk5IDAgMSAwIDEuNDE0LTEuNDE0bC0xLjgyNS0xLjgyNHoiLz48cGF0aCBkPSJNMzAgNDYuNTE4SDJ2LTQyaDU0djI4YTEgMSAwIDEgMCAyIDB2LTI5YTEgMSAwIDAgMC0xLTFIMWExIDEgMCAwIDAtMSAxdjQ0YTEgMSAwIDAgMCAxIDFoMjlhMSAxIDAgMSAwIDAtMnoiLz48L3N2Zz4=",K=j+"PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0NjAgNDYwIiBzdHlsZT0iZW5hYmxlLWJhY2tncm91bmQ6bmV3IDAgMCA0NjAgNDYwIiB4bWw6c3BhY2U9InByZXNlcnZlIj48cGF0aCBkPSJNMjMwIDBDMTAyLjk3NSAwIDAgMTAyLjk3NSAwIDIzMHMxMDIuOTc1IDIzMCAyMzAgMjMwIDIzMC0xMDIuOTc0IDIzMC0yMzBTMzU3LjAyNSAwIDIzMCAwem0zOC4zMzMgMzc3LjM2YzAgOC42NzYtNy4wMzQgMTUuNzEtMTUuNzEgMTUuNzFoLTQzLjEwMWMtOC42NzYgMC0xNS43MS03LjAzNC0xNS43MS0xNS43MVYyMDIuNDc3YzAtOC42NzYgNy4wMzMtMTUuNzEgMTUuNzEtMTUuNzFoNDMuMTAxYzguNjc2IDAgMTUuNzEgNy4wMzMgMTUuNzEgMTUuNzFWMzc3LjM2ek0yMzAgMTU3Yy0yMS41MzkgMC0zOS0xNy40NjEtMzktMzlzMTcuNDYxLTM5IDM5LTM5IDM5IDE3LjQ2MSAzOSAzOS0xNy40NjEgMzktMzkgMzl6Ii8+PC9zdmc+",q=function(){function t(){}return t.createDefault=function(){return{hasPermission:!1,lastUsedCameraId:null}},t}(),J=function(){function t(){this.data=q.createDefault();var e=localStorage.getItem(t.LOCAL_STORAGE_KEY);e?this.data=JSON.parse(e):this.reset()}return t.prototype.hasCameraPermissions=function(){return this.data.hasPermission},t.prototype.getLastUsedCameraId=function(){return this.data.lastUsedCameraId},t.prototype.setHasPermission=function(t){this.data.hasPermission=t,this.flush()},t.prototype.setLastUsedCameraId=function(t){this.data.lastUsedCameraId=t,this.flush()},t.prototype.resetLastUsedCameraId=function(){this.data.lastUsedCameraId=null,this.flush()},t.prototype.reset=function(){this.data=q.createDefault(),this.flush()},t.prototype.flush=function(){localStorage.setItem(t.LOCAL_STORAGE_KEY,JSON.stringify(this.data))},t.LOCAL_STORAGE_KEY="HTML5_QRCODE_DATA",t}(),$=function(){function t(){this.infoDiv=document.createElement("div")}return t.prototype.renderInto=function(t){this.infoDiv.style.position="absolute",this.infoDiv.style.top="10px",this.infoDiv.style.right="10px",this.infoDiv.style.zIndex="2",this.infoDiv.style.display="none",this.infoDiv.style.padding="5pt",this.infoDiv.style.border="1px solid #171717",this.infoDiv.style.fontSize="10pt",this.infoDiv.style.background="rgb(0 0 0 / 69%)",this.infoDiv.style.borderRadius="5px",this.infoDiv.style.textAlign="center",this.infoDiv.style.fontWeight="400",this.infoDiv.style.color="white",this.infoDiv.innerText=A.poweredBy();var e=document.createElement("a");e.innerText="ScanApp",e.href="https://scanapp.org",e.target="new",e.style.color="white",this.infoDiv.appendChild(e);var r=document.createElement("br"),n=document.createElement("br");this.infoDiv.appendChild(r),this.infoDiv.appendChild(n);var i=document.createElement("a");i.innerText=A.reportIssues(),i.href="https://github.com/mebjas/html5-qrcode/issues",i.target="new",i.style.color="white",this.infoDiv.appendChild(i),t.appendChild(this.infoDiv)},t.prototype.show=function(){this.infoDiv.style.display="block"},t.prototype.hide=function(){this.infoDiv.style.display="none"},t}(),tt=function(){function t(t,e){this.isShowingInfoIcon=!0,this.onTapIn=t,this.onTapOut=e,this.infoIcon=document.createElement("img")}return t.prototype.renderInto=function(t){var e=this;this.infoIcon.alt="Info icon",this.infoIcon.src=K,this.infoIcon.style.position="absolute",this.infoIcon.style.top="4px",this.infoIcon.style.right="4px",this.infoIcon.style.opacity="0.6",this.infoIcon.style.cursor="pointer",this.infoIcon.style.zIndex="2",this.infoIcon.style.width="16px",this.infoIcon.style.height="16px",this.infoIcon.onmouseover=function(t){return e.onHoverIn()},this.infoIcon.onmouseout=function(t){return e.onHoverOut()},this.infoIcon.onclick=function(t){return e.onClick()},t.appendChild(this.infoIcon)},t.prototype.onHoverIn=function(){this.isShowingInfoIcon&&(this.infoIcon.style.opacity="1")},t.prototype.onHoverOut=function(){this.isShowingInfoIcon&&(this.infoIcon.style.opacity="0.6")},t.prototype.onClick=function(){this.isShowingInfoIcon?(this.isShowingInfoIcon=!1,this.onTapIn(),this.infoIcon.src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAAQgAAAEIBarqQRAAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAAE1SURBVDiNfdI7S0NBEAXgLya1otFgpbYSbISAgpXYi6CmiH9KCAiChaVga6OiWPgfRDQ+0itaGVNosXtluWwcuMzePfM4M3sq8lbHBubwg1dc4m1E/J/N4ghDPOIsfk/4xiEao5KX0McFljN4C9d4QTPXuY99jP3DsIoDPGM6BY5i5yI5R7O4q+ImFkJY2DCh3cAH2klyB+9J1xUMMAG7eCh1a+Mr+k48b5diXrFVwwLuS+BJ9MfR7+G0FHOHhTHhnXNWS87VDF4pcnfQK4Ep7XScNLmPTZgURNKKYENYWDpzW1BhscS1WHS8CDgURFJQrWcoF3c13KKbgg1BYQfy8xZWEzTTw1QZbAoKu8FqJnktdu5hcVSHmchiILzzuaDQvjBzV2m8yohCE1jHfPx/xhU+y4G/D75ELlRJsSYAAAAASUVORK5CYII=",this.infoIcon.style.opacity="1"):(this.isShowingInfoIcon=!0,this.onTapOut(),this.infoIcon.src=K,this.infoIcon.style.opacity="0.6")},t}(),et=function(){function t(){var t=this;this.infoDiv=new $,this.infoIcon=new tt((function(){t.infoDiv.show()}),(function(){t.infoDiv.hide()}))}return t.prototype.renderInto=function(t){this.infoDiv.renderInto(t),this.infoIcon.renderInto(t)},t}(),rt=function(){function t(){}return t.hasPermissions=function(){return t=this,e=void 0,n=function(){var t,e,r,n;return function(t,e){var r,n,i,o,s={label:0,sent:function(){if(1&i[0])throw i[1];return i[1]},trys:[],ops:[]};return o={next:a(0),throw:a(1),return:a(2)},"function"==typeof Symbol&&(o[Symbol.iterator]=function(){return this}),o;function a(a){return function(c){return function(a){if(r)throw new TypeError("Generator is already executing.");for(;o&&(o=0,a[0]&&(s=0)),s;)try{if(r=1,n&&(i=2&a[0]?n.return:a[0]?n.throw||((i=n.return)&&i.call(n),0):n.next)&&!(i=i.call(n,a[1])).done)return i;switch(n=0,i&&(a=[2&a[0],i.value]),a[0]){case 0:case 1:i=a;break;case 4:return s.label++,{value:a[1],done:!1};case 5:s.label++,n=a[1],a=[0];continue;case 7:a=s.ops.pop(),s.trys.pop();continue;default:if(!((i=(i=s.trys).length>0&&i[i.length-1])||6!==a[0]&&2!==a[0])){s=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]1},t.prototype.isCameraScanRequired=function(){for(var e=0,r=this.supportedScanTypes;ee)throw"Max ".concat(e," values expected for ")+"supportedScanTypes";for(var r=0,n=t;r0&&i[i.length-1])||6!==a[0]&&2!==a[0])){s=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]20){var e=t.substring(0,8),r=t.length,n=t.substring(r-8,r);t="".concat(e,"....").concat(n)}var i=p.fileSelectionChooseAnother()+" - "+t;this.fileSelectionButton.innerText=i},t.prototype.setInitialValueToButton=function(){var t=p.fileSelectionChooseImage()+" - "+p.fileSelectionNoImageSelected();this.fileSelectionButton.innerText=t},t.prototype.getFileScanInputId=function(){return"html5-qrcode-private-filescan-input"},t.create=function(e,r,n){return new t(e,r,n)},t}(),ut=function(){function t(t){this.selectElement=ot.createElement("select",it.CAMERA_SELECTION_SELECT_ID),this.cameras=t,this.options=[]}return t.prototype.render=function(t){var e=document.createElement("span");e.style.marginRight="10px";var r=this.cameras.length;if(0===r)throw new Error("No cameras found");if(1===r)e.style.display="none";else{var n=p.selectCamera();e.innerText="".concat(n," (").concat(this.cameras.length,") ")}for(var i=1,o=0,s=this.cameras;o0?(t.removeChild(e),n.renderCameraSelection(r)):(n.setHeaderMessage(p.noCameraFound(),U.STATUS_WARNING),i())})).catch((function(t){n.persistedDataManager.setHasPermission(!1),r?r.disabled=!1:i(),n.setHeaderMessage(t,U.STATUS_WARNING),n.showHideScanTypeSwapLink(!0)}))},t.prototype.createPermissionButton=function(t,e){var r=this,n=ot.createElement("button",this.getCameraPermissionButtonId());n.innerText=p.cameraPermissionTitle(),n.addEventListener("click",(function(){n.disabled=!0,r.createCameraListUi(t,e,n)})),e.appendChild(n)},t.prototype.createPermissionsUi=function(t,e){var r=this;nt.isCameraScanType(this.currentScanType)&&this.persistedDataManager.hasCameraPermissions()?rt.hasPermissions().then((function(n){n?r.createCameraListUi(t,e):(r.persistedDataManager.setHasPermission(!1),r.createPermissionButton(t,e))})).catch((function(n){r.persistedDataManager.setHasPermission(!1),r.createPermissionButton(t,e)})):this.createPermissionButton(t,e)},t.prototype.createSectionControlPanel=function(){var t=document.getElementById(this.getDashboardSectionId()),e=document.createElement("div");t.appendChild(e);var r=document.createElement("div");r.id=this.getDashboardSectionCameraScanRegionId(),r.style.display=nt.isCameraScanType(this.currentScanType)?"block":"none",e.appendChild(r);var n=document.createElement("div");n.style.textAlign="center",r.appendChild(n),this.scanTypeSelector.isCameraScanRequired()&&this.createPermissionsUi(r,n),this.renderFileScanUi(e)},t.prototype.renderFileScanUi=function(t){var e=nt.isFileScanType(this.currentScanType),r=this;this.fileSelectionUi=ht.create(t,e,(function(t){if(!r.html5Qrcode)throw"html5Qrcode not defined";nt.isFileScanType(r.currentScanType)&&(r.setHeaderMessage(p.loadingImage()),r.html5Qrcode.scanFileV2(t,!0).then((function(t){r.resetHeaderMessage(),r.qrCodeSuccessCallback(t.decodedText,t)})).catch((function(t){r.setHeaderMessage(t,U.STATUS_WARNING),r.qrCodeErrorCallback(t,u.createFrom(t))})))}))},t.prototype.renderCameraSelection=function(t){var e=this,r=this,n=document.getElementById(this.getDashboardSectionCameraScanRegionId());n.style.textAlign="center";var i=dt.create(n,!1),o=ut.create(n,t),s=document.createElement("span"),a=ot.createElement("button",it.CAMERA_START_BUTTON_ID);a.innerText=p.scanButtonStartScanningText(),s.appendChild(a);var c,l=ot.createElement("button",it.CAMERA_STOP_BUTTON_ID);l.innerText=p.scanButtonStopScanningText(),l.style.display="none",l.disabled=!0,s.appendChild(l),n.appendChild(s);var h=function(t){t||(a.style.display="none"),a.innerText=p.scanButtonStartScanningText(),a.style.opacity="1",a.disabled=!1,t&&(a.style.display="inline-block")};if(a.addEventListener("click",(function(t){a.innerText=p.scanButtonScanningStarting(),o.disable(),a.disabled=!0,a.style.opacity="0.5",e.scanTypeSelector.hasMoreThanOneScanType()&&r.showHideScanTypeSwapLink(!1),r.resetHeaderMessage();var n,u=o.getValue();r.persistedDataManager.setLastUsedCameraId(u),r.html5Qrcode.start(u,(n=r.config,{fps:n.fps,qrbox:n.qrbox,aspectRatio:n.aspectRatio,disableFlip:n.disableFlip,videoConstraints:n.videoConstraints}),r.qrCodeSuccessCallback,r.qrCodeErrorCallback).then((function(t){l.disabled=!1,l.style.display="inline-block",h(!1);var n=r.html5Qrcode.getRunningTrackCameraCapabilities();!0===e.config.showTorchButtonIfSupported&&function(t){t.torchFeature().isSupported()?(c?c.updateTorchCapability(t.torchFeature()):c=lt.create(s,t.torchFeature(),{display:"none",marginLeft:"5px"},(function(t){r.setHeaderMessage(t,U.STATUS_WARNING)})),c.show()):c&&c.hide()}(n),!0===e.config.showZoomSliderIfSupported&&function(t){var r=t.zoomFeature();if(r.isSupported()){i.setOnCameraZoomValueChangeCallback((function(t){r.apply(t)}));var n,o,s,a=1;e.config.defaultZoomValueIfSupported&&(a=e.config.defaultZoomValueIfSupported),n=a,o=r.min(),a=n>(s=r.max())?s:n",e.appendChild(t.cameraScanImage)},this.cameraScanImage.width=64,this.cameraScanImage.style.opacity="0.8",this.cameraScanImage.src=Z,this.cameraScanImage.alt=p.cameraScanAltText()},t.prototype.insertFileScanImageToScanRegion=function(){var t=this,e=document.getElementById(this.getScanRegionId());if(this.fileScanImage)return e.innerHTML="
    ",void e.appendChild(this.fileScanImage);this.fileScanImage=new Image,this.fileScanImage.onload=function(r){e.innerHTML="
    ",e.appendChild(t.fileScanImage)},this.fileScanImage.width=64,this.fileScanImage.style.opacity="0.8",this.fileScanImage.src=Q,this.fileScanImage.alt=p.fileScanAltText()},t.prototype.clearScanRegion=function(){document.getElementById(this.getScanRegionId()).innerHTML=""},t.prototype.getDashboardSectionId=function(){return"".concat(this.elementId,"__dashboard_section")},t.prototype.getDashboardSectionCameraScanRegionId=function(){return"".concat(this.elementId,"__dashboard_section_csr")},t.prototype.getDashboardSectionSwapLinkId=function(){return it.SCAN_TYPE_CHANGE_ANCHOR_ID},t.prototype.getScanRegionId=function(){return"".concat(this.elementId,"__scan_region")},t.prototype.getDashboardId=function(){return"".concat(this.elementId,"__dashboard")},t.prototype.getHeaderMessageContainerId=function(){return"".concat(this.elementId,"__header_message")},t.prototype.getCameraPermissionButtonId=function(){return it.CAMERA_PERMISSION_BUTTON_ID},t.prototype.getCameraScanRegion=function(){return document.getElementById(this.getDashboardSectionCameraScanRegionId())},t.prototype.getDashboardSectionSwapLink=function(){return document.getElementById(this.getDashboardSectionSwapLinkId())},t.prototype.getHeaderMessageDiv=function(){return document.getElementById(this.getHeaderMessageContainerId())},t}()})(),__Html5QrcodeLibrary__=n})();if (window) { if (!Html5QrcodeScanner) { var Html5QrcodeScanner = window.__Html5QrcodeLibrary__.Html5QrcodeScanner; } if (!Html5Qrcode) { var Html5Qrcode = window.__Html5QrcodeLibrary__.Html5Qrcode; } if (!Html5QrcodeSupportedFormats) { var Html5QrcodeSupportedFormats = window.__Html5QrcodeLibrary__.Html5QrcodeSupportedFormats } if (!Html5QrcodeScannerState) { var Html5QrcodeScannerState = window.__Html5QrcodeLibrary__.Html5QrcodeScannerState; } if (!Html5QrcodeScanType) { var Html5QrcodeScanType = window.__Html5QrcodeLibrary__.Html5QrcodeScanType; }} \ No newline at end of file diff --git a/system/lan/english.json b/system/lan/english.json index d900c1a4..af4be094 100644 --- a/system/lan/english.json +++ b/system/lan/english.json @@ -312,7 +312,6 @@ "Reminder_3_days": "Reminder 3 days", "Reminder_1_day": "Reminder 1 day", "PPPOE_Password": "PPPOE Password", - "User_Cannot_change_this__only_admin__if_it_Empty_it_will_use_user_password": "User Cannot change this, only admin. if it Empty it will use user password", "Invoice_Balance_Message": "Invoice Balance Message", "Invoice_Notification_Payment": "Invoice Notification Payment", "Balance_Notification_Payment": "Balance Notification Payment", @@ -696,5 +695,7 @@ "Routers_Geo_Location_Information": "Routers Geo Location Information", "Coverage": "Coverage", "PPPoE_Username_already_used_by_another_customer": "PPPoE Username already used by another customer", - "just_now": "just now" + "just_now": "just now", + "Not_Working_for_freeradius": "Not Working for freeradius", + "User_Cannot_change_this__only_admin__if_it_Empty_it_will_use_Customer_Credentials": "User Cannot change this, only admin. if it Empty it will use Customer Credentials" } \ No newline at end of file diff --git a/ui/ui/customers-add.tpl b/ui/ui/customers-add.tpl index 730986ad..e3b97517 100644 --- a/ui/ui/customers-add.tpl +++ b/ui/ui/customers-add.tpl @@ -12,7 +12,7 @@
    {if $_c['country_code_phone'] != ''} + class="glyphicon glyphicon-phone-alt"> {else} @@ -89,7 +89,7 @@
    -
    +
    @@ -99,24 +99,25 @@
    + {Lang::T('Not Working for freeradius')}
    + onmouseleave="this.type = 'password'" onmouseenter="this.type = 'text'">
    + {Lang::T('Not Working for freeradius')}
    - {Lang::T('User Cannot change this, only admin. if it Empty it will use user password')} + {Lang::T('User Cannot change this, only admin. if it Empty it will use Customer Credentials')}
    @@ -132,9 +133,12 @@
    @@ -167,8 +171,7 @@
    - + {Lang::T('City of Resident')}
    @@ -183,16 +186,14 @@
    - + {Lang::T('State of Resident')}
    - + {Lang::T('Zip Code')}
    @@ -208,37 +209,37 @@ {literal} - + + {include file="sections/footer.tpl"} \ No newline at end of file From 0fa78966ef267c99041c37c8992cd52e89de7dca Mon Sep 17 00:00:00 2001 From: Ibnu Maksum Date: Tue, 13 Aug 2024 10:32:34 +0700 Subject: [PATCH 065/841] radius rest, check pppoe_username and pppoe_password. allow empty password for voucher --- radius.php | 177 +++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 137 insertions(+), 40 deletions(-) diff --git a/radius.php b/radius.php index 15d6acb1..24fb5784 100644 --- a/radius.php +++ b/radius.php @@ -40,23 +40,67 @@ try { $password = _req('password'); $CHAPassword = _req('CHAPassword'); $CHAPchallenge = _req('CHAPchallenge'); + $isCHAP = false; if (!empty($CHAPassword)) { - $c = ORM::for_table('tbl_customers')->select('password')->whereRaw("BINARY `username` = '$username'")->find_one(); - //if verified - if (Password::chap_verify($c['password'], $CHAPassword, $CHAPchallenge)) { - $password = $c['password']; - $isVoucher = false; - }else{ - // check if voucher - if (Password::chap_verify($username, $CHAPassword, $CHAPchallenge)) { - $isVoucher = true; - $password = $username; + $c = ORM::for_table('tbl_customers')->select('password')->select('pppoe_password')->whereRaw("BINARY `username` = '$username'")->find_one(); + if ($c) { + if (Password::chap_verify($c['password'], $CHAPassword, $CHAPchallenge)) { + $password = $c['password']; + $isVoucher = false; + $isCHAP = true; + } else if (!empty($c['pppoe_password']) && Password::chap_verify($c['pppoe_password'], $CHAPassword, $CHAPchallenge)) { + $password = $c['pppoe_password']; + $isVoucher = false; + $isCHAP = true; } else { - show_radius_result(['Reply-Message' => 'Username or Password is wrong'], 401); + // check if voucher + if (Password::chap_verify($username, $CHAPassword, $CHAPchallenge)) { + $isVoucher = true; + $password = $username; + } else { + // no password is voucher + if (Password::chap_verify('', $CHAPassword, $CHAPchallenge)) { + $isVoucher = true; + $password = $username; + } else { + show_radius_result(['Reply-Message' => 'Username or Password is wrong'], 401); + } + } + } + } else { + $c = ORM::for_table('tbl_customers')->select('password')->select('pppoe_password')->whereRaw("BINARY `pppoe_username` = '$username'")->find_one(); + if ($c) { + if (Password::chap_verify($c['password'], $CHAPassword, $CHAPchallenge)) { + $password = $c['password']; + $isVoucher = false; + $isCHAP = true; + } else if (!empty($c['pppoe_password']) && Password::chap_verify($c['pppoe_password'], $CHAPassword, $CHAPchallenge)) { + $password = $c['pppoe_password']; + $isVoucher = false; + $isCHAP = true; + } else { + // check if voucher + if (Password::chap_verify($username, $CHAPassword, $CHAPchallenge)) { + $isVoucher = true; + $password = $username; + } else { + // no password is voucher + if (Password::chap_verify('', $CHAPassword, $CHAPchallenge)) { + $isVoucher = true; + $password = $username; + } else { + show_radius_result(['Reply-Message' => 'Username or Password is wrong'], 401); + } + } + } } } } else { - if (empty($username) || empty($password)) { + if (!empty($username) && empty($password)) { + // Voucher with empty password + $isVoucher = true; + $password = $username; + } else if (empty($username) || empty($password)) { show_radius_result([ "control:Auth-Type" => "Reject", "reply:Reply-Message" => 'Login invalid......' @@ -90,25 +134,67 @@ try { $isVoucher = ($username == $password); $CHAPassword = _req('CHAPassword'); $CHAPchallenge = _req('CHAPchallenge'); + $isCHAP = false; if (!empty($CHAPassword)) { - $c = ORM::for_table('tbl_customers')->select('password')->whereRaw("BINARY `username` = '$username'")->find_one(); - //if verified - if (Password::chap_verify($c['password'], $CHAPassword, $CHAPchallenge)) { - $password = $c['password']; - $isVoucher = false; - }else{ - // check if voucher - if (Password::chap_verify($username, $CHAPassword, $CHAPchallenge)) { - $isVoucher = true; - $password = $username; + $c = ORM::for_table('tbl_customers')->select('password')->select('pppoe_password')->whereRaw("BINARY `username` = '$username'")->find_one(); + if ($c) { + if (Password::chap_verify($c['password'], $CHAPassword, $CHAPchallenge)) { + $password = $c['password']; + $isVoucher = false; + $isCHAP = true; + } else if (!empty($c['pppoe_password']) && Password::chap_verify($c['pppoe_password'], $CHAPassword, $CHAPchallenge)) { + $password = $c['pppoe_password']; + $isVoucher = false; + $isCHAP = true; } else { - show_radius_result(['Reply-Message' => 'Username or Password is wrong'], 401); + // check if voucher + if (Password::chap_verify($username, $CHAPassword, $CHAPchallenge)) { + $isVoucher = true; + $password = $username; + } else { + // no password is voucher + if (Password::chap_verify('', $CHAPassword, $CHAPchallenge)) { + $isVoucher = true; + $password = $username; + } else { + show_radius_result(['Reply-Message' => 'Username or Password is wrong'], 401); + } + } + } + } else { + $c = ORM::for_table('tbl_customers')->select('password')->select('pppoe_password')->whereRaw("BINARY `pppoe_username` = '$username'")->find_one(); + if ($c) { + if (Password::chap_verify($c['password'], $CHAPassword, $CHAPchallenge)) { + $password = $c['password']; + $isVoucher = false; + $isCHAP = true; + } else if (!empty($c['pppoe_password']) && Password::chap_verify($c['pppoe_password'], $CHAPassword, $CHAPchallenge)) { + $password = $c['pppoe_password']; + $isVoucher = false; + $isCHAP = true; + } else { + // check if voucher + if (Password::chap_verify($username, $CHAPassword, $CHAPchallenge)) { + $isVoucher = true; + $password = $username; + } else { + // no password is voucher + if (Password::chap_verify('', $CHAPassword, $CHAPchallenge)) { + $isVoucher = true; + $password = $username; + } else { + show_radius_result(['Reply-Message' => 'Username or Password is wrong'], 401); + } + } + } } } - //if ($response == $CHAPr) { echo 'ok betul 100'; }else{ echo 'salah'; } // untuk keperluan debug - } else { //kalo chappassword kosong brrti eksekusi yg ini - - if (empty($username) || empty($password)) { + } else { + if (!empty($username) && empty($password)) { + // Voucher with empty password + $isVoucher = true; + $password = $username; + } else if (empty($username) || empty($password)) { show_radius_result([ "control:Auth-Type" => "Reject", "reply:Reply-Message" => 'Login invalid......' @@ -117,11 +203,22 @@ try { } $tur = ORM::for_table('tbl_user_recharges')->whereRaw("BINARY `username` = '$username'")->find_one(); if ($tur) { - if (!$isVoucher && empty($CHAPassword)) { - $d = ORM::for_table('tbl_customers')->select('password')->whereRaw("BINARY `username` = '$username'")->find_one(); - if ($d['password'] != $password) { - if ($d['pppoe_password'] != $password) { - show_radius_result(['Reply-Message' => 'Username or Password is wrong'], 401); + if (!$isVoucher && !$isCHAP) { + $d = ORM::for_table('tbl_customers')->select('password')->select('pppoe_password')->whereRaw("BINARY `username` = '$username'")->find_one(); + if ($d) { + if ($d['password'] != $password) { + if ($d['pppoe_password'] != $password) { + show_radius_result(['Reply-Message' => 'Username or Password is wrong'], 401); + } + } + } else { + $d = ORM::for_table('tbl_customers')->select('password')->select('pppoe_password')->whereRaw("BINARY `pppoe_username` = '$username'")->find_one(); + if ($d) { + if ($d['password'] != $password) { + if ($d['pppoe_password'] != $password) { + show_radius_result(['Reply-Message' => 'Username or Password is wrong'], 401); + } + } } } } @@ -136,7 +233,7 @@ try { $v->status = "1"; $v->used_date = date('Y-m-d H:i:s'); $v->save(); - $tur = ORM::for_table('tbl_user_recharges')->where('username', $username)->find_one(); + $tur = ORM::for_table('tbl_user_recharges')->whereRaw("BINARY `code` = '$username'")->find_one(); if ($tur) { process_radiust_rest($tur, $code); } else { @@ -167,7 +264,7 @@ try { } header("HTTP/1.1 200 ok"); $d = ORM::for_table('rad_acct') - ->where('username', $username) + ->whereRaw("BINARY `code` = '$username'") ->where('acctstatustype', _post('acctStatusType')) ->findOne(); if (!$d) { @@ -175,10 +272,10 @@ try { } $acctOutputOctets = _post('acctOutputOctets', 0); $acctInputOctets = _post('acctInputOctets', 0); - if(_post('acctStatusType')=='Stop'){ + if (_post('acctStatusType') == 'Stop') { // log in the Start only $start = ORM::for_table('rad_acct') - ->where('username', $username) + ->whereRaw("BINARY `code` = '$username'") ->where('acctstatustype', 'Start') ->findOne(); if (!$start) { @@ -194,7 +291,7 @@ try { $start->save(); $d->acctOutputOctets = 0; $d->acctInputOctets = 0; - }else{ + } else { if ($acctOutputOctets !== false && $acctInputOctets !== false) { $d->acctOutputOctets += intval($acctOutputOctets); $d->acctInputOctets += intval($acctInputOctets); @@ -215,8 +312,8 @@ try { $d->macaddr = _post('macAddr'); $d->dateAdded = date('Y-m-d H:i:s'); $d->save(); - if($d->acctstatustype == 'Start'){ - $tur = ORM::for_table('tbl_user_recharges')->where('username', $username)->where('status', 'on')->where('routers', 'radius')->find_one(); + if ($d->acctstatustype == 'Start') { + $tur = ORM::for_table('tbl_user_recharges')->whereRaw("BINARY `code` = '$username'")->where('status', 'on')->where('routers', 'radius')->find_one(); $plan = ORM::for_table('tbl_plans')->where('id', $tur['plan_id'])->find_one(); if ($plan['limit_type'] == "Data_Limit" || $plan['limit_type'] == "Both_Limit") { $totalUsage = $d['acctOutputOctets'] + $d['acctInputOctets']; @@ -295,7 +392,7 @@ function process_radiust_rest($tur, $code) if ($plan['typebp'] == "Limited") { if ($plan['limit_type'] == "Data_Limit" || $plan['limit_type'] == "Both_Limit") { - $raddact = ORM::for_table('rad_acct')->where('username', $tur['username'])->where('acctstatustype', 'Start')->find_one(); + $raddact = ORM::for_table('rad_acct')->whereRaw("BINARY `code` = '$tur[username]'")->where('acctstatustype', 'Start')->find_one(); $totalUsage = intval($raddact['acctOutputOctets']) + intval($raddact['acctInputOctets']); $attrs['reply:Mikrotik-Total-Limit'] = Text::convertDataUnit($plan['data_limit'], $plan['data_unit']) - $totalUsage; if ($attrs['reply:Mikrotik-Total-Limit'] < 0) { From 0fae434c1b457c839438333a4374a4c1b1098dba Mon Sep 17 00:00:00 2001 From: Ibnu Maksum Date: Tue, 13 Aug 2024 11:42:22 +0700 Subject: [PATCH 066/841] Reports with chart --- system/controllers/reports.php | 101 ++++++++++- system/lan/english.json | 3 +- ui/ui/{reports-daily.tpl => reports.tpl} | 221 +++++++++++++++-------- version.json | 2 +- 4 files changed, 249 insertions(+), 78 deletions(-) rename ui/ui/{reports-daily.tpl => reports.tpl} (52%) diff --git a/system/controllers/reports.php b/system/controllers/reports.php index 2f1c85dd..a1c4e3ca 100644 --- a/system/controllers/reports.php +++ b/system/controllers/reports.php @@ -147,6 +147,105 @@ switch ($action) { } } break; + case 'line': + $query = ORM::for_table('tbl_transactions') + ->whereRaw("UNIX_TIMESTAMP(CONCAT(`recharged_on`,' ',`recharged_time`)) >= " . strtotime("$sd $ts")) + ->whereRaw("UNIX_TIMESTAMP(CONCAT(`recharged_on`,' ',`recharged_time`)) <= " . strtotime("$ed $te")) + ->order_by_desc('id'); + if (count($tps) > 0) { + $query->where_in('type', $tps); + } + if (count($mts) > 0) { + if (count($mts) != count($methods)) { + foreach ($mts as $mt) { + $query->where_like('method', "$mt - %"); + } + } + } + if (count($rts) > 0) { + $query->where_in('routers', $rts); + } + if (count($plns) > 0) { + $query->where_in('plan_name', $plns); + } + $datas = $query->find_array(); + $period = new DatePeriod( + new DateTime($sd), + new DateInterval('P1D'), + new DateTime($ed) + ); + $pos = 0; + $dates = []; + foreach ($period as $key => $value) { + $dates[] = $value->format('Y-m-d'); + } + $dates = array_reverse($dates); + $result = []; + $temp; + foreach ($dates as $date) { + $result['labels'][] = $date; + // type + foreach ($tps as $key) { + if (!isset($temp[$key][$date])) { + $temp[$key][$date] = 0; + } + foreach ($datas as $data) { + if ($data['recharged_on'] == date('Y-m-d', strtotime($date)) && $data['type'] == $key) { + $temp[$key][$date] += 1; + } + } + } + //plan + foreach ($plns as $key) { + if (!isset($temp[$key][$date])) { + $temp[$key][$date] = 0; + } + foreach ($datas as $data) { + if ($data['recharged_on'] == date('Y-m-d', strtotime($date)) && $data['plan_name'] == $key) { + $temp[$key][$date] += 1; + } + } + } + //method + foreach ($mts as $key) { + if (!isset($temp[$key][$date])) { + $temp[$key][$date] = 0; + } + foreach ($datas as $data) { + if ($data['recharged_on'] == date('Y-m-d', strtotime($date)) && strpos($data['method'], $key) !== false) { + $temp[$key][$date] += 1; + } + } + } + + foreach ($rts as $key) { + if (!isset($temp[$key][$date])) { + $temp[$key][$date] = 0; + } + foreach ($datas as $data) { + if ($data['recharged_on'] == date('Y-m-d', strtotime($date)) && $data['routers'] == $key) { + $temp[$key][$date] += 1; + } + } + } + $pos++; + if ($pos > 29) { + // only 30days + break; + } + } + foreach ($temp as $key => $value) { + $array = ['label' => $key]; + $total = 0; + foreach ($value as $k => $v) { + $total += $v; + $array['data'][] = $v; + } + if($total>0){ + $result['datas'][] = $array; + } + } + break; default: $result = ['labels' => [], 'datas' => []]; } @@ -285,6 +384,6 @@ switch ($action) { $ui->assign('dr', $dr); $ui->assign('mdate', $mdate); run_hook('view_daily_reports'); #HOOK - $ui->display('reports-daily.tpl'); + $ui->display('reports.tpl'); break; } diff --git a/system/lan/english.json b/system/lan/english.json index eb4b5e4a..6fa32501 100644 --- a/system/lan/english.json +++ b/system/lan/english.json @@ -700,5 +700,6 @@ "User_Cannot_change_this__only_admin__if_it_Empty_it_will_use_Customer_Credentials": "User Cannot change this, only admin. if it Empty it will use Customer Credentials", "Failed_to_buy_package": "Failed to buy package", "New_Voucher_Created": "New Voucher Created", - "New_Voucher_for_10mbps_Created": "New Voucher for 10mbps Created" + "New_Voucher_for_10mbps_Created": "New Voucher for 10mbps Created", + "Show_Chart": "Show Chart" } \ No newline at end of file diff --git a/ui/ui/reports-daily.tpl b/ui/ui/reports.tpl similarity index 52% rename from ui/ui/reports-daily.tpl rename to ui/ui/reports.tpl index 49e18fa9..234d715e 100644 --- a/ui/ui/reports-daily.tpl +++ b/ui/ui/reports.tpl @@ -8,6 +8,13 @@

    {Lang::T('Filter')}

    -
    -
    -
    - -
    -
    - -
    -
    - -
    -
    - +
    +
    +
    +

    {Lang::dateFormat($sd)} - {Lang::dateFormat($ed)} Max 30 days

    +
    +
    + +
    +
    +
    @@ -127,71 +144,125 @@ - + if (getCookie('show_report_graph') != 'hide') { + $("#chart_area").removeClass("hidden"); + document.getElementById('show_chart').checked = true; + showChart(); + } + + }); + + function setShowChart() { + if (document.getElementById('show_chart').checked) { + setCookie('show_report_graph', 'show', 30); + } else { + setCookie('show_report_graph', 'hide', 30); + } + location.reload(); + } + + function getLineChartData() { + $.getJSON("{/literal}{$_url}{literal}reports/ajax/line&{/literal}{$filter}{literal}", function( data ) { + var linechart = new Chart(document.getElementById('line_cart'), { + type: 'line', + data: { + labels: data.labels, + datasets: data.datas, + }, + options: { + maintainAspectRatio: false, + aspectRatio: 1, + plugins: { + autocolors: { + mode: 'data' + }, + legend: { + position: 'bottom' + } + } + } + }); + }); + } + // [{ + // label: 'a', + // data: [8, 3, 9, 2, 7, 4, 2] + // }, { + // label: 'b', + // data: [6, 4, 5, 5, 9, 6, 3] + // }, { + // label: 'c', + // data: [5, 2, 3, 6, 4, 8, 6] + // }] + +{/literal} {include file="sections/footer.tpl"} \ No newline at end of file diff --git a/version.json b/version.json index 56b6712c..89ba0a92 100644 --- a/version.json +++ b/version.json @@ -1,3 +1,3 @@ { - "version": "2024.8.9.1" + "version": "2024.8.13" } \ No newline at end of file From afa061648727a319d8576ead471586833e30fec1 Mon Sep 17 00:00:00 2001 From: Focuslinkstech <45756999+Focuslinkstech@users.noreply.github.com> Date: Tue, 13 Aug 2024 12:45:32 +0100 Subject: [PATCH 067/841] Create DejaVuSansMono.ttf add missing mpdf fonts --- .../mpdf/mpdf/ttfonts/DejaVuSansMono.ttf | Bin 0 -> 335068 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 system/vendor/mpdf/mpdf/ttfonts/DejaVuSansMono.ttf diff --git a/system/vendor/mpdf/mpdf/ttfonts/DejaVuSansMono.ttf b/system/vendor/mpdf/mpdf/ttfonts/DejaVuSansMono.ttf new file mode 100644 index 0000000000000000000000000000000000000000..8b7bb2a4e1b2c27786398c320e9020bcc24c3af3 GIT binary patch literal 335068 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�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

    b z?(GLH8k^m!HD?)&jw|*&LjRS_ah29*>2e5v;;Sot8XY$Gj2eS`{nG9CumitDQ3iX8 zTf}_$D8xQ4YX=)?jJdFIiJ8d>&A?cb8-rgZ7*eK5>E`@#vjm05WmP#fV3Eex|G8?V z$z#pt^bTLPN2L$C?XH0{Um9StLKDwf%+9QAuUc((%=_D{kv6;0=1O3L+!)i3UGwrg zS~20Vl@Sqa)*3cGL%)4!iwT~-Oq?lD<}hpA?qPpDeVLOBdG$I^(B#U+I~-Q;jgQ~` zMR}Gp-mxyh#)LX+Al=|Dk>RxNG*)1bK5mc{8$u&5GRWBTD??ZTHgEM|WFSEp@ zkOO!{8GJ2c>5D7oHouHl(&vBriPZdb|4%>BDqOv==_hu5KY#PbAJZeL_qZ@Aucv*b zi$_19H$KF!9{NNYC&g(0?ZRc!IAQWP`>;2r=O)QDhs4gY$LCwD7pFj$j^3?{dkKNe4Wl6JcPT z=_Cgn+u@TQNtuq6I{N%F=Xw_X0N)KAJ38G}EDG>{EhLji$L{YyE$8~1joET3R!c{* zDqT;!p+lkcYDTKJ)C`%R&T9t(6qjeJ%a%&#UWE5_D8#k6tPZ1zX}nEp6Sixtc9WC} zvb`HC)Hv#ou(ZI!$7HhGoK72itkEb{NI9}BHZzn{a1m~?+M&R}#`1 zxS(Wb&(&t5-72g_L(nYf-dRIfvsjbeR$D-$QZW!8sALdvyq?`b^;rBexTA?Eog`IrgYVjGGS+py%!BB1fmVta%=BVn8h%#>?Kl{sy=`P3Tr_C zFJe8#@F#aE8o*N0{FLAJZ{Z%C$HAEmTd7QAV$1v)Q-%-CPvpl(4xZ7n zU_r}_!6V~H4jn#a1_#5);Y}@5FJIU)X;f1Ze@&w=nz3NfwCO{K=OrNvM%zBcUeW@* zr;fde@jQ&S43%d_PMXiceS$RL{;Vcv8hh4vuJC((p6X5w4Fd)=G<2%=_`Lp#&hEN!nO3z7v*&68$cws?BWu;B@8ws4AE_%+)D-%lE5)n$u%iOAccqK)t& z!fRmP8_FXKj=Vw^{N$lG(On+WZ!PUZCa)t?$kcUYGVQ}{ABQkckB`HtvsGKSlI7gX zbR12=At{f*5_b@uy`u;4v_&Y#JD9IwJ|yx{{0s3Jj9oAjWrjT0vV<-m-IkDUq#pm# z1xx2lozOHGW~i~D11C?pWOjRMz?3OMFusA@RyU5 zo7XWhdL21HZ(hfcw2t0P4sZu7wqPVTQB;`74QJad7F%{0PHBn~xsjlati1q9h%nRk zxp1G*1vrYc69DIWLU93>GGrx_8Laiv{S+pbzxq#d`F}k02D;Nj{1@frhUJ=ubMrbT zMz5z0WcqqCowVRT+Q4lePx{hF$KyQUmDgMYyS~E6|JH{G+E?j^fd!DrZOgJ1jC;Mdv|T;Cz3 zgG)*VmvUh``&az?m0b7h-+tKf!w&qzE=DfS{Oy6hhQmIg8mkH;ydEf^A&!cbgpWr< zDhm(BnIRl94k7Lb6a8Ii>D}Z(G<7P5&v^th@8I7z9ju^#AypOdPkopk-o%Zgu0=qjAdy+0-TC~B-UL5VSxon{*AA+WtDVv2m=yQwbeMvu>x0pUh)-9epo8(Z% z1p2R^$N%#4_@C*&xQqWyH%0ILSClOHlq`(W2U7IZetPPmhe&8Y8y`^V!yfr2VU^@V z6l>3@%Rp4{L}?M@1qkT=^)IA)89glh_X|C|j8xGVmhmn!3rnOoAI3kroy>ap%|{-F z89k>MiSv3(go(fut23NJRK~?mO*g%~>j>FK=KkxHPtkmWyzEPr(eI+E9?;7T~a7>cW)v9MIevFj4TQMw?ps6bXx-hllV9lF1O zz|i6L_s5XOPn{%H<4=wmLtlKqnf5;Q4t;U_JI&2YNc;+tpl@D5-(IqqzI_FKlO(Pn zaenUjcgK!BKP#zze=K?8)Vtgumi?2DI>+$&_dC~f-$exwzWzQh*Q5LOEf5xJHL zV9)b={@et8fyaM+!Z4a>rBSzxE&kxZyLLMU8idROC zU5r>*Ajn+G5Qwsm!iy);sNn41hY7%4O3xT`HgOqkMHLd&*^Q^sD z9Xm8_*P7{VCQQryxg=~jw?Aa)nCR0LJ$+H8r^l8DVU>W;U+8Ilud=RMje6D)tsrQI z&V+${*Ro!E^m7&ZxwtY|IXctNtazPT>9*=e<94RJuD4viNdx=gA+yvPl<&>xBwfC0 zq{iV^a*s-zQbvmf_THH-s!Xa@+cL4L+mJX;Pz~u;HEEhe0hN=x1pP`IqX1iVp1(+m zb3+!fIFMUyV;yKy`h#7jl`#U)PoLa5Q@Zoy>3W{iSyW}yIuy?h6e&SJCS{R7uS4+} za{m)Wr?xMJ9l|NegBLqs!A1)kD>7z(*W>aKW)Iomi^t%V*C}U~(`>kA#wr_n@?ez* z>N(JroHdqveRD&j(UlW!u5Rodt}cv^?3C=Wp+~aQ$auUyw@3e)=A0atv9b5aYl`CW z_zh!vu*{KBwSD?zGWYD$jpa_%#u^%{o5NwZsekX0*Cn}WPM1L)Pu7g7sqt9y6GPT` zT?GYK^dB@bQD2`JIkfk}@&cD@-SAkx#Z!Y!$vmyu<8-+Us(60Qm@c(0b0RV1DzB53 z88|Y(TepJYLwli&Gi&Y8Tvn!bbWMH&WiVa@MF{$t2ZW~}+wD|5sCWsS56EL^!%$*~ zu*nt?f5g`Q3{MxbEJpvb1+WUSd*)VXJFd9A5WMM2MA{pt(K`QTGN1P6wLMx&!?|fS7f=>>Vnb|rJ%EP(r7)AYDa)5hVYtRE1Y%9ILuzx6$^8Zl&#S9THVx=E zxrbRDykuxJD0-^Gg~4!59+pWSjXH}X*?BeLU_qohOAN$^%t5(^$$bY5Pt?^Vh7agF zxxuW?M!A6Kt_c?gBGrj(!evc^y_U}#w41$FznQmX7d6z>G!$jqc(dQ?HQR$;pS;eE zfN1_M%mBZIUDJQ%xAAjRmdtNizkvdz-jdmAyV8%H&yzkfg|w^0GD^WeRguYLBE#oy zy9Ay^^K5pzEe}3MJ0`{z`}6Y>`Oz?fHJMFee}1&s>4f6=o~htj2N{l%#Wte8ldICW?xyDoTnHQKwx> zl~hy}vy>@MZ?&3o0*P30L2fkSw^;crH7EADo`9S^2Pb{+RQyA6Lh&O!5&U0bw&Ri< zETJQ!|650Ltenh2*hp-jkl8H9Opftk#pUtK>_Pw=UOJ@-F*9^KW^jpYaAz_~oCyLI z%h7H-Cy#k~)I$_w#K5)iIz!B#jFlAS#=;@1#bSzhVop~{w7?$$4y~bBq$pmP=PzX) zX^Qv@qLZaZ5HysfP$=c+$0BkuJSuTHV;;F!IF?&f5=;7H23^{oI*j^S3aK9+iV^Q zf`grcvNbu}(ekW=^Yu7@$Ick&Z2*E|qH03O;&{>T4aWn}{+n}x`SIeSyja9*6U=rf z_VWr$W&BXM)WeiRBd)qg)Oq zX?q|Z_HtY7Jl_~K`#f%k4M!YwHiz5eGe;YFKJ}HTb4Oj_0XA=z-W*Vw)8F>2^~iXUd#3f&SP!zwgi*mv75&-NaB3@ z4IQrmSZWocY?VAtB;TUU$XOmT7&L4owAn1B3UIb9iZQ zwcN1tIRP8suwMBS26C=v&f%SG6uA2hDi!P+{ zknO7m{5hd8PE|QgI35*91pFQ^j@TKp968x>Kd$6L;q3DY1%06$9FoW8D6)Fv*(ii# zsYdLj1_%Pj&&DcEtI@F?2^_p31QytWZi7y}*@Mj$4NTxuOkovlE)%7;NU_a1m}6My~57rsYLZ`gK3CShYbw3GuMm_9HLQKv>u8G zt%HnO%LTVLs&(shf{H%}#GukD1vT;1dA%+tv)XsMyxxup*abP*8*v=Th7AwaDu>0K zuf}WeQk><$OEv07t2uGOt%SwWv7nmg3CH6eY()W#9VC=`in9Zn3d|gvDt2%=Kp9}g z9UM|N+wItA0n=9jmYq47Vnl&vtC4SJ8)7YxU} z!7O-`^apZ6A=ZH~wlw(Sb(wwZx;VB$^#%}1b|@#5?KPs5KM;X2h})w#&`lccM(ug% z*J`v%hJNE(9`Qgf+45I+EYFxmL76Myv1k2P8m*a9$ce`bl8{*f)~W8SyhL?HT}@SG5-~Gbs;Y8H=guraEXl<1VeEj>jLA4) zltgOijOh!o1J>MBkW@;*FT0F>kbY_QW$dNEqe@YVdG%JY3i|x(5V!WP@CEa%;$N6i zEnwh`761Qdy=Nj8%py#D&utYE=< zWB$;rfXUFes=rZV505rm3M+cVI(0Gj!fL&tPhGN8FH==TZujy6t7UYKLu2aSxv$X} z@C;3uOnFV-pwZa3b3e1jku%z2EhvYNur4N6avj$By^Pfrx%Cx=7W3$^U1RKD)z^Rp zV^d;9POdvpu$fd?O4Zt|aFsnkm(!OlWpct_Ltny?nBtOrwc6z_Co4z=m~(M)Qmt~k z%lV09Wz<#EJ6TWP*ZO!8DXfc!%3|HTVkj~C@`%RTclO|6;|hBAEN&h)cy?c_CTB@= zUP$!S#mYkQZUqs-`?MOA3n%O2q0)GrPcEmn^qoCq*x16JJqyPU8#24EMIBzu%6aNz zr8)7s!Z6CcNtef*U3w?Gk@e4JTLovhtRMXWSG)sP#PF;wU~%RI0z`QCS-aorV3#~} zrrFT%J}8cqA|u3QKZS_Y?J9=`7r)T;IuOT{{X*5Na>>7lDH3-ejbD@~hjVoHixM1p zZFi>ydphlDVZYNCblUw|3sUU&&mM4pUp{R@ua=23w!C^Joi?HOzy8&G!nD-#SGUZV z*wSmlwB=W_rxRK_KBZT_x&^oJ6yu?|?KkMB9|Erl;oKxU|5gHTR|>=eK+G^!Yt+*s z)zl)@5w*0SQLgezv&{Dn}i`J+AXbU%gp!;_I*8DtYrOcKOyvbLd~@>at!{T7t%< znE-CZkn0>U7ldWzrj^~2y~?2*)ABxhqp;rTbVlR($*9Tr+;c`#G?^cd;+88C&(F(^ zIUW3S7IQS2>_4)9G8r{np5q;G_mrQEu}mm9BF4%Y%(;2V{z(Z^$5K(`Y%k}CGvImr z&B>_z4vl{9T!ff*GJr4*!-WHeTUN`wkCkd?|4}H2|D0;&$MY;!7gI|%Y=Pp7j|BIV#b}1-bwqcV;1^c zC5ggTpM!TxwlYX#OPW>X?qTNU8Tnq4?&WS^J&;-Pbm#^7Y^mJ6l2wGnX|T&tHd3R zx=UQ0YMo_1D_QV|x4CKKd-NFJJ#~siyU~;6aT4xE-}{)J>_(#LDtv-+og5v(IXd~Q zbkiS#JDRUY4LMF{9g(SFetV@ySalqSO6wW!Lv0^J?>eso?(<<`GnBTT`6>AR=|w`S*Co)U8veZl%J<-9O>@PwGETJ@HBRkGZQq zuKz@7GzY@N!vW@I{?9H_FN}yLyuqM15gidrcmn}%g72TXie;X0%ePFMwq;%voNB zT|eQ&Jc!(y@$3jVU5Tv>R%I&TF^4mtrq7Z(wcq79JAtK09etLi_#d5iWoyM@(UG0q z`da&S!0pTqI>o~ktx7vT&IL#5@->auLGv^q=G@a`LXRF3%;^-@CEMkUH$t5i4B~ks zG^*r~GZc^@h|bnKT-ljxe!R;mN-qqCT3>6w&gS2DIf5#BkkqOI&eTr~dPAy<6Zc3h zJ&1e2CsE{J-~N8V%Or3nW213Ab9cjrt~BsP$wyJzf;);}GSY2nIP)-z1ImFHpveZ^ z128CELmeaQ@zDnWBxcktWsHZ|WJMs?5(;~Tnm5rcG5E=etF0KCEjA5YWQM(+MIUUB z@*E`YbeDvZYQwP_!5gk;1&(3cL@GcWa2kBGPweas!{esLMq21etC|(?mU5;ySpmV5 z?d~KxV4P#Nlc>{C7z-)&2P=42cGv7Iq2f7nG^fzvjH)ceKp%F9Wm(zTS!Egrj<)|` zQL+5xR`YWeLKd>S_=nIBWUtxVA=s1zzHaGtJm4qYW}X)u{A>0n6s@czkHr$ z?z#M8$Wn63U!Q$zoM7+5?`s`cBjoiy`!&{r`H;`w5{Dt1>&ag@@t9L75Axl;66ITzYWIB%Ptdqms?xLEsyE!-nF ziMxKCtK5ntd9@8Y=i*NJS;)fk^oY3g*LlhqO;kc=jIu z8uz34HZ<`HoDHfhQ{tQ2)pdRkxwZ$F*%^+ZT=Yiowy{)y<@vO)Zg0i zKJWl`bWWH-ocdLhb0R^LdCp&EUc6&kt``eBf>T~3JRlvEESWQ zgn6P+F$4B`CbS9O)0tloCUT!^!Uai8kz7j)J+#f?NaS`ZU0B*FFW2dCI&<@+L~g?2 z*hUY{IQab7Yq~=9k$@{xcYdO(qFc9$ssvNFWF?Z7Rb8)bejY@wn1^`26T~bjCPDhJ zW`}OAC_BHK*_2}yCLDcz%C7pZHN^!`>bi>xyH+- z)rRxh%v|ZPvjK;w!gdy0w%p8^K9i>9yzTQQLmk`4kbb1G>tyAaVnco;k7uYi4y)ZZ z92GZ(yEI#(jlHH8N6s!AKHdl~$8CyxuD|__q222YO;2?0(ohx(JN;&lT|d5Y!tmU# zp>SPoZl0l}SJ#}VCC8Fg*eS=dVBkgN{H9o>Q^;%5JBxgU^SX4a=w8~mZ$feHknpU& zS1!BipCo7AlFHb|yt=$(An3B0T~T}2@%_673VUREN-KJGD=~WgS!E`_rO+9w^5#z- zP{tS*rzjz1!fpIvaPNV@592_f43dr3p!F(dg~3_~1c2Y*q#q-k^tddOk;ukHy74w- zl~KVE35Ve2WzlkHx6%r7BRx7Xp3KhXx(;k|RD?sy%SM|0!K|j*P6ofPw0e+cLAg+p zlT(;g5*zhEp}lF4MpIw@;#Te{T_A6myQqZT{m;%7NyKCCRX|oxn03re4IyrI8Vq9 zw`6uX%J>hj->~}9*_}Ig?lkw}wHvM zRn_r|(&Njo+n(P2GAh z_-h9a8-4wTwHMFrgjdhLboGX*@ruf6GnZd^&GsvoA4kl#>Z;ibuH3NmhO5?Hd`V?B zdl#A3ww9kIHbI_7&mlOAD-?sPE^8$}^WvE^FQ(rvUW};eL!O}5(e-re}aLLS4-qnL{*-7S_~UMt_;nscf1Ud7SQg;DLu8dhFqS z`^d#)vh?mAZCCJH#Nn`~Rfu5?w*UCe$LS`r;5gl|iu;oLD#h3->ezsMo74G_O@ljR zA>H%_SwJ_XGo~EC+p)G0e4B_UFMt=)5SU6(oC6M$4{-$8xhDhhynHTX(~#H67u1Qv z!XMILI-3OV)wX*06gYYgp1{-DI1+FNxsHx~n(xi`X+6OD>z{4i1ztSH^2zZ2N$y0p zYY~ZV{L_3NmJJyRd5NCp)#7CsCkj|`$C>VlYj|$tXP=FH?$F483kUx_@{rWtm*|(s z$71d&Sj1|kl;Sqa`GiTxdA642BqWO-;17u75!+XRn0q-a&;ZV_vRKEs!eozoEQ+HN z&Xe)uEaMMczwhz^QZ%vsS~p`w%he}dShI4_m8UkZ zaJg4(I(6kBwCz`Tcse1@KzwBd99Bty+2Cz|66Xv@khXMO$F4_6Le)zJN=lWRMbubQ#p?Ux#QFkB8L zMZ$9aG<4UnfesUxih{XZLGS*UC{rfxJNnzl+y;6#QSK#>z>t4|;#y&xa0QdKpvQnu zfGBTHP1(kcf4pnzF0z3ew>>q57*luEO0e$`mLm=>likE}k(~=EN=3Po#bh~M#qAF7 z4MT{0i82Ezz8rj1mF1f`)4LjeCB(p&V5OquukZTSf0=WV8}3*DFus= zcpxmKq4|pA1Zph@jW3WbO}22cf^kor!aDd7p>OD|mUzfuRKXRVVPk5dE#!rhPPI2= z<8Iq%fY(Nq(SY;ZR=9RDa))DPs{uvSxXJ8Y-~`36$>_0~ao=OwXt2UhpxJ_F5@e%P z$D!mA;3_7|uvi`dSG`h3?t7TmzQi5t43`TGQLOEkBfcz))T&^eRgQckT2Jt~WB`4L zo45Nnc3_IoPGLfGLm4}(m`w<0$VXCnfI^o1nNN|Mj_??2PryrZCi`_ufy258skV z@Ovh`Gj9AllgPbv__?n{8*4y!Kg#WpYSW>;g~YcglNEQfl1vh3rsl`#3hU4^P zcWU!odY@o9`z?3)$PrlJ-$(BQ8j))$xl0%!MAG?H(Gc>RpW%j5H+_ab*&5|OdG=Z8 z!=9nfu>1u1gUJ7swDtgjk_Ep?xxOL)q@|P*4DwWvO~7SW*a9hRmW-^=5LnIx5B8}r z8oZutMB8d%I85CT$fZ-u=-Yl0$O#d@sQ$5-yhb%zuYrl3?KU!XLmWS3D~0f-f+M zo^eK}63QWh$g!a)-2JFRs)|>+;gfssO#M33luB`rOd>BYnUvbQiG0hdbKO>YV2k&K zOpRE(E>gTHT*}`o!?Tr#SiE8cqK=1fW&)=sq8E{OO_Rx~E%jqkC&+WD6Dzsg=DD<) zyLqW=Dg9(AeePPqAG`MKSqAG0#Yth9FaTCI7D()I@B$!-#VwMsWZ|x>p>z9_mz&6( z{`A_5NGbg%tvI=82l-|Zy>k6@5oHPoFd%rkBxJET^&8*yd@I zktz$3e={kC|7&$c-&iabZtTvUN~)3hIq~$zU6VCKh5$~m?PuxCwcD6spsX-y>eb+-imqo(s#sFWW`m) zxpd>krSyxd=nC>cVs5@aF)!iEpO^2)mvh{k{;PW7g~L~m9e4HN7lpVGgcW^Lxd$B%;V&Pwy~b}n8nhE$LTXjAC#JRy2_71vaEsT&Y>(4Vt{p$7PVrJLDt%2*=i_rtEmd1l=bYM(P$#ht=En=bR|b@TuXfSs@dq2&gX#~sOz zMzbSskI6uez%s-M!(q}#r}tgPO&@U0fSv&(tbyzSZ!j7PXSvxPg4>f5iUz#_J1m8a zft~}dk?^-raXcjqPu-Y#1ioN!tqEv684eN&OopmJTw1n5B9C@TyeE<{rsycs;m2ETYvV#s4JN5 zchSFk5gjBP&++>WtSlMjgmI7F^$TYRR$~qa?Ua)Q`1n_t`|>4!QRq5(&dVT7LZIa6 z4*go{f`pgR&@k0@x((7Jrs2j$BF`WAVDA{_ZVX0H?cQxueRKx9)9dN#C2DSS>Y|^$ zT|GgoQ^y@_&mud(HRzk~rQdQw->#z$I!(-bv(^No8#f$2o6K`-JpmiKNjD`oF?4RRhXa#e3!Ww`GZkc8< zDJp&KFL!&)+1X)iRhHzfVaKD_6pYTx%PzFSnK0io09n!$81(9^gQP2NYp|%y?1!UW zt7m9!?NAuhyJ7KM6wD4s^75kL;GuEj4h6%}yu3(Qrr8*ITDX_LhsCnTei(LSWUMlu zDA=lzEj=VR@vJwb#~>33#~gbMhmHuiCAB6bv1aBH79YtEJiEsnd$wIG!H|SA@(j9r<16b1$^}r8SLyK(?!y6C##NL|1+Ko6_YN8F`TrDISZBE48j=_369U3d z$oT3l;Y+1d_6HK+^ZX(#dV!eKzY$@-)6Uk4nPV3?Ar}vcpX#n%6snFQq_w ziafUumeeABmtg@-hvz}nJ|#K;j{NW@hOx-%i!B=$dgC$Q z!VQ)MGrQ1*$wa44y{As~b8G$nsZ)EGl_yXO==U+T2#ZC*tW@tr=MvJH?&EJ%#;~KQ zKoHw_gpVmCts%5G71%LC`<$?!zfsdt2|opd%oh0Z)dlOyj=xVIQ0a-Usi&Rp(+wp} z_whds8MMCS1R<~7-rBhJ-98S&G5D2$zcUTL96|RY@fdccFj!P^NaKiZpE21sTJY_zuu#4o-*avd!_(i9LYtQ-R)(N+s1@j zI1%F;UVL#%3T31cPygrrDJUk5A96Ly^jBJ$jz&@;g~?h1_3pp%AGeC_k+ohb^~HJl zm{N-GNB_MSs+NBvU+bm(HGFzrYj3jx4v^Dr&9o14!zlPcTr6A%+LKz9c5{aP6(~T_ zO77j=KmD}(v)w=bxSM;6JV_h&!kGbn$dh~7k5uP&81T?$Lz(uE>@tnPlHk3(`wo2O z&zFAY$>3yI9l%PUL3=wC_aP?kFtd_HEMl}szC%6Nm}BZ1whN`c5%`TrGto-zFTD@?nP( z80CJUAG4>O`JIwNp)-B)_xYHT?;YZ2tL_)cDGBh4q%+>TQE`g@5I#8YUM%@Y9P9m= zsV`pQoR`B_#gC~kU*a5>)7~=v&L~a^y)t=K1iO}8F?Lo{Uo0XA_^0H&g~f zyqJMTMo6VDr+wtS=heYQunZzR=XfdgCEm=zmAL!{Id29}7#BodPh*ioHj*cpA_X1@ zC3H#3g*`ILI^cqpVHg92Gj!}Bok``MG)iE`0>r^+hM@)Xyt3^<;Yd0*sREm=As*Pi zod2*jI8S&!Le8Xa5uQ8Sh1KbTytWJSa&~g&?0xCX=kiMWj!LLhJA&muNawsDANHbI zK4G-{_V#QY-Yvn4YH;A59HHf@TVS?7IdyYC@-lguR&bM2x1?@4udY&l8?k8kTgc0q z?3|re@Z0`Nex}{!P=Fjc`?~xFR)oBqdBFwswuLmpE&TR#^#L+ERtKw#44y@BIs?|$ z%-3{K5l&kbLV+KJrDIvS4ga$*EGt)FNnmIF|{%&(_&VzHMGJk8~0kw(j3R%c;Ge+2E? zwKr9TJcp3SBTSU`6o4R>jVwKIfV-9BQz>C0t=b{;hDP|Dx(Yrcw9;;Cjw55A%>sT{ z%;-tPSVUJsXmX%m*av2oy3{>Wca zO)cY2y*GKx&1*Kpz0#*UZXi2vB6gBoGuwBkr~mw?PfVT8-A}MSK|OD1JIz0cxgD}l zC|oYPV}#7Yh}4qa-GG7SgO3&dV|Bx26*Wux{_T+glaIdl(B6}auFQ!%S(rHS3U|%) zAv^Coz}mwr)`K4V2usm!rcc3XR;ArpTG2^?L!w+ZXC~%s42E8+KF^N zIrhuXwBTp1HT8nh85(=l+A#r#k~}kh-I#G#@g90Cb%-gbxvumh@&Fy&tumf7ZbBde zqhiddiR@)0pW5X;xaZ!O+Ob|2X!s@muei zy?y4fXV%Pobk*ZK+-0HC34^B)|`goubh=id(m5c8`dwq^s?-%;_(x1d+|H46jsk&sOPny zIT&Y@m1AZDIk9T;5?d+cP@nKF?w3@Mf2sAyX&1dw(0$0D+#&O_8z(QUN_C%bqwtr# zH=e!3IR4dSRi$^YB{sP72lyUCe?5!-e-Ch7;Hwyeq)ZAh&uEPe9;Pg)Bk;&7@mC8l zB9R~$eL9#udeZob6Ivd>WKK?K{HUI>=Z`20YF+N`QK6xAs9GOxc(Tgpn>g|I#`^AK zM|2<7m8+rjx2MT{1#rh+0*?t9nTN-=NV_aVn5;uy%>v(&K8TKe%t*&@(Gc3tyBIF@^NR@rEd5?$VZ-BM_>7)d{I_E2%iQ_jnSx?mLrIwSkZcd4}! z%GrB{fd?%UKVfS$cznhNbQoL9Tx0dmjn~fH)+m1RUXRtO;oQBedq{b2K;93eykWKp zU54#y?&|9QG;W)DZ6kLB@^bg4h9fV><#M~Y-N-B12Qqp@W>q-O<*rzr_G8b-7-5}LzV^TrQ9H+=Dq_;?VViwPV)R6bkpg{vzfy;hKD(Taf>kV z4`8^gaIZbgPX9)R1?b;6xME$iRjJ)cmhB{-8|Y`Z3>f_+WfKcgd`XV*KY~v)T$-_u zUv3ULvdP^G@7l;~QV;U4QhKbAl)S-ZpG0<+UonFJ5%bU==Z7o&O#Y|j{OcjpusPj< z!W|_UwuWM4WD)u>A?B|TVp4A%Il|?M$J@mh?uAqpoB26;?W;HhSYGfaKVU)9!;~Vy zkUSMTIs)e>&78Y(aK~CKl~(BAxlZirMd2N z^wDV{ZdEeq;5q9^U%nr&OYv zIBs{K+H>hmWGcfMXXf{EPa_Ynus(`N!Gc2I1oInTl_<mlPbh{vr;ej;vgiks2yPRbx;iEMCQyDaj?$}M4-CP5;D(g0(`5oU5IY`3_*V@ALE z+1(G<($9Y`Ptdo?so#D(;OaeatbN(?U2h!Zu72w0EVBBV)*o)WZB73w)K4*tJ}qoV z{cxla0wQ{a5i^rNhYYG3;g4wZ>_0z$@%hh7O9s~;yajXpL*xb z<0nrZfAgJPgdU|I(GR7~{NU*miJ~nf%eIjnYx_b{;;?E`2#_$)zgdcb-4b?`z`#?XWy?zcw_ikac%E}wHkEr=giks92^+a%JR2=kOP+Kbc znR;3bJ)Kguq*}FCiq$DyBUTNmKH$vlwGk>0(BqQ_kSIMV*Tw$pSK?AsW^<+{pzEGg zFFe3`%`yE4Oh==ChYPeR)AvtvKHPspzE4`&{kE^Do_mrTWsd1SP3PBV?hB`-`~U8E z|99};CQtn#{I|*F892PJ1N^tirp*2G;HU5Z4*p4U-5`{%(w zNp6tgzz6*U{8Jt9Q_05}esKRZf9M>3a5ATW;RnR`q;Po${FwQVvKZE9^TR|Mc1?cDl>qwa>h=$A9G4xjG|%skzEg z+U8d5pEKM2BP-vOcXjiVjxXEz;QvQfvAquar&|0U$KyfBRgB{ft$X z>pbmtqdZUjX!%cC?$5Eu>=%P&ldcEXSVyKk7(1V6te-S$6JJO2m!pIQB7&#&13OuZ!&jGsXs`=4>& zX~3`e|Jna&|FjkNtMzjl`%A8{e_EP;)&A+$_M7WmevW015!C-OPy0Dx?Z-|Q_5Yjcw{Y*V;{Wl#C>vpT=U3!}H7Sgro7n}C{^`+fjeQDeL+cwwv1fr+s{8aN+ z!reJ8=xgqr;h9svh>r0i+;X-uU_syrq9^Gm*S$Qju{-jTwS|8b4f`-O33QO zk-djZP%$eb)5B(sSNENCy*Xmg%$}Ft9Ovv58mjA#W7YuetN(m=n0$?eYfhR#b* zNOHzLOSbqS&96Cj+h4NHDiLrghkE#)`>CR2xG<5y*%J4n;gC6J_ii|S=cqn~@5;=D zxmc?|eWdR1iE-BJ`v$+1UW|U*+a#zXg)3#RaN?sS>Y#%x>I(F5luAK(P&WM>^ z|F@r}1YdeTg0CzFjT+CZ{&;MwT~N1SA$>RV!8o75p-yM~P(Ij}R5X3qsF(rQ1_Vr8 zIWsAJ?xJh@wtr>(OUM5{t7ng-lre)M;|C7t6B@a$X6d}eL%K{13-2AZ)YO0TYxduC z`TSSv@|o?f%csA#JBspMT@t?EstfFyaQvT2r82K5L%Vlf;jd4-`>}t0H~FvsxirVG z_CCQGAMc#^pNpXPBXgW%4vO(Qa^RQpn@NdiFL-sJi+}u`#$lSSUn`h zsoO?3*AI@9b_i`F-?ZgI*LiGO)a8vP+~}(3&9fP_`44%6cs*^Naf)v9u6lEP*Ye#) z&T*Lev}DH-yVPed_SU)eXlq{*j?!VISZ$?u3CZocEOu|Lr*72cZ@EWV-?}{1{(MNx zis@VK%Us}8sUz?@bHTmta|o5}3bIR^f5b+?Wt(kuAGZE--h`ucu5PJE?-hL1d2hI^ zN7$=})UD?_hy7FNZFK9o&N;pmXNw+EqZjLV&#v^jfL>uMdly>tkQ%-Dj=$I&e0|W{ zbXkvZlnx{H*3BWA$92~)knklj{rnk?`h@RR^ys$&d>x$4sW;tn$5+Vvx+QEg&RCKE z4*j-%BU|+EZ2r;cH|YKkd0)N()K|Uf)t6NIrJ;@&(Z9{uzf-bYV`&?U%rWCdqaWuQ zi~bG9{!1=@yB+u}`tCO7n2$bf4FB(JUU=!xv?0^h z?4{bitD)%}DX0N=e`>iLf7kNnZ(Mno+njDAZn=n&n>I&}DpsxT*LD4HE}E*#$uUW{ zCC;tf7f|%=wpJ?p!Qm6Gi{GSWsM{Qm{d}X|4KlCC$4RcouNb$Vw0gK6_sI3Qy|4dC z-U9zPK6=KDT<~r^Za=9my6Ri)7v6E{NiJd`moJ*%wtvv$Ql2r_$C?k-YBMhV-jqp? zOFvX^n{g@U(>h->P7e2uGl~7ZwcR8C($?dy4^@Sw$6X$O*yergb4I?~o^xfLT_HDh z=C5&3xlu04cNpKucIS?JEtkFcZsFXytL7b^^H|FC$E%ff zCN*RKv|ZEx^h8ni-!|vuFR^-dIy;>FO@7FAz5au~!aLTFa0NQbt?%$_h4#yJitv}#cQTn7H@(A{ zcH;i4cOdF-sE^)5+*N6A!_qXT;Mn^wK~#JvS7SVg&> z-qA0{nYFC5KH4xQ;ywCh);aw>lSuufW-CASUSK+gR%_1~&@*aMUrp>E`DB}@umL$$ zV|&dDnmHkOe7CU4L#M{gj`8m@Y4r7z`=>@suIk?9#r#(J@B7W1-q#qn`zQ4oH!>#D z*=NeSqZPBV(>?xtg+C*3j+**qmHp2i=^|Jsd-WWaUDZFPckiU@M-Lwrlrn2XfB(?Q zLx)X_j0z5%JSur|{}EwHk9QBs>K|#%*}uJYy=3%gJ9YTtH3|KPj~Le4H40$bkZBX9 zZPO-b+aIanx(&J8hH2X$Nuy~)1C73^U$>lj1>LsjadrPqy?^DA&oT1BMjk*LJ8Ioe zo73~e79T0pZSH>V&X}TmYF$3hIYlHNu=ey>gB62wTHr8!9o1|z&P3cNCYN_=-84BR z(U**Jb7SbuQfAg#!qS6F2=c}dqHUTfakYv9x#8=ruS>A z>ne7|^|KwLSMA6dTc6TlM08wH;tO+TQXH|&xyBo&JTX_5$2PlE>ju{1uf9Iq$C`TC z={eJ8j_uSB)twC``t=wv?Nc-x0RbA-zWsZonF0KxmTl+li$MUO%GoB`OqP!cVo1) zl3|l4I%jpi!PzGB=k}hK;BE)_LB1TTu4vbtugpttdn@L0ekGTFcDcypzP-9B-qEUN zFK1vjv^$Ughh_Wx^Z%Q&wW{MN2X$1I zgD2l@so46`xRjAS!upMfA2@JmLR9au30a+!BBPxRn^&(H^Qal>y?(nLc9h{~ub{IqtyzxB7VGQ0RYX&9rYs|5LA@ z_Bf-@d^+X*P|vQn_^;>BKk>--*vy}cU-LVTeWo9}$!x#J2aLd0^tm#F^7Ng)3|NJZsC4 znC{cJq}{T3)~Y`|`^0BV!0lbXVD0kR)8ZYea~$nMd-0LewjDBV>fiU;jJDmohjLd~ z$lyVIu9r3x-g5oJEqUp4_kRC#UM(j#bmqKxqJj^dRqP(@&NVd0`sPyg zmHxjQ7tpxdW6zVIXVrA88CfI!psgsb2cy8wBq*fl}d7s-yc2ohV&Ja zLVW_=^*;2vad!;v-G9Eaw`bmV+Z_`EdiUEpQbqG{oco;4{+c|^oS3hVx9+*;=<5Y( zuJf0USnWS&R#4q`==w}OG3e0eEADj0SNi8joyv@|E>DDnTREw&^RBbsd~W6iKmXeG zXV(SyyrAPjw_ENy*uuV%Zv8;NoQJ@YDQ4`J&z-dKST?5x?iTEx64nhtk7j8OTr{O| z3^h$e572l?q&f6j{u@$bx(xH_GCF$D=pM=HXoq%pP5&^j&(vD_0!cB?hdt{l-nx~zCy#FXD9E%Ef1 z%^%qNtu>ru_1C3l4{GT%JqLNc?_KRQ50YeOmDcAa{w?+pCK=%CG?#2Oho_tW=!fdY*Ob=+QDASB6XkL z`~hRzHQZfc`fTdrmp*tJ?yopfxNOHKHznmbOTCVyOn9SXo1sxRWIz0zt5a)t26gt0 zU%9-+nYq6mGIp@@50||O%{J$u?&}ZCDMjh)52nxl$oh^x%zYi=d3WDzbz`oGKGEH` zSvB;T-fPh(xvQgPj>pLV?zUrf(Q@~kmZj$@nbV?un7J&@C)=96gq}^GOS0+t&P40e zUc|bY=YDB!uPNa$wQafl=El5=OmNw?=jEKP2vY|A`C7 z_KQ;|`wlqp-1W0!oI}G#Pwf!9_t`s>^?bj3{-3)>2MQw){XnN~m);8%zV72P*}1P} zI9hsPy?H!uI&Epq>PV}Z{h#7z4(#B*h;jOiYBRch^t9)gVk+6zB#$u=D9ZSGVh&>k5^o?puh86 zv(Tf(*3WqAj>j_v)(1EB@z;zUP3yx`PAGBHJ-NY4Lazx9j_EgJLC=^igOYmp>2v4A zq|n|0f&GWg%z3dib^Y!Jf1ij$-POI5ZrL)bC@^tojDJM8L1ShPUfj`V`%!20lZx-p z*pn6{&YgR6_rQpRw==h=<*)AEu480}LHc;ojWMmh&f=K^XFRdc<h+JQ9iPCf5 zdYmCgja*-M>EyZYvgQB#x=ZsO=8HppzGcq*4%Z$P!#HN0*{75AeH9*gl9AtTj&F0d zzV8!e?!C4CS*`Dpa~~*n-1>LnCr2&xi+Bb|kM)gxKJbbESIE)lc=^>Pkr~Xt8Dj9O1ok6^D8^5#Kq&U%AhIv zx%5Y!KQQXx`skeIbjKaO!QAhrpXlc~1>T0ykq2G%{miCsp=IBO(;DV!*PhC^ z%g|v~jumw2n@itVYdd$EoUx>LuRk5h`TdgRhi0zXI(Y1&c|F5?-}4Q2b!}?z>Z-oB zzi(Rp^qBt9$@4QOj8A>+Xu`;v}HsX0+f^c6Gev9x-6XtGD;xX&UFk$MA@JiCB zne^0}Cq4H?l74^*zk|My3DcJlzoz+bc8v*}xh0d|J0@)Al;l(NZ!=+fM)cz{Jlm;YREoGGQja(61!i)+Y@8Sth)O z@Xf}4nh75x+{1*;bxiN`9q7+7@vn2wXS#`>Yr@-Ha~xrg+lf!tVYQm{TTT2t6aO*g zqZhaj$S=xQ9@V9T->$B2T!o9!a+O)TK@orT8T*B<6b`JT%$MS2l z%%PTvUqF46xpTKZu`w=IrXOsdp79zl{Yat<_TxnNXhO#k2@92$Pe0f$eX)*gKI)E? zBzGj8lD-V5#_@)wl6T*2^VxgvQJZcb?L}>VB;Olf@W#aVOAKIzXq$p)?nLTM`)oI_*}=AuyyGxk9@he&5y2& z#*Z+{f2hsZjMYyjg$4z5usi$vDzW_>bzS{C*Y)rV4Nx7#Hz?TmnoxYJukFa4s@%I8 zP@mXDwRG&tCpo*0bXU&wgB?vJgc|=sCDiL*{xuvs_|l6%gIwN)(IKEi#}1u3bnXz? zp-YFL4qZD0U)!y_@Y(chd;0fm7ur6oLs&pq$FNReox=jdx`YLVbqx#d)j@TzI@lc? z9eAEz8}cS~7dXrj)+X%QF#oW2-UPwAw7h-L+)mqvduZd#6G_~N#WfD|h?bQ-vRjyc zpXg1i=0%JdGBT)7hp^~P*2?tWiET#qYJY9qK%eW^1@s7Q=RdTcPxkErY_s*Ws~^oa zyWvIQkv!e3{(o*W(`xiKzIt1>W0UFasJEfb4ySnh(HipB-oNQBru@t{8{zoQ-rMFP z&l6vlbd5vWSiHH^#}{AR8>ZH557UHvO%w8^ZM)l}w+RuZ2_g4xqRzUd_&ao4332Gw z663gr*3!98U*A4f+t)rS-T!21n~Sa=4;`W&F6Vzk(lzW};%m22E&12RdD;WTyE-3l z)4tlTq%ggG+nVjGw`h0nMGb4C8*zVouw!tW4%aDrXx9-uWYqSf(kJ(qe&qO0wLNsm zMbASydZ>$zMO^>np6sNyG+xVL32$Q76=G`S4Eud&UR6Id*b#wluJXw>^*GpPqy4z= z8s@5n=d;3ty7n>cg%@XC`=|=vckS&Rmd%}$?eDX(V8h1S6Gn_2PT9R_+DX_UUtxr9 zCtY)Gd*3ual_u@E(cj%+G}Xq@)0js9N4Q&?8hpEd_MExPI^2HkzMVTC^<6W38=x^PI8qHndmU{nv-?aBR4^bIDD;z<-`aRFSy0pS4 ziv0Kvxi6hnox6`qtkZdO6NDy{eSHJ?-l$uT+2<{J)n|ph-eZF=s`s&bfm-|4-Y?Zp z{PF72+AKw1Z9m8}BN6&-ii$h+JrA>a&w#jmKHNK>X9j>>^gzsd?#<4DBlt>k|H!ck zeMcru7&&|K9TTT?2^uqUkiS2-^{ZWbmrt6IzHoHLkg5G69ad1E&18F*Pk`BWTmirG(BKpB?z``5J*EHf&VxO=41A-e4^N-$L1JmK+G*sz%(4^H z7yi9x5C1(nq|iEOx!=ddv$b7#$(CDl)1E#2M_KLMlkK*t-1nPXA$p{%uYI$9TW)-G zPao))=eL|c>Jwcn?8w$f`Z))zU4G}JEei&Y=;`bn+&Q?{^!UL80yDDm0~5xd9$UCQ zHaE1}h{$2%6UL61z9@TWv@@pvtl5J{;+~n)x5wF^F;Btx)&0^OeP*OT<;S-U+$W;? zbw=Jfelv6CJ!kD@&F?oMEG9lWT8)VApK|HB|4x5sR$^F(am%*MT<+I(&&q0q_bo6 zj6ta}vG*@%?`#`BtV_=U!;*u#Oo|&6+&#V*^=9Vitp@JxN&4j(zTOG(a)5bbj1TXc zx^i1~Hg~6*`4rC#yj?nB(E5?PeWG{wTacHqA}-LUyCdVe*wECR`yQ%teY9lKSm)Rt zqmJdSeRQKEsPo|7eS3Eq*17G-)a=1++qCO5V9hIIx<5Iob6m!*QJ*O1+%*qQo2jhV zw{O~?b>qWR$81TQt!~_~V0xc!Z9_(ec1w&I9e9nYUvnM9=KcA4hRS`XG%t^7)#_R* zw`Hq)CNIofmU}kKUFG&|W7fS?xZ@Vr=T?$)!qZc><~`KA=Nv~+&8YY}vv&kI(ysA+ zaPJK_=d@`b&!?|~#&q`SHzcB0L;?@=tx|sa=IKq7dXDN5Q<&Q~^ome{$|fC-H8^`6-5)3Wbf%Nq*VF?rP?r=LT+Y}(Upk1J2_SY}5= zUGJ;SKAwG;eYFdFpnhsg@1@y#_tQF#t88}AZ>x3dabvF0H}=dQlggcx{=t#Y$IlbA zSG+${SubCjYQ5}p_oeR+S)6L=_#f;F-;v&U{bdBZ!si~>nnP;0w;y>)y-a_`_*>6q z=?AuXiP>2FH4-`j`uMo6DlsHvPJ(8`xFqMeq@;1qq%+YWJrnx%59yI`motff&ZKeU z$nQbU7ZQ1%tFt60@m>*&r{FpUOz3FYa=7!g548>86&L}06UQ;6V@HV%3}|X>s%?zx zXr6$oZwzRR78KHSG7!!s=GFO zbL)P~wYYxyd*e3THQn83tr)qgZ?8ckpM3S}54O*k^YVPF)BLNtu1lk>mGvrq`osmB z2M*O8*P`23RyN)DyRBtP{eJbP!>3;TO-l4Zb3SCAz2e@JzW!gRa+g1IYG>VZYP@d7 zd++2yt|9jI|4cn)?olD0^D1-SS{vrW9d|ZAr=JDU_pi0cpGN<4^(NN>e<}Y+rR)2? z-1_FeuNNKqe%@s|U&m%O_R@#+U*_7TUBEZpISzR0kwd=e_W2a6sl=-;AdUEC%?8*{ zn2Jo}vrjQ8kKFLvLr*?&>jle-a7Gj?+InYtP3-un%N1)52Fe+eI&xTdD?M&bM0eNz z^r+~58LEr!0d^1U9TXQ5os*h8e@je!S+Y4E>~Otm%B`<`{oA*e`q-?B)lSNHvuR_V z=NZhisWel!~!tz`WU z-$dHReAj%WYmu%c zP?ObZQm@AE9lT!i0{QhY%NzJ|c@gZq0I5qp}WtxAaMqB3^O!|GHn?AfoAnM;-bS8-mUwpXA8dS**e~I+fSVtwXV@hSxt%~l)J#x-C&;F?}eTBxPs)z?~!mH zb+A#6QqNAT>h`&TB~+ebNsxo2-bjsapad&v)4GM;CvRgp18F7aj5#c;@V!KK;@2d3 zn!n{NE7fY+MJ0>2SA*YrS;rRL%JyE$HcR3BAO)*$@-^5^e8uEV&$3iblJ9Wrz02PE zPo8+zF+JHUhx2~8-^h!6xA7}E%{INCeBV;zS-w)gVVSLBsk4r%k$0i|krzJynPmw} zKh@8Q;3N{%dX|@1blh0p3^16N7tU8zDoka#9^-q1^VMS2i8L|ZMLtsZ@{a1$SP4^% zX-$f8I)@5Xr*2bEsDJbI_$6v7zkigM$Y~t5%IRsI z!*v8wCH8MMYjCU+Qjx>#ZNcXt=&`f2Pd8pj z59{kDk|o8oxrIozg(Jj0&hieS9r$*q%ww$=de`RH@n8Sed-Iy+Z}|=!Jv`wY{_4`{ z^7TTqgOTcTIk4d^oj#7_@UGlWc)Lw*rN;=TmAys!M0~!BHg-}e+Sx{~Qc!A^M%wup zQ?6siyT6cr1-gaEHen@{u-2O?2h5()hxEtTe{>Iige%$OX`78mv{pFUy4;_lGmmoV zbq8|NHLClAFj+3QU{&|0gXJ%jC)3c0{7R9%HIcpS}CNyY975mlthO`!gPy_DAdJf455!z7FSa7Hy-5bGCW(D|@*LFr4*b_R`_h z?{LmWhoi9@#)FRQMLq6Deh=+tDE6kXH+`Zu$Y0cY>ZXPs;boc1HmKt7ANf6jb&Z;0 z@~@HC+3EtY0veN+m4>tfZ1uTG4j zC#xhbgPwg9=@!tNP9bihT84!wTxLyfk+&9D8_J&Q(<1iYgvy*_4+z`D=Uz3SyL zrgtRaEx&inqkYw5sn+QH^$4mp?lGJm$K}u~T)8lkcICQqn|n0-Howt)KkcbyX}+`h z&PzKk?Qr>Bx`5RymgX7FGcF~uR9)KXTH#v3-Zz{P!9RJ)YG;ndVJ2fAVjm=4};H$ixOq!L(mzP~nxPIbuDY_KeQ@mmfFr1puM?8JB z{N-|W8Lub_*R-!H%heWsHSf#0V7>Vs`m0Fw55@rh(51gzSFU>*3oLehi+8$ixE@GN z;jhu+XzKcXa~LtySxY^ z`drHWPjO~x#$CHPgZs#{aIDAbIF6;}pQ=_tQsnu&NL9%R&bV}{MI2Fj5#rh@W3&|I zPpYZ>8m(gaFsWWnv5ZIJK4<&&_(}9Hqv(f*pqW5V9?4qw7y64M8#$WkvpBBZdwS^p z$RfG#ML)ARh+cS@zWakCgC0ec(%MIHbv~VOQd^`GI8TUV9ZOj6HP?F165Z#DZLbLR zkO?ZJ1t;Tby-Z+P$kGz0C2l?ax7BhB$4mEeguZq*OB}KK7=xA-Zk9PXBfP z^4MvW|HF*K^wJX3Do)F~$q)Sf;fiH~IkIW_6;_S5PNBz;FVXuQlBv!AZvMAyX4&HT zTh6Fl`?^y0^HSGwjDYlVgky+4##MQi&6I4Iyvms19Dg&Y)deP%=Scc1zgx#IK!4g* zI^JXdWefA^ef4rVrB`x!o#D}OOD?DV<*!-X`*G!xMyu9~N0%7{KhN*^ti5@7EqTLf zW?b}ucoyCEHCCjw(~xo*ZO?}mv!5r&GN{84jinef-M}Zl2%4)<0D+ zW3Y~vKYs(PYeCUUm>*}v)o2B)<1Op|a)+&8Ep^M?alancI<57z?*FUB?UyQGUBEk} zjNSkA`i+tTT84PydekA!Cww}e|u{G$}N1Fb6+HS z)Y=m7kr89!jNJR%yY^aH+mgyFF>5`Z^Lk^(cKTiEtu#!FX%*(J)3l^tU6#>?pJ(ym zj4%!sa`rxo7=Boo z$$7_mtkyC13PrLCD?QNYVU8R6*ipe)`Zd0gw2L{7Da?^fWaRTHb34P(iRUbDFyrVr z^5}v$ONgB>d7J_4B;9JfDU-iqa~f%IHaFd9iYDK>MywUr}w626b*Nc1r06gyc@!EOlqYFFwulJljB&_e0thpCUK{jG?w-Wq{Q~z0dgjPkfM4 zICEJg&GZt3IDZ?Do%3>Dt>n9!6Y=*$miL*{c!#AM=WlbF70?W%$D7OF;pW^Wi=*yF zeh*i(_^Z!%hOu2YairC`@1i%-sn)W^`}21gEhox&n4w=ZFKd}EiB@;3yNSzS*<=2u zbHpFQu^n&tOXycx<^62M`B+-b@%tEUgL!Lajr1ID1?L1A-hP-f%a)m+U;UNN8%v}0 z!r0;_`7aji(f5~dQ%V58AE6{0XxrP^27UB#RPR&&w`;DTtTy|gXRS+T(*K7wXPj9Y z-d45M=y}(}n?Gi>BF2`^zgu&m{>@iQ!S1d54sVEcEX)UePA%$ps)71hq+YT*d(+Xg zr?!;g3(nTBF4uqXPoIf<&c=r$qo;BI8Aji%EwC%O0@TDkBQa16#Q7A! z39ce>KNVM}#h02k4MG;w$QAS&AWiULrdT+u=tg|^WFW2w`Gp`4xhT@J z7+8k|h=d0M`S;>?uXHE{()C8(I|!AKz|_dgA#$b!Nd)&=7iy*$dCq+xD!0#n;{ZUCh_<%jP)?=7%qqm zcXG!MwiB{NMkYY9$fyI*D3VD1B(ffp1?5mHGA;(NHx9c=5vP>Pz@(UrV*Z2 z4mE)7>Et^d-Rb#oj^@=UG6UI+c*uqdI4UwTNn{pwXQ4X_yR)z}3%j$3pLJMdwgW0>Kaq z*k6kMtV}3^!$3K+8lXvJSs+l>W#q98+sn~kj{foj*a_HNeiTl@d65;^$i{Xy`q|k) zy<}rE8=Kh;BG(s+tSp0SsD(3dL1dLbL_i{>LoO6U1(1Ff=~t0{Rg*|gAS3`~$#II@ zkO~D*3FzI>D6$%z)!15%t<|}Jt<~6Cjjh$_tj5C94PNi{($VJdXby6fOTFHqyhGC@dFax8Vva&w*|s+k$lqS7XW2gn*rppE&wvY z$uv9hx2FR>6kwwu6?Ovp>#?yu1_-Ywydf9Pi)G+HnQP_$ktdWgL5Lq*eOP*n7HD6K)1LGYM>q( zMeai9u6Rg=TtMfpYN&%ok-PmN29hBiuyc1QR6{MCfeRw{pm$FM;PXA`-IEK&PyvUb z4jQ0Iq$ChxfO;vRd?iQW6i_$Y`~aV~B|sYFKoOL~K{yU)fiiCofM`g949J5Ls01gR zfOC3c2!bINQXmToU?&`aqavlLa276#+#3Lt;ob`(_a#FaR6{LL-usZ>9|)A;e$w5a z4TXT-{fD6rDC_-{btif4Y!unWdKdXTkO}0mI|GoH;YZm)K=;84IM3~)P5<0iZ84RJMfBCnN* zydDTgp-JTTSx^b*MULX*(HfCALIB%ultI17oAH3oo2NvM1w%9>0OdGFnq%l4J0VgV z1K6)^5P2&J@}LL~!coB1TjxaH4ghrDM(6ExK-LX*h*sgMZ;K-~M- ze*YAAB%%KSwm(P*;yxhmg9A_l<6z_EZkr=zM|QFH#^2u=B-E zkw1q+8JrL~n-A2<*+!ASWQzRN0eYPa*!^pb$lv^-1j?a7q=7UIEE)8;^2uO48ARHI@Ivq}le1rZs8G!yb7e)RnSEP|V8nN3*{I@AUzTaZ&y96kM zqay!^hn*tlW1s@60loi@hH{bb{U8_!e^0vavG+YXKZHO5koJcIfUO@+iCoA5eEcW+ z|3v?vDUb_=aF$7pL?Hc-wQvS5i2N%8@Z(=KP$zQH0cB7n@)PCx341>^iu@b-zXO4M z|6Ky*Z~$~%lgQ8h5CYXAO~f}5-$dM{G{BaNco(*s1@bxl4uN`6Di4Zyb|e)VcyBCn zy9y5TU=ni2PG}O$MsIbas2h`@N>ncCbJ1Vp2gSnFF<}2D?B5&%JK=(; zybM5gOFSUE75lel0rqag)@^4+<)^?2QEN%J7MtrrpbQ#B-JT5>MHQe^a9GrO?5uAT zwILmjirSa}*eXm0r>IS&-Bb$aMcokr`J(P5&7J7piJhWKs28;vzc;7C0a07$Q4bUV`RvYxYCu+&1;m$~6ZK#Sq(TWah}shjIY9WK03iKC zb)w1>0D1W-QNO{~Ui9{2XK$^jhhqT!htG(ra6mj10pUkT_sC8-07rrJkDM3vs2_v_ z@sHx~qj^vY`1NQF)I+1Fec0QFkNdE>FBP((5Xzt$YJq(AT@+Or2r-ZhnUD{qPz5zm z4~?Q8b3h2hLn>rLA(TNi)WR9KAnI{{h=4>$hg>Lz3OEdP&;U)Mo(O~(NQO+vhf=75 z8mNaxQB@8Ifp|y<^s3OSLaz$FD)g$*dlJ1T(R&iTCsQFC3ZV?Dp%%`-1yTD0AO?~l z6Y`-Hs-Onyp;6Rt9S{QXkP6vQ2o-?dZ_)cLdI!)ufZhT04xo1cy#weSD1&OKg)?wL z)KmTt0f~?fxljxha2V>K0h&ZT9SAXy44IG*rBDUvK8^0v=su0^Gw41O52=t1g-{07 zPzz_^f~abLh=4>$hg>Lz3OEdP&;U)Mo(+T;NQO+vhf=758mNaxQO`Lb1mYnTvY`;l zpc-o73|tWPygx)hBBVnu6hj3ZhB|0~CQ%0iAqJ8m6Y`-Hs-Onyp;6Qe4hVsGNQG=D zgfggxS~vq2L>=;n2uOr<$c194fWuG+4ba3zu|SA{WXObkD1|DhfqG~Zb=UzR5D%%4 z4TVq!)lds(;DV?Z{UHJpAsup|7%Jc})IkF@iFzpzVjvkZAs zRLF)xD1&OKg)?wLl+zy~AQ935T_?KEQmBH%PzUHc(SOAOArJ$}K$=%_p%^Lv{a4U` zr2(2m9SH<ARba78w#Nes-YIpeO>D|iTb@i#6l8e z0DbW9>BoOx2~Icx=YYQTDE-S(`s9z~>fj7q5cLLj--v)jK=%#&c%ul) z;UFA`vw+<hoh=wG{fIKLHNZ7rH1xBe6r6BY)LVXlowq2@TLnOQ-@^XefshB3{SPrfx<8QSIC{qmp&ZcD zyqhHIyeeG(fdFN*pQ|2`!AAwGUsCF&zT2!U9@&PU|&Q7#lg861EbH~|fSje7E|$G`e` zNP$ei9`jPFz8tFIDAdC_XcF~t07O6n5dR5jK4}#7X$+9hsX!p@X9c1@#}DR-)M;#= z&JuM7+h?4j{)CM$Dn$Jm8-FHzHWgU^B?GYaSA6;_@qa__Z`DA)4a7Cz%a;x)67^LA z91!*QBseeXTop9H1yNt4^EG~ajg7C#{~JGuh7`zw5;y?I;hd=d@`GqdfgHg8e;owu zH3kFn#+`6V)VF>>-rr^evTu=n7Y@fo{UZ;YqRtDD<~;G|Pl)>O0HBQjT>`bDz9;^B z!r#}6`XNiyg$SVBKRN)rKOTUyqW%>OX+XMv9fgacE*6XWiL(8K{3r7IH|c-&gBVDM zLa2f|xFD(t8%>F@6Bpt_&!HdQr{9H6Ip>JCZEPfO0q`mLjb3;e_yV zJV=9`K-ea16Sk|MNi0VyR6v7RZDOGSYQ^&5lD$tN6oL~jh~-PXFYiC{B@e#@D2MZ6 zU6Td)!JLoPmNack#kw{INP8{1{vm*lzf-JsydR`p1{?)!wvUDaI4D*Jf55K}^fnM{ z!Pp2+2K?%V-EO4qo*;aH65=5P@&S1dbb6c@D>8+o59u_DMXB1f#q2q*{Sk*5His9?wd@``E_t1o(eiSK(}tms%M1oG*J z|IC$G{heYBNQ69~JTd-|3&+J8$nSxvP%YM=04RVuu?FM&;1XyQD>fTgGe2U*B>?v0 z@Ox-7pd0T8NkD$XuraJktl`wj@Cva;I3N{vLX%htIZz|kNPocos6fEpsB>bC#>VJ! zu@aFbmWjn&h&2|yv8TiuS1MLgqFCc2#F{|-gnF?il71p_$>f=w2M6E;To7wgFko*I z@=29qP4k!a)9`s(8q|q3o%M9=rIrEqQ;AO{{frPu zhFrk@jI(0R6bOeT$bu3$2&crFMcgdnX5~XM92YCiAF{=ooeKCln>=P8hI+Ul)*R$> zs^E-RbFn$MT&xW8%)pO~6VN2qLgWi~LZeuV9Ki3zfe-`OUQC+B4Ps@+LLtdL-jXsnE7nrdEJbH2I!j5j6#H4&%0ixnUKZ)H@}U%}pav*g)_Jj(`2n)!c~CFb z3eqvJVXY_wB zF%3$f3b1!0@?7M(iI4?_Pyr{zS`!V()*xGh4>ytTP1M;#(y9JGX}b`nMy$ zy#kIxqgVyOkOVnU2FMG}iM1a2dhDz(g2RAp12#5L2OCNNy$$5IF&46+9LTFsARaQH z7!JZ2u{Jp%29R$;zR3vNd|s?A2~Y^9#M(;yR%~z02hwak4&+%J0ZD-U;sPiG(ihjkIkD~{ue+il4M=-e z1rUE1@pln_H}Q9eLn34VI(P4cY9Noh$>Sb@5Wt^%(jiBz62jZ6#M+(;SwOn&q}xuq z?WEh@DAtZZAkB_Uz_%Uf?;vgmHcJB_8w#ObEasK0`v~7hy8E%Ui?q9t?IP_i((WSd zuA@Nw1OAW*8BhcjfZYeMyBoW^V}Q8b*x60oZYK~|Mmfr&AsO!CWa%E{+9@sJDnu{RL-y|-4Zhq3u^0aOBhRQN$5knWLiNCU#mFIkUZ z?@{u3G!sbkXc<%kcJ>88BIE!*>~q2eu_}{*yeiSHyeQUV36Kwmf%wPKfBcMCPox8R zK7p(%1Sn?}WvD6zY*p1mlUPqSinTvOtl#>J^-Qo>&z=(NIetHfo#)Vd9@+DhM+|fj_-VmUi zZ^Z-hw~vc;JVdPb@bkT+V%4PpcHc+#ex+C+kmn!s#5zI#C&}w1aUW)h_0b8j>PyA? zI2F!{^~puCJ|%oA90-4g&Sz)D;ySPOIeDBW?ddwP&J+OhKatO$PKotJ0-P7?&(&g` zC7-jT{Yw#$=C9cJTLe^!)j;^GMzQ`*S#klvA)IDx5R%}D%L;Jp+T(k ztj}K%>%S9${Jtm6_k@4I-i2hb{uvE9fQ=vd{bLE>&%gNnuNtu~7K-%~`Tv|D7GqxP zQmR<4e6gCd#FjjnwhXSz!&<{Y?F#?hx2ab!~$qx#}=9-`#SS5BBr`SQ*2s$HnSLDIaJw@yg!l5N% zhxtPW6andbm5SXbTI>k&iLMa4f3nyE&WRm^y@A1E53Uh=2>NlP9a=1Q{6VpY?G$@B zUwu~U(y<^c9)5H~AU?Ab6UPwaI3 znNPk8$!{rkva-Zpeo*Wc#ATCrcB9xUvAyb?*f*fJn*44&A$D#GU@I5h+_Pe@34k0R z&o$UwQv=9v!sbokKw6H`_RYxh4vT$DERgor6Jp;+nB%COkL~>9Vz2cB;@4(C5gY*Y zIDXpe&|8-R)naqZv~N#^0;mFX3IzCFPzM*pUY`tQfIsUS#oj=g4M~7(!#S}x1_I%Y z#c*8gLh7n88xBH~*qhP-dv_qeE<@bI3zAqmt#J)cSa^Wmo5PK)#o#efX^{#R_2>8A0 zyx0!}KrAEy{yeY~oIu*$en1?@CVO`g9Dq7#6uXRcW${26hS#0gyV1)E{a_d0MU>H8IT7hPzg>r0q4YiL?9SqAqBFa0CvIw zI0~oWyx5QWK{zBp8stC`l*2(d4rk$_*c>zMedzA10qSBOb-^*yuJi}$sFHfCqz)>n zx5|34AFG1HVsp&2AFlxHJWifZ2n0hcBtZtC^8`9iR6`Ar{)q-?61xifRoJhJ2kcj6 zLOv7&X{yMhst(ZSm}@^72r-Zh=st<=lci7v=stN)?EUz#A0PJP!~PV=f&$nH2jD22 z0{s20AA~~!q(Kf8K{=p%APHDMMV?QQ=TqeQ6nQ>Ho=@T5(+&uMcp(01EyIte>)?#o z&m0uH8XMJT;iA~j20%0*dzSp33kQ6Ep78S-kOw7D38X!U?m_Z;fqY&dpBKpIg;dA} z{5VAVLj_|0&JXzgy9B`Q?{c6B$^kpS`#-e31$Z3C(k{F^Jv?KFnKlk5j;$S(a&mGa zn6Z_ZVo2ifT3SnrMG@F>n9*ToW@fO%%*@QpOq;)Y>Rn68Irn_`|DNZ@Y4y}VS66rS zTh+BaJr7fQo6^rYapRJdsN5Ur-kYf0n|dkH`J1VXoA;tb^}qS|oVdlMbZJhIel)nGZ>CS_4;?Bn@y-taE-%0hl%cVs8?;1^MQ%Vyk?LeuM(q5Dn zP&$*+m6R4ydYsbhls>2QdrsW#Qd*VLXiA$>nm}m>N}ZJUqO^e0nUt=iw20EMq_h{M1(eRDbS0%llpd$_I;GDk{hkx|x|CL>G@8<; zlqOKxfl?=>y(lf9bS9-MDN%dfH-!@A4^X>5K-V60Dbe)@sXrc~c6^AQedsVsk5l?N zCmyCU9;Wtw_}Fcxt#l@ z;?kRbb8*2mg^!h-n%@z} z^f9|UMLn~7R64!|$6C(Kzl&o%H&PjaW0T(U-5keGZZ+j-9FMS0SdOBcSvezf!5Yt! zSD05VqVJ@{$N5|#Pgiein{ZIz9=3vXzS}`lf z$!(%c#qo$`)>W>=@yJ~J8twGXQxEy3^XXm14tj5~JvWdm;>LTgV~siT`1{I#ajvUdr0|m4Lv>d_kU5s|KgFYsm1!J^*XY8$-WyyJs0G1TbKL#J9@ec z-WZ>#;U!mv`I{(G5*B3m%>~-6KuRq8zd(Pv|Eto^?&+qs9iSG^WjZuKy|xLx1w5Ae zi+g%5_2L+MwukaQ>dA6eUSHPdW2oFRm6>ZF80g((?ATW7nYn{w`g;cZTFSF~`r684 zy32Gq9ae*?j#PE^-*r>!vD7=MNwes0Cp|rn^jd1_UnTqB>YvnP`#+3|0_nBvjS_Jh zUgv)wYc{>}`@jDux&M2a|L@1|e?o%cGIwM;BBhr|QOa~cj@dpM6b0&q+4T3{`)fFs zNXe#TZP-N`-B16jdd+3GXV=QWrM8TV)J=&mvYgp;hI^j5aSyY$$?F4D3yCw`8Lsta zrAghCcq8|e8lY-7--LEX0l9K%`HHSG$Ybhn^$>i>*`(}~dEmLdB_U3!4e54*rc_m6# zdq_$yHBt5nYgj+wx*VO;GfuM2X3;&;vJdsaP)}9cRPy?FB#`z~mMgVP$}!Yh)v+?v zV#6_D_;XS^={;~yNu2+yu5oKfd1U$j=l+y(%4fOnyRw{ViB{D%`ak!!yk~yar?ZI< zOT_k}+EV}RS&5F)!{Yi&?y}A0Sgsty~?J^{BwIBMkF(Lb1a*~n^?`b(2s@@LcWFc$&ZfZY?FV*%g&|Q2+ z%FLR{BY}}wwoi35mFb9EYIqOK%XFbRRrd^(0nR^?aD?Vk0xlt}hlFa2XHCP%-tHnMdk z(hRk2wa(Qu|85nyN2Kj4WFuI%pRA*-vDBWwj)5V4Vd?%8hRZ$~q^G4$4{zcB)T%@N zifrGZKK$Q~S&6ZoS=-57DY6XxxU5r{~7geKWGMxQwZEpDcSO-7CwMGtEgE zwI$s@iOQ0wCwKCYJQ6BRmO7b^W!V$y>;%dsPkEnwqLI$bAX*-eqjL@5H;JB-GRXTU zQkssMPN(xjT>n}tSu*pJHJeD(R4RWw>ReA{H)rL^`b++4R_>(iDfygiIa$+sN>k|X zRN~r9CCs3wBqh(zpnMA5H;ta+ddT*ZwVg!wPNFiVX8Aa}E^EL&!EMz@cTFMQ@{Vy- zujyGWBqu4Iyi?X{I$f`)7Lm_Ou3Khjxn{CWWG~CQ43#41QIa>;L$?3cC{OBulz#&K zlWi;8aazV9p|ca|9GATb9P7Po@9MqW3bKDDWj(tU^)vSfmnY|`!=;dAZIkuHP=9a_$Qnw$kQ}RRHq`r) zr>t|eK2n>dmR0*+F#GLLFM&d8pvmMWk7tM*GR zljEp*U-h~Fh8^5SRo=4fA=#z2%C_Vh%3kKy_@B#VluyX6NekHvyVg%7u*X}S|FNAP z@^RSq4EH}}YgFyzkQJ$7^fI}c~&jGf1a6EXDxCzDDClI=X?EB zM``Vv8*|5N)*f4rYGi04!tSqn>lat!g3lF6F#{H)r( z+yb++Ytm<})>5|PkoHL*dz0+h;eM#}m87T6I>nIyc~0_a%Xm`AGR=ZbBbEwW^5U4Qz43qj&$bue`TsjQJFMCn=MDvy#-<(3v?4cVt#%tSC%6(lO{aLJ&?rtyll_?V3)>rBtD7TI-%YiWdrRXRHM|)-sP`J0FyN$TCP)J$cInZ7%a9p$0($dq_OSj7#2HL4~ z3K5sP`>BCPWlb__11hYwQ0njRY3V2tKZ+l>40e^f2TB7n_By+xlOoLP%M!B(3e$RK z56q(;8nr=IlfH6qUr*~`OF1j1wS$7!9kT`p%2^#Ghs6(!rWkcg=U}U>$-It%_MX83 zs!Uf07)cIUIGlp9J%z!35>$#ay3ke5q|Tz-{q3U*Lp(-Ho@0CZ3jJk@lGEKCR8@%o zH`Y={Dwf)e7^3MiM)TTxy8gYc1!}0-gMHl{{q58u^k8dGp}%Kzp?`4JuH}{id4}7# zlT=a))Y8-4+94aPe-qoDPNI}%^~^125^#(^tH5F<=Z3Xjc9!}w(Ob*?9c}cx0r73?oZs6{M}3)w zmRhKge))uKp-jjA&WSayl^d+oIjn%c6@nU8>oQa#Rk6Esexc(ps!pxYSMDx#agWJ^ z{sJ|o?3?NkDU;rnS%7&xeXae4QHx<>l;ka|EH4yB$)P(cYc}eg2^cf8$~2l}se{xH zvhU{hbY$uwpDXV^K%=Hm>g}Z=R+`mGL!bxpQ^|jA`hoV+K%u?VPwijsUfcs&k;HCD z!&?i3-L0tbP*n?AWyEbD*phdr4l{;t4N{vqn>Eub%3)3d2)3>RgniQI+6{bv`ymfO^(o`5# zKaJ>7qYK+KPai*d#`FT+F|~fu^qGapX`z17%)*w2ZPVM6o7=IK=E^vT(yD5^Q3=hDK&WNPDhD!IO)c|!B_ znWGD7^Ylrw%#;ePFHEVQI=#7Z#)SH*g()+pPMJI{p)#7N*h$Tk(y7EHnV66eR8ZsO zDKn=wj~hRIG(9w(PL3{2pIYCPOst=}DBEbpq^A1m&66h;8WIwvzF~qqNp+)EXq-^rJaKfPseWSp zI4Mq*iM$Qs3^j**U|cdOnOZ+#bYa?*q_J5ZP&+nHO&Y1TbSJevwFI4|k{TyZnwD%e zgHF(WRTk7C!5qvom=sEbWG4GM_JAoS4w+Pcmq2p)d;R;${k>$VI_8!;=Z_&~ebS!E`VunJ?~+{* zJ;TP9flaFJ!a$)-wiMYrLX5t)F$HqU<{AcOTQ+-a8hUOzRJFv{EAb@6Ua*O&Ie`4gGb$q~ko@C1?$W zMk^}}T2*1uF9A-@r9Ih4(r(jB=9Z#;tCz_wOFKv}pIaffBJHKRGVLwBD(z6bI_}9`NhqM!GoU5fhoHwDpoj0X@ zmN%o_@HfxqlZ{!FBF$nM&9vw9mec|hX|5@w99z*GRYn?SP%J|3X+M)>**>=eeXVCF z+WK)9^0u$cU64D7cA~w5_C@}fzFc!OZEJTHeZAtsyplVDwwjXP5BZjMn?8!Z^>kS7 zKH5C$8~W{=jX1Xowy&Oy|ZVLuYN4eZXP4g|6%(2%~QF@<<8F8H~gN< zJx$-|x`sURuW7gD7jw_k_mJ9Y7i9VEiCw7==g>@~lX~)8^4oW#K9s-P%Shi`>gi8u zPPzxpANHjEp7+Y#nmdp7+1@9&UvB^0=eaL)x991b-gzyr=Z(CX`y*G$TX{S06;a_7kz%^{3^MhbHC6|`K#qur@eCv`8D&S z@@wVS&aabSH@_b37`;J$!~90MU+F7Iqw^cn_i4t`cO{B>`WA6MpbxA@wAXHJzAnEB z?E?NDeRE<{`p(2=v=8s*w8wLU+}oPIVUyCAB*y2PbJyms%Wsk2lD>O0F+YjENi&7^ z#-5s=misODd+z<*2l?srC7P}2OEuf(XVT98+tYW1cFev2whMiUW>&t1zL-&_oqXH! z?fDMc(|6bWoP1}#EB9gUBico~C*PajE#F693meD}=I7?;(a!Yq^Lym?%1&H1M&yb_bLyjeXtLuFPI&kKZ3p}wt&7Yc69z2`Zn}&`QzyuVJGHK%AcG+ zg}yd+TK@F>8T3W6v+`%>&&i*gKQDiN{sQ{q*+uz_^Oxi=&0j{}b-aSU$#GTw>ijkN zYiXbJ>uC?@8}m2OSJH0D-CXIJ`MdM?oq}L$o{p zBl$=3kJ0zep2$B*yJ$b1ek_Sx#AAS%LQD zUrAY6Sw&e@Sxs48Swkr(Ybv9ZwUo7$b(D3L^=K#W4U`R)jg-;K#>yCFtWu*C6;JV% zKnaydiIrNVPT55Hhq9^iPh~UZU&`i6z0#mGDoskFq{=vDywa>}p=_y4P$nvql*!5z zWh-T>GEJGT%uu#gwo$fKW-8k$+bcULJ1RRVJ1e^=C1sYYyWwz3$v@0FTuF4#x zQ|VH=l^&&6*-hzF`jr7?P?@XDQ+8M8D|;w=($@v{R`yZ$RrXW%R}N4PR1Q)ORt`}P zRSr`QSB_AQR2C>lDMu^ED90+tDaYqt&b_0Ypq!|jq@1jrqMWLnrkt*vp`59lrJPM) z2zZ^okNI})mE2p(Im)@pdCK|91CCa7BWyP1hjOQKmvXmqk8-bapK`zQfbyX7kn*tdi1MiNnDV&t zgz}{Fl=8IljPk7VobtT#g7TvBlJc_hit?)Rn)15xhVrKJmh!gpj`FVZp7Or(f%2j9 zk@B(fiSnuPnew^vh4Q8HmGZUnjq ziV#8-n$U$IOkoLIIKmYp#7MD(pbry^rNuI0+1xo|IkCK0L98fN5-W>U#HwO7vAS48 z6vUchlvqowE!Gk1iuJ_$Vgs>Z?hLV!7%esyW5ifdBZ|Tkz6eApA`y#PQ71ML{}7vs ze~QiMOXr)5deI;nMUzNGD#nTNqFHPqwiFY@L@`NB7E{DlVyc)Xri&S3Yq5>kR?HOJ ziS5M>Vn?x)*jel%N@A915v`&uW{Wn_E;_`nVvgt(U7}m`h+eUq=%X*x4~RiASIiT; zi}_*?v8UKe>@D^Y`-=U<{^9^}pg2ezEDjNeio?X=;s|l1SRjrPM~h>`vEn#!yf{Ie zC{7Y5i&Mm@;xuu(I76H%&Jt&fbHusgJaN9bKwKy;5*Le0#HHdgak;ocTq&*+SBq=J zwc~;wSO5_(l9GeiOfoKSV|RspizYs;EL$ zRZZ1ZLp4=PwN*!T)e-7QbqRGzbt!debs2S8bvbo;bp>@rbtQFWbrp40bv1Q$bq%$k zuBnbv*HYJ3*HPD1*HhP5H&8cJH&REd8>?f~v1*N4R6W&K12t45HCAiYI&~BEAL^#+ zKh@3Df2o_R^=gCKs5YsInyTZ}@oKZWg}S9WL7k{hQYWiZ)UDL1>NIt_Iz!!B-A3J3 zovCi8Zm;g3?x^mh?yT;jmeg5li`uG|)!AyB+OBq}yQ*{4PPI$zR(sT5bvLz7?NnG&D1Q-)*Q{%Mrb3oCA1~ArL?8BWwd3r z<+SCs6|@z#m9&+$RkT&L)wI>MHMD}ZrZ!4jOIur8M_X50Pg`HxK-*B;NE@wftc}se zYBgF>^E6)zv`~w*SgY0Qv`w^sXq#&P)Hc)prERX&YYkeX)}$p`s*TgeYt7mg+Lqb` zZK5_wo2*UIw$i3*)3oW@3~g&|8*N){rna57y|#n4qqdW_v$l&?(q?HbTB}ypW@~L) zyVjxYs?E_lwJxn&>(P3(-LyWfUmMT{wYl0nZFg2wx71Yc7S%E zc93?kc8GSUc9?d!c7%4Mwm>^dJ6bzNJ61bRJ6=0MJ5f7HJ6StLJ5@VPJ6$_NJ5xJL zJ6k(PJ6AhTJ72p%yHLAGyI8wKyHvYOyIi|MyHdMKyIQ+OyH>kSyI#9NyHUGIyIH$M zyH&eQyIotTEz<7L?$qwm?$++n?$z$o?$;jB9@HMv9@ZYw9@QSx9@n1Gp46Vwp4Ohx zp4Fbyp4VQ`UesRFUe;dGUe#XHUf15x-qhaG-qzmH-qqgI-q$|RKGZ(aKGr_bKGiYr@oo~ zFMV^pUT@GF^(H;hQ+=F1UT@a7(6`hl=o9rx`ec2IzLh>zpQcaOXXsn&+vwZsGxhEC z?e!h>9rc~`o%LPxl0Hjs(OdPhK3i|o+w~58SACA&sdwq!dXL_#@22AUOm^*!`G^}Y1H^?mex_5Jky^#k++^@H?-^+WVS^~3bT^&|8n^#%G-`qBC^`my?P z`tkY+`ic5U`pNn!`lJ z{-FMl{;>Xt{;2+#{{=WW!{-OSn{;~dv{;B?%{<;2z{-yqv{h zV{@b4XfPU$CL=LYS_^-dG0qroG#gtOTN)FLiN+*jvN6Tj%9v_QGo~9ejIE7rjBSmX z#&*W`#tz1g#!kl0#x6$5m}RsWtw!0HZL}HfMu)MhF~{gMx{Pk4$LKY7Gy05vW55_R z<{I;i-HrLi9>$)=UdGgN;LsLyg0X!;K@1BaH>dQO426 zF~+gRamMk+3C4-WNyf>>DaNVBX~yZs8OE8p1;$y%*~U4>xyE_M`Njptg~mn3#l|JZ zrN(8(<;E4pmBv-Z)y6f(wZ?VE^~MdxjmAyJ&BiUpt;TJ}?Z!f5k#UD{r*W5Yw{eeg zuW_GozwvVnM<3? zn9G{Wnai6im@AqqnJb&Cn5&wrnX8*?m<4mq+^Oa$b1if2+@bWYK}9C*%HEVTi4Xa?SX^pbhvevfNvDUTLv(~pZur{Dh1Z|z|1XzgU}Z0%x|tXWoz)oPWk*;bp? zZgp6@T63&UtIO)PdaPb+H>=O;w+5_1YpylV+TEIO?P2X{?Pcw4?PKk0?Pu+89bg@3 z9b_GB9bz479cCSF9bp}5EwGNVj<$}mjy1WJFUB{yRCbyd#(Gd`>hA82d#&!hpk7fN3F-K$E_!$qK zXRYU~=dBm47p<49m#tT^1FC z_FDGZ_B!^u_ImdE_6GKb_D1$-dt-ZyJ=U(Vi?(O`c3_8gWXE=`U1x7%|HIzY{-?c} z{V#iSyWVcF8|@}Lu~U1TJ>G7%x3IUgC)gA1N%mxWioKOR)t+Wgw`bT}+uPXN+B5C# z?CtFx>>cf$?49jh?2S@zlXIrh2sdG`7C1@?vZMfSz^CHAHEW%lLv z750_(Rrb~PHTJdkb@ui44fc)pP4><9E%vSUZT9WETko~azi2bPjnEkl@g#D!bl>M~*jQyvz)WM zvx2jtvy!v2vx>8-vzoKIvxZY})^tWWYdLE>>p1H=>pAN?8#o&}8#$w$jh!*hSf|D* zI-cV@ffG8B6Fap|owJGa4`);7pU!5^znsmTdZ)o@bef#RNu6=dc&FLf!r9W9;7oKT zIg_0!&Q{J;XPPtJnc-~hY~yU}%yhPMws&@Lc64@fc6N4gO3o~&#c6fQ&TOa6X?HrD zU7a~jr_<$hJ3UUXvzycB^g9F2pflH*=j`sxclL1hboO%gcJ^`hb@p@icMfn4bPjS3 zb`Eh4bq;e5caCt5bQU;AIY&FkILA82ImbIEI43$MIVU@(IHx+NIj1{kIA=O%IcGcP zIOjU&Ip;eUI2Sq>(c6aiI2SvYIF~w?IhQ+EI9EDXIafQ^IM+JYIoCTkI5#>sIX64E zIJY{tIk!6tokh+a&YjL(&fU&E&b`ik&i&2<&V$ZF&cn_l&ZEv_&g0G#&Xdkl&eP5_ z&a=*Q&hyR-&Wp}V&dbg#&a2LA&g;$_&YR9#&fCsA&b!Wg&il>>&WFxN&d1It&Zo|2 z&gae-&X>+t&ezU2&bQ8Y&iBp_&X3Md&d<&-&acjI&hO42PR04t&AEB{bg6JvS95jO za81{8ZP#&KcZ56AUBX?`UCLeBUB+G3UCv$JUBO+^UCCY9UBzA1UCmwHUBfN7Yr3P{ zwcNGcb=-B`_1yK{4cragjoi`h#_kw*tXtz2UC;I1zzyBVjon(e&fUcQhr6l!Pj@r- zU+(5^z1!e6x=n84rtUa*yxZ(<;cn?pa3{Kx+{x|~cPn?QJI$T$&TzMOw{f?1XS&_l?+*94t+|%7N+%w&?+_T+t+;iRY-1FTF+zZ`{+>6~y+)Lfd+{@i7 z+$-Iy+^gMd+-u$I-0R&N+#B7S+?(B7+*{q-+}quS?jrXN_fGdN_ipzd_g?ot_kQ;Q z_d)j|_hI)D_fhvT_i^_L_eu9D_i6VT_gVKj_j&gP_eJ+5_ht7L_f_{b_jUIT_f7XL z_igtb_g(ir_kH&R_e1w1_ha`H_fz*X_jC6P_e=LHtAF-DJFP${cN_IxrIx;)ZllDx zUO%g^Jh!ZuvdpOOX`>&u=NKisGo%2^ZfDGeA27}C-n$yiUAVL8j}WbxB>dGVoM3#DUMXN#e7on42H-7SYz#GUgOqK(!vb$8OziH;V1LaBuo3hA9$ z=1v%XU*|AFpTG^&nPut(l3wkkKl&tozMG$)H0%+#dl;cl;^(`$fxAn+J+w%vhZII6 z-EE@W-DXUN@buV)=9gtl*gS&K)yL1Mm8iZ6c zSgOG+(`NM1&(YeT{5xXCaG6F74yTM6==wpJ$ToHcRhI5gLgf6*MoOGc-Mn>eWK0Ccn%KnY=FEC;N1Y;4dC4X-VNa00NxGY z-2mPV;N1Y;4dC4X-VKnu0qxz0_HG3KM(}S0|3*C5i02ydToaya!gEb{t_jaIq25iX zcN6N}gnBoj-c6`?6YAZBdN-loP2k@I{!QSYfPVu13HT?zK8{CcTb6N;Cg7HUTLNwg zxFz70fLj7?3Am-;mO`o&Ql*e8Mfqu+QJ-WZ%_x-_T_*Q;mS{1Hgj%O(=s2qvZ90IQ zrSNK43a^G+(W_y8UJdi}YM7r_!>#DmFki2RhUM~# z;9ms)BKQ}qXIrE;G+UQD&V660V)un0s$BYU>tyPfN}zq6XLlL&xNRXi04B*AL98C4Hu%} zLex7%y+hPHM7=}s3#c`PkH9|y{|Nje@Q=Vh0{;m7Bk+&FKLY;< z{3Gy>!9NE782n@KkHJ3%{}}vZ@Q=Yi2LBlRWAKl`KL-C8{A2Kkf%Iy@zZU#!!M_&# zYr(%3{AvwK2ZQOsV0ti=9t@=iL+Qa#dN7n8 z45bG{={2Gs8_|!A=rc0@aES(B~0ANCaMwhwdU!yNfAM?TDv4|C+h9QiOuKFpC1bL7Ju`7lR5%#mMY zS^XmSiC^SC@nM8~7$F}<$cGW~VT61bAsg z55wfcF!?Y{J`9r&!{oyd`7jhdfZhkN`T$lR!0E?{Hb9#f^^a)nptl$L=?xS~+4Y^h zw8&l_S|wV>Tkb4(l-#7Zzk?ZG6*G z9d!F&cxf3gwV^yv(#Dl&Le5%DNCynl?OK}@N^3254wMX(rS3r&guFS(kIxvk{NVyo3! z;&0V-Q6~2mE@p(CJ)9kKHJWPlteQo028+tZ!w2~JO@T_hi+c84^&0dUGX)Zc5-K74#1KE4kh-%n8=`1(Hi`f|qX zrvSN>4Y;4OA@EZ+;C{*m%um^X1@QTU8s;Cs=MUiX2k`j=Ky3i14FI(PeEtAFe*m99 z0LTUa*#ICL0AvGzYyglA0I~rAb|d10uf*W5nuulU;+_f0uf*W z5nuulU;+`qE(DlB1eibsm_P)WKm?dT1R?li0uf-s5MaU(z=03ozz1+}130(=9NYj7 zZU6^2fP)*r!42Tx25@i#IJf~E+yD-40Eabz!y3S04dAc_a7Y6;p{Qfad}5JOG{t!1Dlj z9sth+;CTQ%4}p&%@G%6wg}}EE_!a`+Lf}XU90`FVA#fxFj)cIG5I7P7M?&C82pkE4 zBO!1k1dfEjkq|f%0!KpNNC+GWfg>SsBm|Cxz>yF*5&}m;;7AA@34tRaa3lndgusyy zI1&O!Lf}XU90`FVA#fxFj)cIG5V#QnH$vb>2;2yP8zFEb1a5@zLqp(42>b{Ua0n4_ z2oZ1y5pW0*a0n4_2oZ1y5pW0*a0n4_2oZ1y5pW0*a0n4_2!U52@G68~9KtUS5pW0* za0n4_2oZ1y;Wvi}ID`l|ga|l<2snfYID`l|ga|l<2snfYID`l|ga|l<2snfYID`l^ zga|Z5@Fybp6A}D~2!2Ea{~?0?kD&Jv>~{pa9l>r#u-g&rb_BZ}!EQ&e+Y#(`1iKx< zZbz`&5$tvZyB)!9N3h!w>~@6l7Gbr$L>Lzl#zlm25n)_J(DMj-96^sG z=y3$Sji9#?^frQ?M$pp;`WZn#BiQ)}b~}PSju0SOL46a{GeO`k!8l3~piAJ7B=AQP_#+AYkpzB70zV{y zACe%@mLSlUAkdZ|(3T*;mcU<0;IAa`QxXK!68I|#{FMZLN&-J6LHi}}Qxfg1}jVz*&O8S%Sb>0)Hk!;4Fckk{}?KG_qfsz;8*=ZwUv;iZ$%FP@c_$ zD9`+0%CmU@<(VHuc^25BJoAGo&-^0FGe4N}%nznK<41YsCsCfw!zj<@VU%ZnDCLvv`zlCV2AwTOc(U70#p+vL%O+3FWHu1cXa;|R^&-02+JinuyUxJ@+pGHw$MzKq*MgD>MY(csItO*Hs2ZW9f88Mle%{%c~~E;cc4 zQ_lU@#JEi~_g@p^HqqRFO+1exn)|Pb{UM^c|C-nzDmF2mQx16;&xwXS>|Yd{*uS70 z^=3by*u*$PIrM;WhG?`S<4m!M1NxMs9T{(k24BWwqQRE~`b480IiOE8+L7^yXw--2 zPeh{~8JCDgJ2Ea6n;4fUM>{eu5sh|aTp}9n$hbr_`0_l9Xz*oRA{uHOn9C_ zIrwuNhG>+}aTcOkKN9xGh~|DxFkTak*97A=;W$e%VSkNsl+XSe(U6b*HKHLO`)fpl zKl^J$gFpLgM1w!@AOQ{}z<~rfkN^h~;6MT#NPq(ga3BE=B*1|LIFJAb65v3>^Pyq_ zJV<~C3Gg5R9wfkn1bC1D4-()(0z6272MO>X0Ujj4g9Lbx01p!2L4xs}V0VFh^pE{F zqM?60uOS-x$Mc$E!t)x+p&vZ2AsYI@^BSU|AHbaixRbCyNY|kcJdYt7^2DjWP4-KZ zK993)vR|9@d0A#{Qw=X$^QuQOu3AjkPo$i22L2b(keB^1q9HH;a7r}f|YU$`{5rY@Q)JsM+y9+1pZM1|0sb!l)xWK;14D6 zhZ6Wh3H+f1{!aq`CxQQy!2e0$?pmhqgPJz}b&^iTLr$FlzXq^JBQ=oMUv`&H6DbP9vTBktk6lk3Sty6eY zDbJdVDbPCwdZ$3|6zH7-y;Gof3bamv)+x|B1zM*->lA360lEHv3U4iix0b?NOM&Jo&^!g2 zr$F-*D4qhnQ=oPVv`&H6DbP9vTBktk6y943?=9uocroSKIORP0Q=oYYG*5x%DbPFx znx{bX6lk6T%~POx3N%lF<|)uT1)8To^Au>F0?kvPdCIf3Pl4ts&^!g2r$F-* zXr2PiQ=oYYG*5x%DbPIS*?BPqs;BUpQ+UlOyyg^Wp91Yuc+Dxi<`iCY3a>eZ*POy@ zPT@7D@S0P2%_+R*6kc-*>yg51PT@7D@S0P2%_*!&3a>eZ*POy@PGMzIc*`lQObRQL z!fQ_9HK*{JQ&^o8UULesIptq3iYfnkK{@)Jf4v|Y{SIrD!dj&q9iZ#zZ;lQS&DJZ0 z^-5vAQeHko*V%ffh!&)X7Nm$4q=*)zhz_KP4y3StDXd=#>zBg%rLcM_q5>(R0x7Iu z3M-hx3Z}4vDXd@$E0`iGkRmFO!YZb)iYcsO3agkRDv%;7kitr)u#zdF04bsXDePj3 z*?)@Je+v7UR_!BZ|0!nwDQ5pE{|a49`B!LKaGEWjqCE3LD9`$j@@%$8dDefFXR|%Z zGp~d4%nPGD!zs$Mexy8`6?iplA1N=|vpd=bX&Xyg^(sv}okCH?XhgP~A}toB%d^4a2LgX7FeYC$D?#;TJ*1@7WY@TR6Y*Fv(=$5Z5^wWx^ZrsgAiLQbJ8zrJ+tGs&) zt%D#gTrQg(x{^7iw5}FU@Faj}h{tAyXo$z=gx24pUJSFe{ua&0uu3$_V^}2`OHlyqpt)4Eb1e@m%hL@P(2OF7(l6{dbO2aV^EX9z8*Y?Hf89fJJ5#= zowP<8vN3cL4cQnvi3VeaOrlwqB8E&6LxduV89$2bA!j~C=zWm`Y+jKAY?PxMb_t2b z^X%ezMRx5d=e{a>4OY2-fL;uu-GP}yP;1KeYVYW4wFc(VHi&f4&zIPL@rvxfP|h7v z??6R76>R*{&j9S!!{ zS)T2)%NJXF=5_PYEUFwI4feKXuUB|Q=t>c~QiQG)p({n`N)ftJgsv3X6w~u)XEw!N zkxen>+@D1@#YA&|7TFXN&HY(qQ%rR1LV(upS^Z^}59(B8drUX6!WP*c6OGP-QWc?8 zMJQDfN>zkX6`@qchF~PUkI>gayS?_62WV?!X2<5)E3$c}oVB`G)ipNHbRN}U^Gr0V z!RDE0=p378ugK<^a>k1yn`fdKFN%$53pUeq9%{m7nrNsAn`xrKpUpJU;Lm27=#<-% z09R@TYXlL4y(6+Vro&7>7T+aRWHBMNgxiCI{T@X*L8D%5&gner#pax7)QcyxM5A78 z)`>>DuvzygYR2WVStlAg!e*Ulv?IW}Rs8XR}T;__J9j8vJ?k>(RWB z`LmfP8vNPJ6Ak`s?uiC}Hupq>Kbw1^!Jo}N(clkrPj=rT8!Rnsi7g?SW2d}3Ez+dd zD?1jS3(Rs?@4$RQSCi)C6o=^^Flfc5+=krd#hdalt2*JR*+1AqutD!%O8btNOekmG z9#4rq!Wy?keEK^2=MZ*r2YWm(ri&~HX)YI1Y;nvYgv~bwd=XTHz?c_YrKC3<58dZkgJ2Js{9fpk8cmI zf(KW@ zh6fkJgKOdOjFp~53-FAUXfz}L-as^~kjFDv&*K>^T7J%dB!SV9o zczHaJ^*lIQc%6f2&z3K5c9wfP2m86Gx@aVy>Kg1E=;-a7kJI1)vxyfus08#U%qCvs zpz~}t@gj%k!EAakn;y(2UgV(b!3Ywlw=CZkmfOx7v=n}59K&#UFa#a|*#jVZ0Avq< zjMo`xK%(aX$at;6!)pzcV;ljHJpi%?K=uI09sn7yHPCZhu8;YRUsKfR3kR_3K4v#Q zW;b|^!NY3|lyh79nAP~0)!@Yiy3TGgUR)rW+mc>f7(w$F;1Ov_)-!m0!Ncndl(S5D zeSv5OdAzPbG-D24Pav8{3tmqkI<+Ox5i)lU^e#S}1#TP>^za@6nn)%zhc5D)JOcs`KN2lC;40XolP)d$Y`m`eG;J0Cdb1Lu6;oDW>{ zfoDGO%m<$Nz%RUyKmd-`0)F|xFCX~j1Gjuk*?f-75#Xa2I1)!RdI4DF1FL+FxY2dU z5A5=RT|ThO2X^_uD!d;-1_k8;t9)RU53KTmRd|1b?niF}i+oJ=d`$IxO!a(B<$NHD z4@B{SC_biQKE}U~@$bWJ_A&l_xXnJszmM_nWBmJYn|-*=KHO#>ZnMu3EYIf%7Uk#< zc+5ULW*;8250BZ0$Lzyp^f|Ia2GlpFQFvYcmkpn=rYKKjXK;dhF2v{!G4To!n+Oq` z2r-I7jN%ZZIIL-)0x3c<#DSYU#4rwPQh5VmN3{wZFB0emT1*(w_;9995ofT#?Xwvs0UO#swjX)B$FA^>Wzw3W`Y`+=pcL^HHuX)Dn@ zlg83kqIqazX)DnT=d`qyDo8H~(0_E`W!*^!v?Q3%Q0MT0pY?;hr+S87rRGcIr}06S z%W`N%JD>5h?w3z3KFC^Ap2_-!4hXJrbM+FvFu`Yv)pD{ESq-aI4Hn;AEty{P;HQFW zeS&JqnOO31YG=MDTwKmD4F>LEJuJDCP!Hf9*29u}i7^5k#Cljdk0Ama#CljdkIn%O zVm&OKXS;*-utY;S;In1xVS8tF_O#4lQ~*w5JuJDmzCrW&Vb{SQAu(DHs|~*j-2{q; zgrc3ZhhGPG1jIt}*ZKzddglPW&)-_svcE>_9M0vuBScs%1Qv$~b%Y3Yga~zn@YzCy zIznJ}2+R(F*HtV=EW5L72cO?!6N$CJ`k8ylb<0<=Sbb_mc80ooxzI|OKl^>zCA zVl54*EDL4ORup;pmqq<4iV=F5$6ag&Ou+ADzy#v^8JW&gb1F62%d!qaD)hO zga~ki6yV67?*l&yaAY)sL?HqkAp#sB0vsU%93cW6Ap#sB1vs+jJ7;r!5a0;mr-le{ zga~kijdeOZ)wmsq0CzTQOtOaIUq5L|1VG|nABcv|^REv?v+olkd=Vmi5jMqENB7)W z^tmFMMbOc3mhhNEc+4R@<`5oph!92yk2!?L93q4fB7_mbV-Ddlhe>GDR>j0+zhf zdA17?F9IN%wID(yBZ7Yr@ge{(!jBvg+=B@2K?Das;za;-A45+B?;t|tH$w0ug2Nvn z0*od0^c?tO0uaGBz|wm!f^UE&_(ZcBVhKLctcF;EPc+*_EWsz5p%+W=iH7``B47zV zooDdF5`3Z=`muzbX8m;Cf@zQZRG&?|baiq7ffn1V z!w5F(SZVKJr9I`SK4uhHX;0@FyRp)qXto?!X-_n&53`Py_8wN+Q_hYJR@xH{{+MxK zr9GVof6PE4L{K8kK(G>@?gM|!Kq5p?BFsdhFxC2d$zrhb@(KY8nRqIFj&BxD23mWW zJ`-lNc9iJ1kXD?9-eQVEOZA$W!;Y&zbYay#m5w&RtR;f=j$pkbL|h_R z?+6A3tNbaD0~Ln#jxdXfV7>7c0Nn=_g7uCNafx8P@m2uc2Nl9BCxZ2kFw4PP0u(rc z3gZVYye&ZI(G-{kMVJLeu-_48K@s99c&mT{P#7Zk;VOcKj$ol9Sm+2A8gC)cbI>tZ z=m-`%f`yJSdx|i7ieMKb#Q$SJR1AoU0Z}m^D#qL;1~kQhrWkXV7*G@gief-f3@C~L zMKPc#1{B4Bq8LyV1BzlmQ4A=G0Yx#OC?D2nmJ zZ44-iF-wU7MKNY6F=i(*ASea|#faR-fS?$YlNb;bV{#H>auQ>562nr*_(?d%+$2Vv zH^$r~M${w5+$6@_Bu3OD=5`_c+N3A=NQqB7~?g@c#YvW$8eluILsM~9K&CZ;V;MVmt*`O z7~==Q7(WQc_(3p+zZ}C~j^P)_@PlLc!7;qZ81d8?u3-$@zR|9aZ0l3xxTx$TXHNfR+fXmeYoNEBiH2}vNfMX57u?FB+18}SXIMx6h zYXFWl0LL1k$Bod#M(AN9^so_n*a$sqgq>@IoomGGv=R2L5q7N+cC8V!(ni=dtk$P+ zHrqL@wx_T*`xaPjPc+-rgmJANxKDXzZz#{~DdpLCqC9g6DbMhT@+?$AdB&$6c7XEC zr=dKvca&#*DbMUFD6%Cq*Q zJgW!gnY@%|^`JbHm-4J0lxOnNa=8rODbL!I@~k~62Y=QpqQRf>k!bK|d?XtDd7Kap z{)~@AgFovf(csT|Nz3)XpYf4s@MnA^8vI#ri3Wf6&xi(p)?cE*pY@n%@Mk?H8vNNm zqh*5N&;3X=p67lf8qae-5{>7%KWTX(o@f7yXw;waoM_aaahhm6&$vp<62Xsgm1yu| zoT6okkdLQ~v^){ldCEvMmzSVD@sfmL_>bIw?spJwzot>e&_|>uAuYa&-RvRv_JdfwCs}g5O2E@&3cHp zU5SSLYDfn~5ifHiXh!xS`&k-x4!Jil05Doquts)xy zIa)iV}5naua5cEF~2(ISI7M7 zm|q?9t7Cq3%&(65)iJ+1=2yr3>X=_0^Q&im^~|rH`PFCq;xywBrx}Mh%{atq#vx8K z4sn`sh|`Qi%v}|y8HbowP_=eW;H|!`rj8Qtai`VG4Sluga_@F+oZLszZd|;Zz1AqV zsvj|%b|se!ld?^JUHW~1RxuaHw3PbGOw>ffiFi2CFq}x4pjDpTyA8^fpgr9vAjqzm z*{W*Vf1Hpb$-xP^Z@NMI$B&^k5i(dN>xVo;pc+J?D9;e8 z1`#L9GbErqL!KH$h@=$!JX?gCh!MXgVq~TqW{dMRA z)*^3bLT3vNK9{CcpX2il|h?AA5`6E8@3`_|+4?EEGTQ zEq?lOf%a2H{B*ba;}0{n9~X!p_fvoPeqHT{nc|1d)$i98-+en)`|elq?O5?mMSNWm zUwPuoWyKdKi_fWwpI5}^xBmIe=6|Z6jT4`K(yD!WviPJ`d|VM9eYlGDQAK>Xiuj-+ z-k&4htB7|Oig(^#Nqgs4@%BpMt&_!@74b$zy#Cs9+UphZ+H&I6lf^49FQ>gy5icL* zXfH1(UfNr{xQTdyh!-{y&sW5A&)V8^74fVso~ekZE8?jmmeQVDRXn-8c%mX6KUq9> z)Dx+*1*EQ+anUEADc|op&tM?yQJA z7VW6ru~6KxpSoz_I@+Qg#iGsCh3kmhE8@13#jVHGYqwOy&6M5ztGJ2Ey0Ic|XcgDD zit9#-YnK++RK(Sl&HoTrRm7DQamCW&@`||Z(vjL_p15?Rxa8ucv`f|(7cV6)x^QFd zqP@k18;c7n;{1v@uOiMpXC>|2R&mbROKRt=B+gz^oMnqME8+}daz;g*K0=&!>KN^` zia2$QIEDD1a$>j)=3M+N&BfM9=ncq;*R3P&D9es;`oX_+aJ9iD#Ne&@ z+~%*U1FjgjTkT(3^lz^ARm5%;(OVHc-P5$5lSOye`dari(Y3zltcW?D*tH@$JkkEE zXj>>|S46oYS}USu*6LbIMa;@Asm)qllqzDEirBd#cG}L-b{Z*mY!y2^EVd_N`(?#; zjv$TRc3H7aMQmLWGgetio8gJ+6)~+MrdGsOdy6R*F?m@rsUjxkH`XRr#Ds-n%k{+; z%`0kK#G<)zX{~uhF+N#Q8($IQh#J=_Qlip@B3V&1(TS#5G&U@yH7+e0Z&m)k?#?B- zX&?y0mOgbrM%GBNtR%{VBw$EvPZB2~4@0o5D%kiMz6MonShD3LEL6pYbFt{6T|NcO zW~OI)y8HiT_FdO;)GVAdIZYdO%v#i`EF6nA_-$4_Poz$%+u*BN^CXse!n_UYdKGgLQPO@AkeJ1O2e?;TaP{zv0JV!&$!b}miCIoyU_+UrW1kZ#!Zj9srw&)EHpl9*)ux9+1C zO4pQhmAK@2#xrHhLT@QjfQhq?#G!43GXg6h@N_b)d;03z_h9`0jLttU<*@S?esQjo literal 0 HcmV?d00001 From 9fc4dfa94d7afca6aaf4dab118ef7fab059577c9 Mon Sep 17 00:00:00 2001 From: ABDALRAHMAN MOLOOD Date: Wed, 14 Aug 2024 02:21:12 +0300 Subject: [PATCH 068/841] Update README.md - Thanks for the contributor --- README.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/README.md b/README.md index 1c087fe3..918ca8cc 100644 --- a/README.md +++ b/README.md @@ -100,3 +100,10 @@ a.n Ibnu Maksum - [mlink.id](https://mlink.id) - [https://github.com/sonyinside](https://github.com/sonyinside) + +## Thanks +We appreciate all people who are participating in this project. + + + + From ced0d487e7f257d0ceaa7c8d29912258f28c1421 Mon Sep 17 00:00:00 2001 From: Ibnu Maksum Date: Wed, 14 Aug 2024 09:11:11 +0700 Subject: [PATCH 069/841] Fix rad_acct --- radius.php | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/radius.php b/radius.php index 24fb5784..09e09bff 100644 --- a/radius.php +++ b/radius.php @@ -264,7 +264,7 @@ try { } header("HTTP/1.1 200 ok"); $d = ORM::for_table('rad_acct') - ->whereRaw("BINARY `code` = '$username'") + ->whereRaw("BINARY `username` = '$username'") ->where('acctstatustype', _post('acctStatusType')) ->findOne(); if (!$d) { @@ -275,7 +275,7 @@ try { if (_post('acctStatusType') == 'Stop') { // log in the Start only $start = ORM::for_table('rad_acct') - ->whereRaw("BINARY `code` = '$username'") + ->whereRaw("BINARY `username` = '$username'") ->where('acctstatustype', 'Start') ->findOne(); if (!$start) { @@ -288,6 +288,17 @@ try { $start->acctOutputOctets = 0; $start->acctInputOctets = 0; } + $start->acctsessionid = _post('acctSessionId'); + $start->username = $username; + $start->realm = _post('realm'); + $start->nasipaddress = _post('nasip'); + $start->nasid = _post('nasid'); + $start->nasportid = _post('nasPortId'); + $start->nasporttype = _post('nasPortType'); + $start->framedipaddress = _post('framedIPAddress'); + $start->acctstatustype = _post('acctStatusType'); + $start->macaddr = _post('macAddr'); + $start->dateAdded = date('Y-m-d H:i:s'); $start->save(); $d->acctOutputOctets = 0; $d->acctInputOctets = 0; @@ -392,7 +403,7 @@ function process_radiust_rest($tur, $code) if ($plan['typebp'] == "Limited") { if ($plan['limit_type'] == "Data_Limit" || $plan['limit_type'] == "Both_Limit") { - $raddact = ORM::for_table('rad_acct')->whereRaw("BINARY `code` = '$tur[username]'")->where('acctstatustype', 'Start')->find_one(); + $raddact = ORM::for_table('rad_acct')->whereRaw("BINARY `username` = '$tur[username]'")->where('acctstatustype', 'Start')->find_one(); $totalUsage = intval($raddact['acctOutputOctets']) + intval($raddact['acctInputOctets']); $attrs['reply:Mikrotik-Total-Limit'] = Text::convertDataUnit($plan['data_limit'], $plan['data_unit']) - $totalUsage; if ($attrs['reply:Mikrotik-Total-Limit'] < 0) { From 68959b5a2edb0875aad2723787b4ffa4ec3dc89e Mon Sep 17 00:00:00 2001 From: Ibnu Maksum Date: Wed, 14 Aug 2024 10:55:03 +0700 Subject: [PATCH 070/841] fix restore old version for mobile version --- ui/ui/community-rollback.tpl | 12 ++++++------ ui/ui/community.tpl | 29 +++++++++++++++++++++++------ 2 files changed, 29 insertions(+), 12 deletions(-) diff --git a/ui/ui/community-rollback.tpl b/ui/ui/community-rollback.tpl index 02a59c9d..3e039e03 100644 --- a/ui/ui/community-rollback.tpl +++ b/ui/ui/community-rollback.tpl @@ -15,14 +15,14 @@

    {foreach $masters as $data} - - + + {/foreach} @@ -40,14 +40,14 @@ {foreach $devs as $data} - - + + {/foreach} diff --git a/ui/ui/community.tpl b/ui/ui/community.tpl index b8260a26..4f96379d 100644 --- a/ui/ui/community.tpl +++ b/ui/ui/community.tpl @@ -1,9 +1,24 @@ {include file="sections/header.tpl"} -
    +


    +
    + +
    +
    +

    Contributors

    +
    +
    + + + +
    +
    +
    @@ -20,8 +35,6 @@
    -
    -

    Feedback

    @@ -144,7 +157,9 @@

    PHPNUXBILL

    - PHPNuxBill is a billing Hotspot and PPPOE for Mikrotik using PHP and Mikrotik API to comunicate with router. If you get more profit with this application, please donate us.
    Watch project in here + PHPNuxBill is a billing Hotspot and PPPOE for Mikrotik using PHP and Mikrotik API to comunicate + with router. If you get more profit with this application, please donate us.
    Watch project in here
    @@ -154,7 +169,8 @@ Download Latest Version
    -
    Select Old Version
    +
    Select Old Version +
    From b4a37a4722a54ebbc3eb54533adce3f75fa14063 Mon Sep 17 00:00:00 2001 From: Ibnu Maksum Date: Wed, 14 Aug 2024 16:54:14 +0700 Subject: [PATCH 071/841] get ready for pretty url --- .gitignore | 3 ++- .htaccess_firewall | 10 +++++++- system/boot.php | 10 +++++--- system/lan/english.json | 3 ++- ui/ui/sections/footer.tpl | 12 +++++----- ui/ui/sections/header.tpl | 20 ++++++++-------- ui/ui/sections/user-footer.tpl | 12 ++++------ ui/ui/sections/user-header.tpl | 42 +++++++++++++++++----------------- 8 files changed, 62 insertions(+), 50 deletions(-) diff --git a/.gitignore b/.gitignore index c14fa910..99dbdb61 100644 --- a/.gitignore +++ b/.gitignore @@ -51,4 +51,5 @@ system/devices/** docker-compose.yml docs/** !docs/*.html -!docs/*.md \ No newline at end of file +!docs/*.md +.htaccess \ No newline at end of file diff --git a/.htaccess_firewall b/.htaccess_firewall index 5d37c58f..e0a5bd5f 100644 --- a/.htaccess_firewall +++ b/.htaccess_firewall @@ -11,4 +11,12 @@ Order Allow,Deny Allow from all - \ No newline at end of file + + +RewriteEngine On +RewriteBase / +RewriteCond %{REQUEST_FILENAME} !-f +RewriteCond %{REQUEST_FILENAME} !-d +RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} !-f +RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} !-d +RewriteRule ^(.*)$ index.php [QSA,L] \ No newline at end of file diff --git a/system/boot.php b/system/boot.php index 45f1781e..67101234 100644 --- a/system/boot.php +++ b/system/boot.php @@ -43,7 +43,7 @@ $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('_url', APP_URL . '/?_route='); $ui->assign('_path', __DIR__); $ui->assign('_c', $config); $ui->assign('UPLOAD_PATH', str_replace($root_path, '', $UPLOAD_PATH)); @@ -66,8 +66,12 @@ if (isset($_SESSION['notify'])) { unset($_SESSION['ntype']); } -// Routing Engine -$req = _get('_route'); +if(!isset($_GET['_route'])) { + $req = ltrim(parse_url($_SERVER['REQUEST_URI'])['path'], '/'); +}else{ + // Routing Engine + $req = _get('_route'); +} $routes = explode('/', $req); $ui->assign('_routes', $routes); $handler = $routes[0]; diff --git a/system/lan/english.json b/system/lan/english.json index 6fa32501..9337da6a 100644 --- a/system/lan/english.json +++ b/system/lan/english.json @@ -701,5 +701,6 @@ "Failed_to_buy_package": "Failed to buy package", "New_Voucher_Created": "New Voucher Created", "New_Voucher_for_10mbps_Created": "New Voucher for 10mbps Created", - "Show_Chart": "Show Chart" + "Show_Chart": "Show Chart", + "": "" } \ No newline at end of file diff --git a/ui/ui/sections/footer.tpl b/ui/ui/sections/footer.tpl index 8d1cd480..5df993ad 100644 --- a/ui/ui/sections/footer.tpl +++ b/ui/ui/sections/footer.tpl @@ -7,12 +7,12 @@ target="_blank">AdminLTE - - - - - - + + + + + + {if isset($xfooter)} {$xfooter} diff --git a/ui/ui/sections/header.tpl b/ui/ui/sections/header.tpl index cd337197..e7d3ac49 100644 --- a/ui/ui/sections/header.tpl +++ b/ui/ui/sections/header.tpl @@ -5,18 +5,18 @@ {$_title} - {$_c['CompanyName']} - + - + - - - - - - - - + + + + + + + + {if isset($xheader)} @@ -87,6 +96,50 @@
    @@ -103,14 +102,14 @@
    - Income will reset every this day + {Lang::T('Income will reset every this day')}
    -

    edit at config.php

    +

    {Lang::T('edit at config.php')}

    @@ -118,7 +117,7 @@
    - Hide Dashboard Content + {Lang::T('Hide Dashboard Content')}
    @@ -227,7 +226,7 @@

    Radius Instructions

    + target="_blank">{Lang::T('Radius Instructions')}

    @@ -246,7 +245,7 @@
    -

    Customer can request to extend expirations

    +

    {Lang::T('Customer can request to extend expirations')}

    @@ -259,7 +258,7 @@
    + placeholder="{Lang::T('i agree to extends and will paid full after this')}">{$_c['extend_confirmation']}
    @@ -313,7 +312,7 @@
    - +
    - You will get Payment and Error - notification + {Lang::T('You will get Payment and Error + notification<')}/small>
    @@ -345,12 +344,11 @@
    -

    Must include [text] & [number], it will be - replaced. +

    {Lang::T('Must include')} [text] & [number], {Lang::T('it will be replaced.')}

    - +
    -

    Must include [text] & [number], it will be - replaced. +

    {Lang::T('Must include')} [text] & [number], {Lang::T('it will be replaced.')}

    - You can use WhatsApp in here too. {Lang::T('You can use')} WhatsApp {Lang::T('in here too.')} Free Server
    @@ -383,11 +380,9 @@
    -

    Must include [text] & [number], it will be - replaced. -

    +

    {Lang::T('Must include')} [text] & [number], {Lang::T('it will be replaced.')} - You can use WhatsApp in here too. {Lang::T('You can use')} WhatsApp {Lang::T('in here too.')} Free Server

    @@ -410,7 +405,7 @@
    -

    Empty this to use internal mail() PHP

    +

    {Lang::T('Empty this to use internal mail() PHP')}

    @@ -449,13 +444,13 @@
    - +
    -

    Customer will reply email to this address, empty if you want to - use From Address

    +

    {Lang::T('Customer will reply email to this address, empty if you want to + use From Address')}

    @@ -885,4 +880,4 @@ add dst-host=*.{$_domain} document.getElementById("tax_rate").addEventListener("change", toggleCustomTaxRate); }); -{include file="sections/footer.tpl"} \ No newline at end of file +{include file="sections/footer.tpl"} From 625254852d98a7646bb6ebac12eda8b8165ad619 Mon Sep 17 00:00:00 2001 From: Focuslinkstech <45756999+Focuslinkstech@users.noreply.github.com> Date: Tue, 13 Aug 2024 12:45:32 +0100 Subject: [PATCH 082/841] Create DejaVuSansMono.ttf add missing mpdf fonts --- .../mpdf/mpdf/ttfonts/DejaVuSansMono.ttf | Bin 0 -> 335068 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 system/vendor/mpdf/mpdf/ttfonts/DejaVuSansMono.ttf diff --git a/system/vendor/mpdf/mpdf/ttfonts/DejaVuSansMono.ttf b/system/vendor/mpdf/mpdf/ttfonts/DejaVuSansMono.ttf new file mode 100644 index 0000000000000000000000000000000000000000..8b7bb2a4e1b2c27786398c320e9020bcc24c3af3 GIT binary patch literal 335068 zcmeFa34ByV7B5^?ckS+*-m(%%r<2aYp0I>XmWYV#ATkgHStEuW*#txd*%#SF0s&)eX?d;B(&lz3=yZzwe3vb52*+tvYq; z)PAc&C?UiPA`^ehmR;Hpu*Gd6gjPprr6*cE-tv{fBU|A!K(;*5spC^UW0o$#=bMBy z%zxskKQ+JFL+(n*BWsbsq>fLe)t*~Aa4R91Nr>OI|Iof8dUZPW6+TZSBx-j5v7`Mz zX-E=}&`hXG74eh}OpC_by1H|9>T;EY6h=zZp`z3rfo*OcLzzgpUy@Jozh;(XW z&a-{9OK)}BP2_4T@O`};1n4`MhR>(*IVor8=y467YxFWcL%#}_h79lDH+py3R3blq zmXJEThxQ#e!n;^bCGz;Ci0>cPcj&WyE?t?0&pQZ7h#WC|)aci?w|axfc_#^(aBalM zXGb*pWS>Tq$bE!p74ZzW7CAC&crDIPH2bRQUCzI80vmV;VWa|)*bGA1OtuVC9?OHg zoUMkuhW#1xTDAf5Us*onx7lXMTi6!J@3Nhccd>ntKVpX&1uii# ziP#B!s&jKcI1i)cIs8^;h%J-4L~s36dq1h$R?v2Ww(r;uAsvL=xg-DfskTpXDnjn2 zstoNraxn1=T3yh(LkABXOd5?G-7lLo7kV-1BNGKOBP#bJXai3Zn)3Rg#0EX1h>xU@ znxr0SN?MXmB#ZPxY_56day|}e@Xz~@8aU0fKHDZ*pY3mfBUSIzifi#b(#^;hAvEK2 zeAWqV&YU* zQGNwnlE=#vDDe1&Zl2F=Kadc(?A}vdf_)HTgoHeh4l{zV zp5!Keq+|Igw}T{)lV6l4Jy1enCCgS8)%Iz_2-S|FgvIn5dVvQ ztHcsnWmc2bWsO)SYsuQN&Mb@dV%cmE8^Ol1iR@Lh&v|Sy+UF{^j%{RH*$%dc9biY< zN%kc>%f4rq*;RIf-I9o;N`~Z>VkDoGBvqBtrFv3hskzij>L7KIo|gJZ1Ee9+NNJq( zvNTniEiI6iNGqf@(gtahv`yM2?UN2k$EDAuucdR+CFzQEO)8N}WhU#gQ;v{hWxt#v zSC?zc4dkYB3%QNlN$x85l>5m!@-TTc>U@$sU7jm1l9$SF$!q0&d5gSV-YxH!56dUy z)ABd+1-Vczmaoe1q>DK5t1or7ZLuXpjjfMk)X{*NFPC86)Cq9 zv`26`(s??#0!zr|do$2CWCg=_EZC6g|gR)dV{C- zAZ5*jR)++weviV!ur0lMFNBJ35zcF0P`X3NZb94eTA)isU34_paEl4L4!Yc{d!kh~^OVH}vl57Zi-aAzIDr+o4vV@;o-?kDdw-O;; zf};_ilr6YRb3jUDzGEa?M6ZGp4`6O?@ z<>4oTuw=P>R^&dR>?@>f(F?)XQKDYK*Y1W`;fsPRMYu(4K+X=j5a+ERW?yVja5Cfz zW(7{mc7itGDOlmGQLrsSz6m~we81)~$(rCZ_%_QNig45HD^lY#!$CYX$t%*_X!1E> z%U~pr8B7&1{{*_f>>xric{;3J5OW6BnWqnmc^%!tV={LcW*w|u*$<#{*(uPP=0ea) zW$z%)B3=uukvRvnvpEfPoaoK0zNiKFLwZAm)D`{AE4dreMddzJ zO}lkB#Cqzy^6h^W(o^KVQap8UE@Q(?{RJ^&n<&2|zbwBZPsR+CV6I0nV%_XUo~$3sVZ+#HHi1oI)7f0Mh%IGrVXcyn)ya0Y zo9)LszBPmmADYcV2OIcDcDO(yO zjgZDl6Qx(BnbJIIv6LsRlGaHZrLEEqX^(V3Ix3x%zLd^N-%FRJtI`eWmP}+-He|0H zBm3kexvHEl*OME|&E-~d2f2&abP2MH% zlMi7%^tt@Cd``Y3Uy-lLC33046kTyD5lXD$S5lPfN^PZq(o|`ov{5=KU6r0nKP5*Q zri@l5D3g@w%3NiUvQ&9XS*zqLTa@j}Ze_o6SUI7bR=!a#D1}O~a$UKpn5wMWRks?Y zR#Fqy%4$uuuG&b=R9mX;)Xr*_+Dpw=2dN{}vFb$iRduF1PhG6$sjJj=>PB^|xeSp3*hQXBDJRGbN-<>&l2v zE~}79v5GY53Z*jWMCAtJXUSbaOBJrw3gsrkuPMjTk1bFSAY`e`W8Rd}s^~SIG8--N z{%51ySbUofx?9GagvKc2KsRy9dUHMLN{N?upmZ6urJ&tH=rkc`3fd)v_7HL-L7NNO zN6=S!d09I_dnnWKf@_qpzyLZkWqGe zL(N2ZFA?q+b)n0b?uPdh;h*!|=`KMx3Qe+vyj9S3f=+!Pe2G+qr*?#d9}+S53wq#Q zI2$gvhYq`ip84`#$V=sagC;1b7y7QkN2Q?Z1pT+5bGe1dPlDc3*FqMQb&)6GDM9HD zA-g%H$E6g|#q4E#+fn3eS$K=^Iz#^&;aU0x(78${E_08flVpU`N)oKZsw;eqYoQDP z?Wywkom5_@ITH5)H{-G)9R}?wtpJtzJ_hT_Q$Pq$Azh9DtuAwqN|$+FnKJjK>R8%S z=2x->?SmX|3Y|}LZ>OV$hxd`;WAv7v~kN@K_^q`3$`%Pl|;OG`n=Nl1rQ=4q0Xau(zy-m=JPc{J!XZa1<|g>Gnx zobFREfflPbKu-$!8n-GrtnyM!Rd}g4@D%6)1!=MzQQoO45C2*j0Xj();aneflZUXI z@=b(qRCYifq9lQ4D;q)k$fpsWuB?EZ!^^@Nt2#n1s08#EsPqgk0g)V6~+QkT;9o;Hp#! zAyXvo?T<)R5MIikqU%@-geX!DH~+%@LuVPUKin~xfjtH@Bv0# z<#U*)xSg=R9)mf^a(OukU`@T6B#HSfpp6l@X1ptk=zrvHCsOxL_xjONplw5nRVR!?iJHP>2c z9kedm(^?;GfHp)Msg2WK)~0H+wFTM|ZH2Z*+n{aIwrRVt<8??ou6?e3t)0^@X;-vs zT8UPwGhNr6dW0UU`}GvPx?Wpvpf}agN@PB#M2i&kJx=L3Ax{u;MXtsbNgSfD(|dP2_- z8-{A~-^#SE$lXd)lu`O!$}FosNFS!HWuFks|F;@i@hz){(om~fIy2#!<<#;7E9600 zl($@yP}!;lt8{-v&J)%X-i31+;d|U$?vpLw6YawCE~|}%dfIQeEt##omkV~jg|}NF z_o&<&xiFkVC6OkOT99XOw)85QfpfdrWGQJx^2mD9n&e|YrW@IXv!wy#069p8lf(G; zJUL4KPDYZm!;;t!?e-b1Z|QwU7M>d(w1s( zX=}B7ZHu;D+pX=_4r?d0)7m%M1+7pk)~;(eHB*;$yYAMb^h$c7URkfH*VP;8nR-jT zo!(i`(tGLI`XGITK30cb`m4Z9eV)Ep&(l}w>-3HKR(*%QM?at+)lceQ>Sy)u^~?HI z{f2(aMr^9huz77UHlHoYR@Ihnt7mI$Yi?^rh^+(A1$Y|h0}KF$*hbpM*_du`@uoJM9tnSi2u` z3VaY4w(>#o#*Fp15rRFAQ7kx)C4e2IvN3)j+Tyg zj?RuO$i0AUU=T0@7z<2vyb3x~q%{xHVjvG#1*`)$0$YI{jy)pI0mw&zla4PPXR%_q z4EZW>1Gt4(7ZAx%0mJa}_(qK3Gm^lo0_jFQ(8fS>qZMcepo{S|Xde-G0Hh(tNSxQd zY)my~8w-pj#tMY30X7($K(~o_yCCfY4jIRd&yBB*bC53qR{+$VQ38|_62`*xFlSgq zSS(~ekP=oMv^Gy8tU*}QuomELfKEVHpl4V=&>ZpoFi4}rCV);7pQl5b8@4EHY1ms~ zYa!6UWywUYbA)rObE5NA=S=53=VE7`bCq+QbE9*sbBA+}^MLcH^Q7}j z=UM0X&dbiL&Ku5KF5*&MhRf@Uars(t^uwgu92>B zu9sa?U9(*aTuWRlTx(n#T$^0mT)SNRT!&o8U7x$YcAaxwa$RvT0ad&ceb@z1lbLY5+xktMvxF@-%yXU$WxtF@%a<6sgySKQv zyLY?yyAQihxKF#kabIv3x{KY{-8bE)NA}n~Zcmh_k|)tq*;CU~*VD+8>1pX{=jrUp z^7Qg#dj@$%c*c4rdS3O+^vv@t_T+h1dDeM0dbWCYc=mV>c#e8bdcO3W^?dKS?78Z> z;ko4{Ue#-Oz1|qF&zt0}>P`37^EUQ2_qOtO@OJS&?d{_o;2q)}=^f{N**n!c+q=NK z#Jj?~#=F70$-B+F%e&8e$a~!Tx%X@DIqxO!74J1~iMKSIh3nzY@QCo(aDRA8c=hnw z;SIu@hPMcB6W%GjYk1G_e&IRc!@@_0PY9nBK0SPH_@eNo;ctbn4bKnX623ircliGB z!{H~wPltaKej&Utyg2-N_|0%LLXNOUxFez>Dn%qlRF0?_QJ0X2MnERe5@-i>2GD{d z(1IhffkD6sU@R~Zcomol%mWq!dB7@Q9k3DD3hV&Th9eFDM}d>Tm%v%zd*Cu~6}SQ1 ziX@S0q!H$kHgr+d`BMIHMw>Vx#;~ zDN)s`!l>e?>rrS~d}g4Wxi>!uk>3-tHSeh>GrVjP(2?O=YJ>sK0U>5d5%?HvAbo-?}>2BZaE?0V?{W8 zkJ~3CJjY7MnpcH}TQRMQrRN`@ z6GHsT@;%GP9;D?qe<02KYX5<6|HD%v$Nv!iz_Xz#hsuBC+0Z(&e8cjA2k9S5?E&5H zdn&YE9u_my(=6Gd55~9bBhs||`HxVmm$0cdONe#>unv6godt zwlsgRT%k1{qR)Lce9#V7Na(X6b`I6S>Ra+e%6TG=^{qv%Hf!}ERx5rmygWpt5E}o% z@cVSObPLhS`u1X|=9V?AI1gIpzby5GwQTu$dH4gG+^21*Ru9Is%JN|CgxdeXZy%=r z?}tCcZsppBSjn=#75*^!zFs|4!%)pb<%h)y3Ac;*nD?T$4;_(1N14!87AoI2(uJfM zI^uK{>30pSk>BPeF&;-^mNl$&gnZv;MS4TXZ-{4y33*s(91$MspTk8u!$o+xEaJBi&$bAS zFXRRyegh$k(?-@w$p1l~&}Tz+5b}1B{&p_YQkkDkr-a4{efIZd%jOS0YlVwv>xsPT zg~oY6?l0o>e;_X+!VwG&L*-B#juLr|5^09Yn^K#A?^~#eYa%_r-Z2uZ#ymLQ3VEQA2mWq4p=mxL;y)qcR}^x^Km4rKGg}_sQ#{p|TZZ)&*2q@) z`#;!K0L>8L8A5(8#Cp$)IM0gkK0@vzbYl$tdjLUnAqhuKh|$REMY`Ova?sMteV&8uw_Wg&@cO1`S-+!~%_kUOH z`@iRS6Z`(}8|RJlbSFxviJMkL+_CbC+f@~CuWA$Vi5pdk;x1J+af_;!c<&N>KLmR} zVNc=o$wWY)H%`J1lN01L`G#B|g`^lQ=q53#OzqT- zQ?5!l-KtD$(z>(}&7>`9JKC9M(Oxv04x%IISUQouN@vn}bTQ4NtLQq4H?ZVW+@kU+ zdDZX9{7w1)6z5^#4@>jEjW5#qoWJw+AN2fh!%saVo&QPMA6AyT;SAbsln>!E?jDL; zl0@8(qy%s7;f-sG^G%93t|{pR@bywppdV!J&BMS)19%?|bxu+16!lI~^ECJie?t#; zf8jq{SZ%~{okdbA&~F-=l%L3J)~eKM`?rqa96X1xU1Pm+|?W+?rM%D zGUDHVS5tu%_}xeidDzQuY@$aKH#V)f3{1KEB+v0)DtGQ}HWl|an~HmzO+)T&HVwJA z*;L%y#GI`BhA2{k#0MjalUZB;{zFHQ2H8UfK1Z4k7&xpiX)$ovz|o`)0{Y^{>G1wT zNLN974t+LzAn7-f#}xgGu!41;6L$whdii7rW(F32)k>Z1!}oZep-(2N;|oxVae|Qu-114nKdwU- z!1G|F9l?8yLgxOcTc6Pjy-66}uV0Ouz1Dr;x7mk~KVkcCnP)*MN&ix zJUyP4tvqe%zR$R*h<|rtKsUWU*G(FPun{D~QRWC5)Q}9tuo(`+Wq6E8qk<7n%osM@Me{uZP@xJ37 z#}UUt$ES`{j;|bN9Dj5C-SMsCqT>h0cgRncJL4`Y!F&2+NClbS83`Cya6VZV-*q9W zhGv8r;YPGk(TFz!Mw(H_sBb)CG&3GEo-o=P9gU}qZblEIx6$8t&QW9xcYNr0&#~U| zw&MfGX2&tdCyvh?UpV$U{^2<9D8TI#*cI<|q9w~&{C!&75$J`M-ya%i{H6fj{u~WG zqM%0}iILxgHi_kWsQjGPh%#bvN}FiZG-@05j7CONoX@s2+87;-&PG?`X``3X&lun+ zG=@2LIkr01Ir1Ib9h)3S9fuqz9G^S(IKFY5b6j#<`Crn5;;jn?e~mz0$;MdR*5Qy-jbx0(P4A$ATRM)iyWflv-;5I9JTJbvmr5*B(vgx% z41PAjQm6k@u}Q%ZDt1qgPaJO}ax=>xJu2ui4ZpPh>DkWL zoVm`G&ObZ<;#}{1+qu)Z+xe-xG>*mD;v(Xr+c)yTjpEtTkU(t_pWcJ?{B_Oe4qNh^%eMj^!@DnH9j&vF8=ZO_VL}~yT|v4 ze9!mT)@rT5J z1=K)fph6%aP&rU7kP&DaXc1@~Xdmbl=o07|=o5H0FfcG8Fd^_#U`k+4;Elkhz-LK; zl(dvNDJxP|r@Wggr`l3eQ`@GtPwkxAHMLjjnAF9on^X6s?oU0GdLi|PDnC}aT{W%h z;A&yjVykCYA5r~<>JzHJQZuGze9h#VHP=V2k6)j+?$v-e$Ka-+trv%G>YU z{^54e9Br1G!C)E26#k!|tfHS{b#epuzDrpWdklBHJFyShA$A=1w=W1UAmv^#T6n=! zc)>jB&$w@N4Y#XD;@;32+@|LDg+7sw$)91R606iwx+{H^S-A0RyXyrBxY5IJIgeJy z2Xct`o+B< zykL3UP9O2b_|kn{d^x^}@Pd`TjlM0u?Y`ZbvlQgYbevc)=}r!JukNH7~qiX!SAG$5)>yydV)?ps%mEK5_l5^$Ua-(A%AF&%XWE z?fl!9Z@X2HON%2U`W72sRAX4^|0=1+}1LmYKhrznDLpKbhZ}XUzTP zK69_R$9&9eZa!)@H0zqR%yhGwnQA7QmCP73%8W3>O}i?6bfjos z(c4A&MT3e46lE9nDtfvotEgL1m!dXBt%_O{H7{yZ)S#$lQT3v#MU{(Eiu^^sqDn=v zMKMLuMNvhOMG-~bB2SUK$XOItk8HuEHB6_SX!{8;EjUU3l*K;?|{qk+^Z@Yin?c0voW3xwQkH~gqJNuVJ zoOQ2ucg9;b&D{-LrmHw?V%Upe<9XPO3AQDy^96S%HuLX7#d^9iy;m5!ySYWV$1lw@16W~*U*^oa2 zpKF2ZCCvj?BOJfsB>fpcT=paQN#Hvm8i4)e-r!ZhVPCmFWXuvV<0dl7BrOMD0Dw!d zv%CiQ3*^6o=L7FShHd3t0PKZ3bwu6=9Docv%AWwde0#uA1{t=K`1jCNMjc7}F)wuk z9?1U$#~FYU2l-#%*c(-_B9LG|r8@vU1%J(g zycHaJJE1SHV<&WVB2O9h>qH(-_>+vho$v(?`6KZ47Uccl`M}!<{}}uoU?=2*;P4UW zZpfd5!!MklLOxB1`y_z2ird8`j#*GpmvK6Px>Puiu%Mt`{n!IuLlx6%?E<%ru0 z8STVJ0Hm!90*?V|KzbPhSo&9y09Xn+U+B3d-(7`W(u2aM;)f z`zr8xAL`8a4&)N>Edc6Axe2}b3#J=g0f@F`^2()Ts+Eo6M* zy8skGHoz|fKSK6`Uj=@K47>Vx9=}3H0by1W&)bY29A%7$t<`$q{4;E$!oKmX0F+mS zUE@0e-5{f^@!c(`BfxuDP@e~X#)3K$yf^R?;*SEK1Z;!62pnaMKL8o!iATBOzkvKD zILALAUjj#&;?Ym2SHNMr_#2SRz)Jww1MWkhCh@~xH29F;4Fn)ZfTvi{Dubs1^$}hL zydi+Luhj-e+5Al**9Ave{jDJ*p1-XHjeigQIkYC=D5oFg)9{RcG%ycxCinti1!UO3 zzY2ICGVJ5u0qlhQG9d}5Ck|~AxMD$@3?2r!5dJDS>LDQ-@-*-YKrG~$;BgkT+2Dy5 zv^n5O7PPtGC@+Wh8hBNp8f55~fVRS+LC1tv7PN)nPXWAKsEY)Amk2$ymEh2YLr0#8 z9v~dD4;;F2=n3G^G0_hhx+JCoH6Wv1Cc=)1u#;W~{83;aWPDB>3P4|d0Qh_WdFm)* z;v2wUAkP9n2poc(2mYxA9X3t;2KWKtZ-W2Jg8mL6sAdvS5xxmr2e@wUgTsddu$}%f zcqIV(>PQ<49}=hx`4~8C!=Zl$o?$^h368oCpl-IcuVF9C)r~O$!dx|9aH%`Y43I3|yzX*>VR(oVqcNmM)_|~hP)PhHt+`I)8KgiHu?hx zY-Y#14KmiNP;}#^OA&5{bj`A5Z)wfh3}{NkYR(A*t9m ztwO4jYS{U#f#0Z1Bk6>nSJ%Owc?N#Nu|8=)8saA2Bcw5Dg5BU|B$GT!nv=&!3-UN= zNuD6Bu!Gx%v=t`|9Y{xE=4}7u@&zD|s8|oEynIWHZ@Bwvczpd*pqx4dT^gQyJ zbvF-&Rn9E(G3blx`5?l}{n`Q`FlG)Y@9y!u(Wd zHU;{Bi~5;^w-}aUE%`L$UF0D2G2xG*Ec6WSWWIvmbZWu|Al^ZwmPhjF6mo`)k_ojV z=6A{&Rt>3cLkak*d4+ODS<3AJenz>5Z!n3)Zx=;q0hEH3zm|GkLRUSu!GeP}-U0crM= zZsKzSG+QA`OvpC8q0~X?fHDt2*a|`CTNLNVpGvo2_l3-)t>l(i8_y>%;&)Y+!i&*0 z!!m>nmokw1aPp$^n)MGpolj~guSrW_QDF^QhczK9*Z?{Q+LpkY!=)BzZv#l2a+OS@ z+n_hmULvFLJ`Ec42b!wL5~HNL-@Sz;x6a;@`DB*=aQB27)qnHR@7DZVNT)4fGZj2flmQm*3T>-nLVge+P|zyhVAkkN0VTz^Ag11ODg1$nJ53 zSpluLD9QN0b)PN%{yF~H?%9Dxv)#`&s)6$JGe?HqQhqX+V=j?%l(mpG5|1BKrYIOu zX~cG_D^r+E(hi(1u0`CZi%%D)hkFt{$qAl>9GR4kk}8%Km`gP0&Fdr8DtHE`lQIbE z6n&qK#Amvs8CaRl)MZJd5{_TpryCd7ZrHFENxM{9oKEX_q=4k96B%IgvB=et$Brpy z%APlu(`U>DznycIRbmPXQjX6C~ySO$ol-vLr^$1Y=EYZ@?~9ldK9A0KCivX4 znxx}5ksNBpaHX=}i3;^ayCf~$eLA{vadhp{#>MW^OIJ~zL$wcFExGExdZ^^8$J@}; z(Bq8;8p4oGX-3_YRF9KJMns`lHEC*wk4AfHBDh}tj5^Wy5Q#vK4-r(2Z5uXm#JQX? zLr-VZ0Y~~}AM1bk=ofplX~#8P{WJa>w|DUayYHT(8HT0^N> zWn0tcj2?~OzU0jhoj?Al_+sCwmL{7|#_!L|J7MF#q+lE*@)qvd^SOr?s|P?xGb(n0J-vc0Y&-d@dU+$UDIdmpv^iA z8r;79kU<@1>`bqjHoDogT_4ccK6Fi=f{p|6#o$35@I{RpV;-HpbBAbCq+#%)d=PzX zRrEgZW%l#9nb#GKlX7QtSeQ|xI;&YN8uOLfb?Ro+Q)<bS22)dS!1yMLo=2v8Fe&f%|Onfzku+ zLza=ae+WatMY#PAT`IZyh zEZGzj{XuGSkM@sD{;c(%d**%;6YYu)gK;TyOZjY%=wrMeP%;z0GRS0fExcnnAi5Q{ zr@TYqbwO#qd0iTV-HkBbyQwS4a%Y%EB(F+h>`pvayBM~@!@PG>S!9GaI*`IL>U!%- zW2Q}+GHq4v;>EeD_mcTYVS(AG@GAZI!g+e280q#zx~X^4)p)uZb?A64!RtV}rNy=H zrCTS;8yUg0Ks|3pT}FF~G*=;Y)mv;fKL4HBxcD+Xbny~i6ogl-V{PPW@Es57kXhXw z=D;fiHjV$vwDhLpG2XOO=Mt}O*d?3lk#GZqRB*`-TZJ&yE4u2l=v;Zn!23Y=4c>Vl z-~srYPQ$2{j80cctwHN6o;sdnxtf_r2Q)Odj54=0qyx;nhP2Zt+DSgY|Kong%o%k2 zv3?)#?|+PrH)kBuBGpnGs~QjjmEwYm&iYWl~9x#d$l|0eu$owgglN zjx3QWx>^t0P5)*-w!v&ccgwGvE%LdLPj|zXubbbo>og5LNKB>!yVPq`Nv3f`?(-Z?3K|e0^kVyZ4LWsf*r4sS z*XGQ5ZQh(Y^Zxbo&;R<@jT`K0{Z5_gH|WrgtuRlTN6e$yu( zIJ|%PGJS>46m?gEai}Hg&Q4M?BcxoJEV2NOuHRzZk@s6mis@}&T;_tTZufGS%p+eR#YXXLaY>B zFRc1-?sh_-Y;>VPv zBN=sV%c*ks2XMtNx71F5~$eB=(4^ja? z8YfAp9Yw|HZdI&wzS+F?`wpe&5BvI`H@-DXuhRgHXtUV-cJkuIlc&#|schSooNAso zi?Roszx;F^6Xr2=A)P>9i!U3pYwg-y@4mAMJA|<59MmW8Q&p0YSwTr=5|ff;MQ*OZ zqLL!ved|OLuR+%XV(?76QGBPN@K(}25w=9u33H^4WmmpndRc~Yrt7WAN;Mo0k}0UK z4x;Z3VD9}`W^#-{a#Ph@UyWQZdf(K)rpFjbRq-1TK9|iGSus)axf0^jQEkPd-uUeD zj=OW)G=#5*m>~Ji%!jwf@-~o!8Buu1Oq1ozc>RrOGhcthJUV&d^^>QrFPyw&rDZS>_LiS*4zwvMU0{m=qxH-cd6^}M+jj{L(J$!9iF*A&< zAsgj2szT#rf+ZkYCGP}Lu~2w@n>tyzNfiHU6%K6iNybC(z3dkL9d zMaH^ckv6ICXq1u4aw>Pa+Pwa66l1DnW05q2%HvBnNu6(>mlLFq@G8;AAJ8@HaLEJh zFN^k($4hI<%V@}}RJMxf3bl%O07VqD1gq_%{bMhQCv*EeGd8m3d@%WqKB|J5oFZ?c z?`SHkEEBFzgJ9hgX#mZknOHc8RhbwGqR?Di7*XS} z{Klri#yw5CJl!;H%Fqs5`}NwJv+LW(dSyMHa`4zOx-hTbtj^sZ$*R?T*yAmBH*BzP zb-O7&yEgCAB+a~Ta-Sd-&5z_fWfbOCb;*d#T9vCM#YRg`!&b4bv^m#17{A127kA_>6u}Z zlu7C&ZBqE8h)IzupTF=jq4l6c3=d@Rwv&S5@|BQSgc8wd)~g?lZ~WE=Z=~#;G1Y|?DS9?Wlcnje@GA|hv0h{4an&!yAp3A5w^Y=W}@d7~H~?PO`@ zqa+!VU$}O%B5Qz}tSGWAS+eT@O}0yRl8j9}$&T?;%cWZ|d@67jRcwOUlr*~oHnKKP z(5UVVp1N2TYFHgw3&cB;j{bP7CQ#=u#rbkWzzq+?eE5W92Mfjb*2!fFG{Ihsg{lSyy*$N;g-)<#AZRUn604C^OVm@uwP|$f5{lu z?snf*D1H84Tb8`F;a@*4nlgE@*@o^axH)CY>+8)DyhPZN9Vz?v#n%?iVgt;kBVKww zd)=Y;XT22>_1UUppYd@F{cv`NM2?0;I@YX8SgBxqXqep_IPd4p}zumFh%r{T1yG>iswzqG;pro0L z%}JPMzk!TUew-0utUZIaSS2$`<@0N7^X1C#+NolzrD0lB#}L(W0PC! zPq6|&NW;r|vS-VdV^cEUY?WVDU-YvBP*$AalJNndNRNF!Gn7bJ@#ys zztg-I+qS2N{ediBF&l;qkC1uftZto>;Hwx$IqRo7zlAkY&c?o_= zJ9tsrjdVSvdS6C1hb6t9_eWq)f*QWU#Bm+K&&egIbCL$-`ed+bf*9>Aez|A-7 zhW6N>Gyi#W3VY&`+3(Hlvvr6<%Uv>sA7B}>iHy6J=QF8Vkv8XX)e zgVwQOVycPCc;TOAAF{4D%nEtDMsnEFvbRcKW5sLB_~sxbU!gqw1cL8%7`#fbu^`nV zbyc_?I*YVRR_#V6e07YSD$Q2Th}EaK-zJa8a|W4~SzX7}S(7AYrwl(F&S-PH#&E$1 z=5U}($DxK|S5-O9u9EaH?$Xv;F0C=PgYNGBDOeTpmC>Em(N>q8l4mlL6y0u%rZG~q z9%D7YeSk zo42Ydsipsv!f*W@<>qsLz9zSkp_!F1>!J)-G@5g@x1ma@#yoN@%|p_80~ehYYyo}Y zHh0%>GS+Zgv0I8dOo?VOS{0UpKQ`8l|1mgi44a_YV^k=twxq4qZuB{tqw?V=JOLwt z2P7~Dmt$^z93-axv2x~i9r@E+)#Oia*TFbC27N?NG0(=nO=h?)*CpjfE^#f3A-G4R z*7jz^2&L|Lb2@c1YtI6^7~vtZG;2oQvKcd$<<0owm$I^wUrMp@^aE{;U&1ZK2)@HC z#O>?W<^*#R_9|x58FZ342|mF@e>w)X(Q(RLEi;DZy0KX?)9beDIG#~zhc)mJpRG;= zlt6P8%W^D@ux)X7jKk1|odUTUN=fHmnfvC7*UWZw+bzn>;O#3%m9(_MHeZX?Z~ek;F>B7@T=yLdRb+G$W-`JE=6LfPb6KlB+0rlf zTMM?C55GAD+k|7+Wl&}VOjsnlnv6eKqa@3+)LfNGq$ERYEX-#*WW^I@Q}MTKJfxCS zvR9}rdum14eMUMqVPLxh+;}KK`M!8#ZbV*$J98c0QHV`(OlNUyB2H7dO+CWA>RofQ zn;nLAKKA#m?O*Kw(J{KJgsQ8{PJX*^UhV?+QN-|dW)2;{`kAs>%9(SYFaD5qFT48c z^vSb$8-Sm+fuE(4shLf}4CZts`{I4NjcNAe_;_D)yTcbR)5!NC*2m;}=zC{h6{Z+>n|J8uKAMfrc(bwNkJ6y2 zNgAVkW_EWMKmI@L>!jhrb4J}H%yFd~J$Lq+zi#LogFfG9-Ygw>dhn=EbC%_gSvch6 zZW?yJ>mFszr;jwA_I&@GKuoRA-#>GqMvbppx0v3{x|-{71rcLUW0nn zNTp1tYIS^#FjZ)z@RLEY8FzOGg2B_|QD%)}W;KjFx6betKJPnUhy9u$jX2CZa7^aK z$)_zhW|^DL^tpVVS_~tA7{SG)3nLmgMmSo31V0|aERb)m@sE5)&q^}<{T>kN0 zyNye58AltoY@R=8VE$u|H)2hsrKQHuXDU3>xbY(udJd6FN^=T6YW7H@MvpYb>5nW!o}>nIZ^PZM=-<2YLlfY>3o?f1}AiE_qI0p6x*6+ zV;hjqm2r@rLwlbx+x~2}J(aIiLq{s+UC3Cp1%rH-*#hIB&2E$JHp%Y5ZXmyax#9T){dc4$8qj9hi>o%qIK}?&`4VOVQFdOyW@g2Sl&?xTx_0c ze6-Mc{~KfDj?^n&ikIW@`~*|HqZ7|-cB#&~J0Jl;0e5rA`g>Qtos ze<|RgfrIn&zt}kc;Q77Bj$*IdjA6*8I$%AlFXTtmH1dd@PrELaUV;-@ zL(!de?{6)1|7Vz}J~kJg$!rj&$c`8#l~$IjC@GFC$2c}#dBNd8pT=CeOUIw^(i5;& ztEMMAGB6A2u4g%(Wuusz53ZO`@F@kKRdoG3X5k(FZazxS|J__?QsRKfSva)JgZun!hcpPIO*Yy*VFlF}0BtnQBCCtoTS{%_iDk`RbRK^`Xuw z)Z+bN@>g^S9sGAQflqOUve!$Gl=WkH8w`5jZ4-GR>cU1I&#a_ddwlT9<~rZw%T+K( zp>i5g`8bb>HbxYl;cqwkw(2^(j4v-Sen;|SoD7<q0|wLz05@1D|s@&h0Bb)NUr$eZ2CTiQ-PP1p$zfdR<*ZX+UNG2?eZ;$a=0<0&W zx}9bY?bHcHh0f9PRaT-7K-}a^8{UE1DbvQHq&&B_TWnq0ZgF<$k+l<%GaGa-=9yFa zEv=Aeey9#GXVP)-VZH|)zeA>DL;DV9ePH6SoF?z%p)|TCjZVlI^lgj+tXzApC=4ix{2=G z`N(^d-adZ&r(fvw*L&^jG2p|jIR~4h_*tFjM?5>?i(OUPl}%ok-TR|8AMTHvKE7Vv z9jU3EJJ&`H^ZD6FC@XvgWvxWgGh<^6n>5#Dn;W^zwWs3p3dHMuBF0eF*p_i9TWw6y zxJ!!(5?}R%?j2!!%sTkuqYrmQY01oK(`V0~K5b^%#p=rk9KHO*vFv3vckEzkUw-qC zGpEmf!~O?z?;RKAvHg!f^E}TsShm6L(pf-2MWu;=Qr3ou4Z9*5dyPHz-W!OCMuQGJLsFW;~h7+WKutEJ* z90`lKPyb*c<=xNsQb2gMS~+r3>0|v6nfnn-VshV|y}NH6{@jZ%9US>c$Gp^3mdnEM zC%0v*S30);Arvyt7oUmj*dX54ynApzD>>83txY8e%wyQynfA^O`F!NSuedScK-clRsX@P12m#m zmNQrhzH;^2rOO{(^}#a)`(g(?UERre>oZuqs)TwAD4{7-K$wNanP{GPm-tSD$$1Ffs)RXFwxUuy3J4TX!V# zDjD^4T2=`c0`2J_F;piQG};hza2V9(XTh2A2ExYCyWjFXY+3{qkUWN{B8jHi@uZ2A zQ{ElZi>*+W)hm}->NC%4!)p3Y7*pMlCcRtTyPn(+>AaK@)MHfdY>7K1!WbKsVvuZ` zLLG+6SVyHseIjvb(^c#FI!jt{g*xW^&h>v^TX>~Ju>y|H{YDSe|uWJnD_Pv zAH4ncKd&m+8|FZulbXL=12P^EzW;%}HJ67d54fK6?f#-=Ktvbg$sd1OOcb+yz<>f) zk}Q}f1e%pxcZ>#}oRxZ3Ct1##9+gh(&)94MnU7$LWmS)CnQ`|^>SKx)T?_jFs&BO%SP-t%&%T?>Be2+5(HdXRV90M zF*=eX`)N`8${~hp!u8o=TTMHCu{fR_dy(4&{>2fXA>o<`ZKN(--yB)+n(I199biGs z)8*((rS7_++M&8B(jcF9f~4x;6^xz^#k+UegD55B`D5@yBD5fZOxwKqft{OA+%MHte zmIqfms-4y0)e+T^)lt>a)iKqvi7;>wV{$~WfD6)iQ|$bg;@*TwrR%2e&n_Uf7Lu#Q;eGG}SLEkb71ZUne=o0L7Zf4)cy5 zCzkl-SLesqupif{a>KeR&l}pH>i&b3*OYG{CcH72{p=MT=x$>#lzws??4BgM04Bfe za>85_btd9;43}KGL53-82WPV1ny z6!f5N@LD6D2L;VVLicocl0~pEi`6B#n9G_jz~F01x4H#4>uhmb%Y-skW+}7UhC^pT zhC2T~I-K&V4hy>k5o7gEiY?J*|c%@aYOgaJ8OpL0U=@X?jb=PUb61p~5*<};e zj79mGq%U~kk$4;6d+Ad)-KB^j)wtimCQbDD9!PKY+1-E1qKX$vH&oqxuYcX-2`>*= zxb|m#*T)~adcJ(0oOiTMo4);flqQ-YYnSYMDKYUxcJ`Q|%QHk%+}34#{ua;Ix(a)* z*X+Vw%y5UBGeFyt))joAYZ(8C=rw z-hWkfL)JULsF-}Fe#(rM8;>8)cxL9o{cJxmY+~2qg4<8*A2k--n$B}9);LujiTBhv zcMI?kJougJyC3{a3r~5xn6>m4J`E)bY0KsALRTGV0_R;f{z^ApSrE0n)+Sy8#RSL$78Z=p) zq?s7BNL(f@Kn3-Mn#DoOg2J(HJ{=Du9Z%hv-H$zSrcU|e@bgCwV*}@jojfO`4YzlT z<2^gobM1+}T!Xy~7M^jJKq7(d+9}C8`UZuD$RsChA;IKZ9pp3w!L2&T861S&H8`=i zu#w12*5k}Y?@wZPy_TdF(nF|H%MG8&2<}GMLBC#(+>ZkPjUCl-Ye_6*AKiF1NjH}* zK)G)QSc2?9?d7&XFJ zP3dz6IWxPRVH4+^RDNsUyZ6o!XXV}v+ob!|wO+uvT9A3dAPjLwOLQOfPAs<*1ntw1 z#h^2iS$9F(HHc`dS8?!Xol!37jNJBiQm($MRH`2=4bhL2ChL(pOdk}WM*6qZ+OtGl z)$kH@XAjGx_cvVIen5h9410cEIU?PH9NbJ8@6L`e+k>@9hDeJ&CRpQ&mxSOtgHXp_ zGrVrE3q6)(Gz4jyIU*hM^v83pTNV}Q5og(dtHd%;_ zvlm!|V41HTF)REr{a5Sfo8sMrbSH>AEgFFZ{#|g;q8oQ1m0j;rHK=_0v|)p)x)lDt ze@d0xT{UI@?}aCZRQ*=FIVxiFW4~1msor}1$L+JKAK3B3^=;~UhOnFP(W1Ps$!;49 zmdz+vwmSm12^Ho{DbdhALj1ebkbjB%L;)0D)g;}dkX0Z+hvaaQ&yT#IM|Gd_nU3II z6SDeLb?^O9|Ln1)M*9Q9i#JHdLmhImg5>z{4n>FZ+d1MiK{@ct^2b$4!0K37JcPAu zy$rV)5k71IVO6*2G_v8nW(~~>wIZyF;;Q5i6y;P=o)?~zb2sz-nv5cv4MRHQ-l|@CXI(1)}H{nyIf$9D= zA#bJfuhqME%h?B;w~`xnYFalx7?&U^pRrg6%e(ytD+pzA%BN7*rb;7?H|y)a#r+~1 z@DSL)qJ%=XOXpy=pt>-<5k9LhbVY2p7d;sUBH!m%?S8*DhnTl`1i!A?xPruYdG$#|@gg`c|!;KlRUQCGEfg z_HOm}${#U&U*8nY$UWsw;3;Xs3U{Q-5#=;BZygdI8)ax|Y@HHsH_MXYPMkBUo(b+0 z=}wD~*6DFAnz=%pHdA~`Gp*TfYZ)7El(oWqhsm};JHNTB8N#=qd4t|rwKw_+0pUJj zUE?oFhZ6ABL|G{1IJv7SLU42`gqz7Jx)e18CnqJx$sc9X*u}%jmn8_O%(7nLaXoZ^b?&9aR6F)nmTo;j@bz7bDTG~JWs z`?7|&$sFE#-+lY>Z}t9wB68odaABFd3+xF7ZaXp1HwpAEjO+{x&_taO|1xZIuz`S9>Rw=a&_}2u2u6sYc=L1XI{c$>9Y81#9@ISI2@-#4 z5a@4?H?Q9*kd46QOra2V>HNfIv3Xg+)@Chb7F8YjR_xnORxP|Gzn#9_S(K===Et{e z7u+l_OV-5?4ATv49hN^(NH(>OOl~(Yr3lmAID6^FO}HjPg~M3{*`xu-S)cDcS~;eG zN^#7$hdI3=Zz_s3c`$IpZDX(&UTx4}0$=dDmG<|q&Kou5%}CRwmBWS?w7>XV_eTd0 z-j+9h=JoI^%ZCrk?{Mzvk{YF|u%PPK!u)DY-QJXxvTo(G&H8ye$CX!Rx1H+Vygw!e ztpj?FUu2qJGk#cgMynZJS3Vx&x!k%u4evqvo5C>Q$6KT+mL5cOFYPztLABz)WZ}AA zGfHNoxM4;Oq`{Vx|88OuDaeZ847&dOd9CIA`STb1dZneUeBD#Aj95v_E&VJ=$fPL z@2}vw@7qHn?Od_z^X5!}@j%_JSm;Bzy%-t+P)A>Yq2F)}S_5mcG_w8l_H))%uFRc~ z*>+aJ(YN1uzF^kb$;W#1=+&!7&tsD&AM4q(N6#KTj!jv1wYPzIt;+yL@s zTPDYa2~LC5JS9BDFgbWioHRLXQcKmDATyK4s1Q8@=H0qMW|_0!e|Lp&lF-r1D}1Vw z0(O__h3kvFrWevpiwCzX9$YeMRdsd7s(vfBzjUx}-khu@ox7|nsz2zNBG!7w%4J=8 zyL(m7jww*wGdgx!|GPCTjHQf{4OPxNC? z_KjJaQ?-u5r=HuGNdfDee$g8DH#Q= zb5?#eetdapX_tH4g{AknGjh+-c05%e4Ro`xa_JSH<6I4qPHcFh>aZan&X^0*^TEC{x^r?NyX3o(3 zn9-*7tWK+6IJ$1_iz}v=mEAwBcb^$5jt>E^rMODiZed>tH~c$Tw_E;qhz9YDS{A97 zqm4qODagXP6ERQ{h`_1vV|orP!RqIWRvsfDj`c@c!fA7>^1=b-DC>CuZz#q(iM7%a ztT9{|IJ*#pzYQ!HKZW2Y zEz}wYXa|F#-U$+-0d#2Mb_BN}Vk|6TS+ZrBgy6OofE@AVm$-geg&kCmg6jRjZB2A< z-gnvE@QWXf7<1z9?Pqo9IzmrdpcC09ecf}iGqLaHM6!tK-Su?a^Su16L*61nOyyL(= zv8rKrhuol$ZB9p@K4raomU%9NrcS=of%_tdz{Aptx5;{~XcBaTHPT>~fr#mA2;SoX zFK07voyC)g$SeKfK4@YwJ5_bE>Vun11ILT;+PL38m3mvR*Pr-G#gDJWH1Tt3B<_zL zg=82zhHLJN?Zuttu|^c!D~&{i(VaWwG$FM>u0bv8%@ckN!JXKu`51gOuVXM|6@f4d z{M7*Q&;V?LldU^MvprZpN;_CuB8=hzq&`x>v7aOut1deyi+h($e)HqcH(vC7AO(qI zT0D^ANu5S;O2RGh>+8T{iVuz=ZG7ZU;o#7=ABFFX+oL1QhH$%Nm~5URO}0Y^c_TW0;mjx65J(~`bflZCyt*zd;GXLvnL$5aQ@i?=Px`f?)6k?7S(RrwDYm` zn`-BL^72a`fBe$RpEQj0^43?tTPqrQt5Fjqao(!YGoy~pg-7vR)v8H>m3~N6-pX03 z0nP%5OfoQW9lNZgg1f%2wD$590O8ozJn)m+?|g5>~pq z-8&{KUX6(octn(tu(lb(qH3D0Pu3QeVAYH24;IgK{JZ%nIjHdp#x^L;=_jsO@D8j#_MCO#@t?~v$(`PAfB1h1t%IhzU&VTQbNp^jv;g>RV{?Fi zcekHx(oT4+_CMXEop4ZXKjCeE1LJG?_y|1V}x|qw1Vsi zvt&vchV<~T*kBz6mVpL?9azrtQ+X|uN9ThFxhVD!(Oe)WR_2TGqSIhUd05v=%CpM5 zOO~)SZ?G5BE5B(j`+~c~S05G^{qe3E^`)df?D-VyB%NKcZZzNrtXStM+}QVudJktV)9z zGSD58JIDh-gW9;GgD7kg#z2@%H4=BJ)*%Rq8IWn0a-eXpYWki@5|x4F7?{(*bOyxn zjZmI=0F}e;dq8=DRXm_Psq6&{tzaYO;NSF@vUeW!0a`#_(BFAcKCE>@7C~HyFvZf@1=SOdxRQQtnEhPdrm-xocR2;X zOk3aDb3uH&??C06vbJoT_(fj@`+%sJzI`tgH*{y(T@)44uk4Ld;xF9ipW{^ST{soz z$EmyfG~(3VeF&%2aeO#sbv0ugr<$d?gl1-!52w^I2~X7iK0L8Di>Ln98S%@SrNQz?XU?ug6o+c{zvP>^dg)$ zHJRqzP-M0+WI1qfcxkwB|EN3Fy`pvG#9^0k#Jde_Kzx@Vh z&hv7-=cm=HR;^-3mH)nX^`m!{2XQromtl`z0y|e4@^fWC#|`auh)a-LIyN~YD??jW zN{@!tv@se&VqEb!|7Iy#ZH%^=#nD=8=^_-T(-Yz%a!p+V7XVnKM<7KmGIS}I$-+fA zuf|4miARksY5J^EV@pUysd{U?{N9Hb-xD9*pVPVhj_IGA?Ygd0&ov$HU*2(k=ZaxZ z)QSscE|~R_JoEBf*FQ8Z9-GmtWzz7y59~Y=5xzGrc2wVP_m!sPuIaP<*~BTcR&BaX zKD#&v?w_n3kMrvSdaM;X)0MhM``mlCixZl(=lI4E7c^1yr%$(KTrakORSu?8k$#W;?j2V%;y0F*k z{9%ie;#Utn^dNh&q`#m@au;;^PI-&=`3&R)_&}4KFp9xkPXg*v2o12ROIh4>Vk)Fs|#;Ews6&T!@c6yZ9eyC>K`VHIKYtk+$tIt6<`yr}s8kvDL7sb{?TUCrMJNMv- z(F&62z4tm&RGgi5f$#w55T&L2*_Y12e?PeoAU~geP0r`;cHj9lY4@Iw<)}F_)(&c~ zF+<+KF=0NnAI*nx(U0gs_)&8k7xfECcNMj9xzgHLTybr*0sZMrd4EnP!jBqaqa^CT zEOtiJeX(UxePZ2F=npzEMA!~p;B@??gRGGP;Ytx?MXTS9B#Fq@F%On15;4d!ic5a! zEYv3C!3f(4x%z4#?6L2E#(&CWN;twc{Ve_SmnRO;<&cE5JG%uw$*!;v86ribT$vnF8F?bPrd4Vy$P*S@1EE$ySrZKwY&z0H;L=?`?<-R;aw z^2p4|J>2U|r&kt|mu83j7kjF7fcv6xycp61FYa#l;YE{nKVAeoB1sC+m>oi-iWh1> zI%kY)#ogt25fteZ`8h|b_|Z^gQlx#m zPhTeV(Yu8-y-QH{P37w)7-w_Salj8g(OkBqi1XR&{5ODx=0*D~@Cj-k>iY!Rc@7UQ zSK@_<_ufgNoWJ+z9FzFDfTMt~%q3HszyAZ46uk77vc>Al6z%^0;)L=*KBSIchIPH( zgW53*A4lzvy%ei?J7x(OpX5^&o-_A`N1W(|X9MV7KivfMPvP*NxpRa~2Rz_^8kg1% zIR7EGzwCgT7S>B^RKg*{5fpf@@!f_6-W)&hj8?+-niQ18|+B<_EemYA)4qQAV zH1nM$WSLQD2jt*w6BBQ9_<2qf-BgZ?cG+;Alw$?!IwUN=^XXmi^hWzm_!zfQA;NkIcS{=K2acu!ps=Gx z&)0 z+Kb%rTG56a0aoJ7U>H8?)>RLWEBHaqP z7^zrn<(3KLRYuc>^J2^M>(-t3TsgmXEq>Nq{^XNS_TK&*Wnhu}?%n&zCjbS48SXfb zSBe582?htnE7?qS_7H7l#0iTxXvq?4wHvf1OK@>C%-0ti01KXe1PC<$*8m2&fN;k> zE_#!TJGndoGN^aBFOV-ZV#$(vHcEN?PXSHxFMAg*+^d{MlmyOz-k@6D2;k5u(w5*1 zpr3*y6BllXCCb|;+-)cdPdB86y9^|mG|H!teMsuTX+lcn?dn+Rem+1WK?4j|H;km| zBf2G(M;^hPT>^MO)6X~Z0QK``y+C|KL-ar3^XmOE{un4?RUPAFKRwSvU$p81(h(;T+o+Ue#lxyf zO7?f`==QW0hu^s2dGf{$H}dL~_V6XvnKQ@X(3}a#=Of>_t@MyLg7#C~8RcE??oJM> zG@NmXQFS(J+*wofqmu1(Sa_W?NHQ_4S&p~IgofLqBV8njUc8on(Q*yR*1b^U-q4#9 zT4HR{pM%jfzHLjytxA;M3k*$bn8a4HRvsHm{r1}(JK_QZ)lT^X<#4W)f9SlI9;9>n zhY)DAQ~cciM*7FTpkqb*2G1vyLkM_#XtDylZR2gfiFU-jak{nT4*jM#e&daY10Dnm zXOYAG|1us6`!;vP?uQA613jhEAARJB}siXyl!(p$^;f~JM-4D8OQu&U}1zkwP zp5W!{;*ta3&)w(~r1rV9hxh4&K17dA0rdEBL&vG3k%ptVQrKCFH?WCe;{n} z&cN<~|MEOcAwrHj7Ajn1!9!#SwC;LPEf#DNjHo%FLz20+NGwa9i)|p$kWhpBe}nu7 zC<#}R6A}*SFBGC5Twon~EAuF4(}QIwzTtV~qv^``NNXl`m^^J4Es7Bp;<1Ky_`k-7 zAxax5J78xv)mbRyFxcoYhf3No*$UnlVsMZGxdA$4)$@<$C4(@}zv%OjMhqenOmLb2 zQ2eoom&@299+23fOqt`2N@UI6ozC=P+7{1=kESW#@jX^``%~zwQOAVjhyZ@8C0TTC zm=3Ld34HAFCY%*=IMG?Pq_aYA-hKw{QCt^uD4p8<{juI++*58l;Brk%RmMhp6qm8l zljIsCv83^#?vS^0dfgX6bUJaA(jC7*-WS9|6lne{#0Z&)V1rACY`5%)+U{6y*X_{S zbs@1rMyNB^f#fed=9dIfyozC%rDI~&Fr693B@r`~+JymhMw7FRuT z{(QUor7s%y67LX$TH+Xd3fVFlx$SCPVNHT$R93UYwxwtDrlLri# z{p^5&h;?eGLbX&pzhm>T3Ir)r&|_xCO!6bb{;775Mn0U0=CGp{QF4Hf8v1|_r{P7W zzQ?#8!^ewp%lo0P{%EKuML^f&AFGik(^!_Hk$S;JJel5Of%*`y4Cx)maug*S6R96~ zxVN9*?qdXn0gljk1hZf7B5vjF1P4At60iIUi znS*1)@lI(S7ORQm**#&Mr}%h&MR8%V_t1EH z7@TZ)aNUMosh)54|G*LtJ&kJGKRwOX4R~@(cGkhv7M(kF>Bx`@f>J^hb}Z~j>R39* zYMj@*cu#|t+&RW+NjA0fSkLvKB`K&S^_D=?WT4s~Gy{3Ph?dMEnt|TDzYFb%4W;(= z)Q;W(1}W{}X(C^t93&QVSa>?93qs)y|AFT7^D( z?NZEzPXUI1pm0z)=o$Yk_Z4XEcFM*bh{!b)CuHq4NJ428+M`qkxY12wMgag z#Uf4{>&!-Th^U2rQ)`b1bw*JD2#)~4U$`Q~{wQ)qjTKOJ3wZlLhQtL>15yhZy@*Ia zR)bPM|6C1A{rq!(VCvVKzvhvt_)ejz*b~*x7x)g!#fDmrriB~gh=S2O2$YVWt*Ybm zzJEaLpy@-;6o)>B(?o|$uhK+y%tks)BZeKdi;@QY?xMqd%m6w}W9pBZkuXf9!|GU# zbXbKhPA{1GoPIj2!q!NKRoEiD{Tk^oA5T9JIDnDBW9Pw-vJdt_{ro@Cj!yy)=b7K< zYgXrnUy+w?)BLn=YJa*HD&3~}_|wee^NOk5YB?mO>8cNTgL9eU6e_xAuSstz%54A@@LBRF6TRfoyPFw(t; zCX>&vewOUK_zdoi&p$&p8~yjD7BD{Or6p0EmLT^o=7rW%wy3mZ5REz9JEq#7zc0D| z1ib_LTde#(_%;v z{9iSaj;<>#f~vGiiDSSQx$=PYalRl!ai2F?%ys0BkzaU#xy*n)r*MvE5Ji=>7S#TajjBkA2Hsf<*0M8g<%kY_p~`viP@ z<)^q^+zJa@;pii?-0jZ!*6ppQZ=6^^Btw|d^Bcu574S9FY|*&vHESrz^*%O}7KT`#hq`p#Yd$%4&xHvSrK2|( z<(1FJ`ESGd8{u&Wb1pPx)iTnt=!*g=lJsv z;J=Gwd-iNoe;TDAh63WL(=K0{Hcjf+Z^)yyl+bF|W2vqBSJ8Znfzw=H4&PYHX{AFh z<_y6IsSYVRGX%HIn_SzQYJ0n(CbBW(WqK&&92ZZz?#r5>X3x;-HX)}ra?ckjXOvHo zQ@i^!Lnx>ApaZ3vT`gKD6Oc`Bi!zxf)kZy;On6zRyKw;-U;D$_3CP_d1Z3=XLOuth z!9K*OJ~4K(TD8lOJ_|_QUEaspvizyA0a>m7oWZ*#s|m}>#IquMT`}eH{=uKd8*`4p ze$UoyrrlQOL{SDf?=+p#YogDQP6Z_ED()OwfGP1_xGQIu*qr5BW_6=?%+hTgeR;cp zrx41ye%hz|r+-t9Wg9rN;M>eZD_<$y55FrJEB@M-9{lTe`RTQ%*cjE5EV9vyOp}(D zJS(I4*pog_vfK0ME)eghoZ))GfjLx?(Sb2A>v$I`Y2>s+`5kH15Bqm*Km3EItF%@r z28#ZYJ&rBE@?uH;& z_xzNo5NnI@N#8D5OgUy2#VzyYnCWR~UQn^VUq55B=fcfqCZ~LN?`%L7*b> z8dL?NoNLb;v^zq!$2fMd2>4Xf@8K(S>((W3A>?uiB^HG2Hr_ma>SYx}!>A@y&KxOp z<96IoTq)15ltlT1%5B@08pN;r>;J=??t-^*ahD@su$n|U@i#ol?MUX52YbUd(GJa=itblPO&h&GLmWap`Cys*Z7@6Yw z_B&RbF)2A&R6bzM2Pfqhk1{~}RMVn4<&BHFGIC^XdPWU&u)U8~q}U^AuD00Y$3PdG z`)Cv|dx1z)Kbg|;JyRc`?I=JnUXJZ|-j^Cbdc+{B)od@{7djv-m6aVBdG@tauXP&V z{KFCCe9uXyh}h({zWf+D;%@!{S}p7M@-si@{4VD>K_7UPT3i zkxB_mR?|9pb{k~4!mh9Wt%i3e$+(*PZ z<&&C>wzAm0Q!RT`8F%B;kt44#S7UOywZ@E3)p^N&(jItV#k@ExIz1=eG)_LLC@Qa0 zF8)@n%a5~v9;g_qNj-3&Vd1iZ!e=Lse~sUJ`aJ9(v?KgU#sxEwIfyr>T2IHRJsSx%Plj8k03EDN8obKIlz+4{a!(wT*e^oPd)^KEGEGD+1HC z`E*~Jz_e}BH`}}@uUG^1)fjU(;HCU+7}Kv6j@YdzIcj3l_$~9tVR#B!@vHzS@PAYXL*)s{s_A<8O z&`J3p|DA?R4X=o&JZ|a1(%aKn5SL}9-uax@E%V9`3CR)g)8uLzj!c|SVHdrbOU2xK zCsvzvK-)&KSn>P>0c^}6&vtSvm`wZ?A=`x81;T?aMe)LcI5pUPZV^tLP=UbEfyn%ch zqcM&}i}ieD8iPmO;`-@ePvn$8{c%#hc)W@ndNQ2D0G@s*2A zzo@Eek@8#pA9Jg!=G=ztq6H0ln*1BYC)onF7q6(y2TAsJq5TNAtv|_D(`!lSw}be1 zYqakL-?ETw6KYAqt#u+yE76LFq)TMLY?WH&v}V1t3*VZ)^^3n9ov!3w7uOeT+_+%D z#*GEy*W&J>rd_M3T)^&zxu@7tX+)JTqkk36F$jD3EZ;*H&B4{UcHbm)iE}J`^;XO# zX$SpLHtxOYOTRpPY})(ZOdoXkgHZdjjvbf1)!ZPav7@t-cBD?DsUGwEw&Uf86lG2V z>RYazs(jW7_fw=-yIg}acao&YEE=e`u^6AIhNZK&||q>)@=2>jp;BS_eat^g2ahhduyo&@X7k>SNm#S)wn2ZTjd9p%olZ?$*XsC%qTX*F ze+D6AY08F7-PJ4X36t^zYBucE`cv5T_q?Gw$lCOYsJ(7N5UNnE{KoU1J7Aj>7%(Xy zH9s7nd6mS#j#p@&NJ;t6x!oty zB3yH4EZWee`v?T`-|V z^O`{wN99BBeK^uR{ZYQxt1uUInSu*z=6XcZ=4Q-o8ITGu)-SbTI3W#dr+NtB`J875?yp+?fEfPAPn8c8fXqxiLkN;IZp1$Ze_V)a> zM_JqF*Ur}*J-Al+C>cVMTwnD0ri*CPz^?FBBXRCji!;k%v zPia2juSki`FpGsYl~bfCzr3LIe}$F2K4xm0)@3~+x&Tq0FL%09OvCsuIZRU8PWCiOX=;xBY~)Mxj)Nf(G>CDi znmvpEm(&{fFIU+$^uLtm>{I1uwwcB8TxZImy~=yr53tC+Yy!rKymLc-0q}sThT>pc zs_FjviEoYGhv_j^`cre02}} zSG~4-={|P+z<#A$ZtDFLH(vkmf3K_i8!#8kQpbb@2!6##;H7J&>X!h7^!+&udkq7> z({JFI6_b?p(m9Wd%{sKNqCy3OJx>E~oOpj~E<3*efYNPWY4^1p0KU&ll%B}LI+Ey$ z;jZCHVPnVnCaOw@oOa?21zF-eL8F(mYwX(otxCwg z(jKcZLuSUAq);2pJ+&oRF%zBx-ZWF^BChKl+}bt?Od>HI$ARTBmmQ26#cdThVuR7oc=1TG+Mj~DkpqrfX zt9T(LXJ-L%P^~1tAOyIfbdzd5X)IyViZKIK)abXc)%jh+Hou;l1i*Z%g z|I3774;<^J-V5J(;qI}fbLF)2;b1~awgcHPa*E6q!=F+vk&1NxgjHh(_9YB_>Cyq^ zmou%iX^vL)N)}^zD)yD08H0U04SHzy@)_txNn%2PB>up7#8F(Q1%1lq0;<%jbm()1 zpMQS-%P*h0f6lax%Ji7e;LXvFGAB0V57Jz&dP7U+>n%dio5`6YB(A3$Y)A*7Gz&_qizKj>h_nW-FG5#0cc6A?ApDjcz{COYXXW`!m(1HT&=Qhv+$goM^ zPo#e3yK96S#=>MX3d=)3jW(_KY9RddP{(f48@?+HArAdFX zvA=qc{$x|HY102Cz|V6Lc*k$<9mgMgC?b<3#xL=WI9{=2#(lG&{4Ia{#Dc_}9wo{3KmG95stb#q?Wc)PbXGo^ z@z(D3BNKM#RMtG!XWZ(nl4mDJb{w;*U(TSc1Y`Y)y@TqO=Z~NH0AM+!^x<`!+5(nX z2@`3M!%yaBG!6)UBtT%SK`B6jL@Sw!XB5VFy8n^Ko`1OXiJy0kX+C#&hoTQZPUtwe zsC8UM=Z=Y8_itrEYiHCyFoC_P?@~S_smI3qM->;Om{+zLIc)T>tRXWZ25lM`;>zzj zKCe}A%c!6Zv!2nMb83fizU;!S{13_LKZW@2$hM$psgh zICuUrMf3PwUY*F2eCK}oalG}lux@~QB{_0HEfZ40oRH$|7U(^+y2PC1G~~M0`fYm- zr!@;^M{X2^md@B|kt8pFCS=ycy?=B|j}4pG#g%M{&h0h!$%^4G?I~N7SnsL1|I+m7 zm$um0qlJYJB;I1;RpoVSpS;r{LzBw0OPKiRF62|9x<>uQ&JF+Z+9vrLYaw5ft;h-4 zA1?~>dt6B+ zs1e}|(XJ-)Nj-1(eU9h*0Eaq--TXN~z6<;u%Anzvz7X)a#`QF%d5!Dw(LCQgKDo&! z2Q~RzAbjj!d>(b*(tUCSc_Hz3?yuA+N2vZvcxUVeo|3&o%Q?D=r4q+Y(#%1+hl<6E zvf_s-MsA4#Du!mIkoAKjXE8@Wr51>%8C6=3f;G42`LGdUBXYIfFOSDthDS;?xd{j^ zx9GfgA%$lyCrdtm?U2$EULjIjb<*RGg%cjv{LwALJ9&1ww_?niyj&IkXSHb%#kaIt zP9V4YL{H-IN{PR7e#iKSwJ(a5X^W~$N z#SZWXMCA%>K2z&3;Y}Yx{#E`eOenx);suzH>zT>|`HL?hy#h~v*fiKh45+%)SaS*E zOTv8M>QJs@MHLQ8;qN6O0scS|ZKqGOZokW!A?v%oyZiUwE$-`E*0*23zGXi}4lh`^ zsd8a{Mbz}Diu{F@RSWWmM^5)UH+U9$9frvHCZL*JU`QnhjtZMnDi6ikQ!Qe^29UUS z7w#yY$EtfpC?%uzIT<4YEf7>|qI81;=PB=7R@T3N83%4bWfR~EDk7(ImmsR#CawjU zqgrnRF+=kOTPMp3rMx=OeVJJzLNH(~ zO9^HOe;>&VW0hA}hj*tbomb`#%9zlWeZivorVf1@&)nD9qEaRI_HDN2#S6v7rKoEd z|0r{NB7keY@%8XNgXV~y>@X=q08VtJ!3r7*j}CImp`)e<^9-pF~|1FJN=d6sj0PwuX-|ZHT;5E zu07Z~tJm5!u@28NyKN>4{xRBfnd-iW(B7-MAkqgx>FBxud-CrT`~q!bFkT1_Qdq+8 zm#-lnd5qrBI@f;xM;b-zbNoe}+l9$DIKXF>9? zpRyAzCp06?V|aC)_->`%@;aQaS_1j1!^y~$?}I6^fT?_Sa)yiPF?ZWxeDZ>FA8Wl} zbt%7jXDO;Rp)v&{&m(y!_MMzCe3m}gFnG;xgn^QKBOLVDT<($u8=qSE`}}z-1n#r# zJ*gJ|7L{!*Xe-?%j0s;woJbU5R%pC0^Dh*>Y6h`TpWCG5&HtOqAav|wF9vu=7Vp}1 z;al>W{PqX(p#0%m#K|1nuq({*_U;RBvuO`Yt(3wUOJY)vz^^lT94?GtVO z+Tfc36V=3u0DzP;1;|XwRvzVxogo_QD`qvUmr-OM&+%*50*YGQU$JMelF!cWWxshV zTZzI>>~k*0q#CWbu|DUu7*u)ij)(=}RGUPQv|&ss+`Si7QxDhI=O0;q@M6P%e_Q|1 zh*K5gUmmjYwS3e}P4(4G6_@>G%~W~|Q?1E+)doHNzt#o?PBh_pR0qWe{$JJxt-Ae0 zAV&)*4GPM0>dvRocP+qP{JDnf>HlvvTp#w8C-wZ>U$e9oYPh!cmL?VF2ePtFD1-%g z8f(fn6Y|_~Ql$|UWy7hYY(#uztXfqzHa<=*ESto$fWe)c++ow;&wT@haFBwlNxg`> zowR*!-uAyJGW+~f7wgN*|Ekigyp&2rF5&m39%mWJaWmbm4Yg@i*Idel?hfUZXL$|U zN&_m;p78qS`U=ke**RC0A+);s(%ODZhL6@&rJ-zR?~-j5hhBUc49P7grKT$9l$-c- zF0kON2wm)Kxjo>BCw$hl&EYRZZ-hn6(EFad1BGq}RsibccWWhc&MYiwn)`fiqi# zH&ZT`+eoA2liD;OU5(b;0(v3(#UqwK_414vms!_iiOov1xvNXMB^4BuQJsLki~Qo5 z2}Nx`^qP0~^lz2wFK$bCLiZ>Ka|ZDYB8@^=QlS00>1A=U4pS#jnLd5WWY(oy$?9B9 zNwdTknk_0j`qtZ+Hqk$Cu5sLEKK(FgAgnT>ZQ-2R#KjtAd*XBAiBM@5 z{(9v{=E5=F9(HEZ)Kfzaoox7by*R>haLxLM#Synz0l<$<+Q&V5a%RTpkwz~GP zDi?Tl(0q;}?o(>Bbf?O^yehBHr_|xE<69YWA_ld5sg5uADuv*E>z21tFZU`X>4=vg z;Qrt^g&dW%EtFz>g?gC=DEA2!>czE1onFCTr&oC$K;BYLv4q#2IDk66DF2PUe;)W| zAbd+A%NmJ%nG$&rfoOW20d%nNh%P7v81T^rjg8o;r%p+AMihRzqha38%Dl4pjMXb9 zJ3mvljp-I97MsJ`E2p>ayt47_!d#`cYht<7@YS4cHKS@@JlA*RT)^;;2Pf3BmzpPx znRtjaOiXy@&Np&%z>!XrBDm6MsnngwjH+{HCRZlKSGKIl3=d8YwaGEIHpLl@{;sND zD|c-rw^pA7gewBsRh1*Xq6s8Q5|n(_OET5Nz4euO9o@Iy?K`Yu(!{}odT!iSQnGH} zg<(_BsSu0iIZL^d+*jt@jmCasrz1tj(#p7ank6%)3yvQC><0L^>ldnuC*gps4(YZ z?`yF4@V=tMS3SNlGk*5PTJXvJhF2h<*YL-r72>$2ept{Ib?J8|Mk_xh5&E?s)8 z?A+B|G;{9a@$K57Ik#iS-hH}s&EGYwhv}J(G0}Zo>8m;xysyasoTa5x_f-rdNUgTE z*`xdBUwj+QSg~N9)%L(9lVI<)(m(>!F zGbU4{7vi?bQkub;YnSpI>pwTYLx=cH>(_6J@327m`@lWB-IB~DioO2%bA)FMd6=Yur-7VpM{>c>Wg4~0R zUS{O(*oX+eiqoK0p;nLrPA$dnN=nvdM7EEKo;dNX!nK|ItZX-bTH>N1hu(ST(63jf z&YnGO!Zdk=%j=wT`~2-yEAOg3{WZ(?e8isqP#OKtt9)M{BY3bb16dZ}x#XScp4G1b zY*xIqSo!VVrLX7AJjcEk^SqI$n`**gC%*NW= ztUV6)igL`Fsf?dF3;R7@=_^mc`qX$3_*k37gf^nj&02sUW`#g7zvGs;gP{ zUN(u}Yj~Z@LD*vx{JK<+KpKM>q8xN_U-=N_6ZYYd@)zOAC3dLt{ zp@)rk?%mQu%0u1>x5*=_8ct9>bo7TUMqU6tXEGr6Nmo!f`Z;{2lLHQH_m*%<5g%$( zQuyIFd+XYysWtjqK(=K6npIJ}p%mr&22Ntzw>B?Af$rCWc&R?ExM54f)7b@uDBy?u zF~IxBFlSrL89}!!(3>1M3FRiA5W7dr6R0U37&i3ES5F-)RKETtyCo@C|M;Wc*{yel z*Sq}MKYoc|tF|=!w0rmJ9(ZzM4?qvqTH}JoFFw$y{>&X1B#gVJYo3I=0ez;q(o^0K zm;j+4B6wiZx!HXlS|EWCKX{5DA9-i-Y=23~!IxG)c#|y`UsPTgFriOZ_fMbn=u@F=`UCD-cZhC=*4p`~9Uuov`+OmZvoyo}DUcI^p+__*jL_JdM&15cn^Z2ws z`Lu&5;JW!-+A|X-mad<+zin|@{{Gx;x%>CK#uoM*U&TGz#SNZiq~{e^c$SezySU=^ zZq=im&x8B>e=(1Go5laPd4B&uY{5&CV?7ga7L%|ZSe8_O+X$50^okLUSKWW-)%P-7 zopy0&{XN@X+~2=<(^BaDTV?xdp^rIzsdn*F@!`7)qK_Ei?vRKHX`M$fe=p1*hnI|Z zV({hwuOTnR(SgW(vuJ&`*d;pp#f&bU2k##==y=75=^fo+S58rcjy&t&xXjFX^S|;` zh`S!&b>Dq^`S|NGek{g!kvEd+ebhuzZx490h+nly8$QF`@z}As|OiYp7c71+f zn0VyzK7BAE5{-;FIBqOWQo@Cdk$euIsN4~A80bz@`~m(-+`=sE`dQ^iCGo7hs9}M$ z?)DmKUBd#>-*Q_E`g`L91eZ7V%W6sD`VNStq48e9iY;UB@uKVO;S*x8Ipa zWDs*4xbvBujP*FUCD*sf7Lp4KKxVm69m*vXTu;ugAz52;Y@|b$mgki{xT>UdaY75n z9A^vHl6~np8}92IWwAtczHe@qT=!&V|8{;kQ)*}KnLhhV&@W3KNG6Fk^ooOy{h6qcc6%IUz!qnCTQk;{h;$~&YA%f=?t2IM#? zgo%Vfi9`tkRt)=5eB{SH|A)Bu0E^=4{>SIe%F}n6oj>50TdAx#e#~8 zs3`UtOQM1$YAlE?#+bwqdqFgb8Z^d$#+Ycz81WL1MPv5;Vk!FNVBw-gg$HYTckJ7@qh(-B-@Y-L>HGILw3$<( ze4*UkHmA)mFTC)h*P?9*L=31{H1XkjS-pEl5Sg_Ez=TzoGK%VuwfjR3(=6UC_V(?Yq+bzwg@Kod|d=L%-0eHPPE{ zq&sgG9SkOE>F^N)#=USttq-pb#(l|>UGHD~nJUD;rVfba!HUtITDM-+(Y4r6Hr?D~ zh2|UDYwbR^7MgE~>4l1~PTE zcwdhT>!EBdM+}6x!iw=)N#Chw-#wX=BYs7%i9>f3>?#;X_)k3PFu>Q7#|mKMl42D2 z#Y0jE$st)#T!xBgA>z%%__+AP7x$$lCy#yk414P1sZ(ZH{HNdO+5Tlh?7`%8?Eo2Iodb{zrc#1%mtMnq!h(-Au59YN6&-yF=X9&EgqT zrhcp}KJ)U}_)b(8lE%0^l4_F@>bK`xP5ndQ4juru?bLBlM!R-luA%)iR_r+l?i6DrztddscHnny=Ln^_O5n-~;L`i5eD(4PO7h^& zB`dkM=5XbpN$UFB-p4t_KqZ^cKr3qqO@Os2gB|7`IoeZ4gAQ2%<{8k41`f(CmTH`O%-e4cVS@(qOIv^iDT04j$uW zXlWk-gT>DgaKdC9Q8Di68nJ6lWo1pz;lt;=@s{|j<*n4z#aoAEabtjD$Np06U>Z0$ zF*fFxZycm&vj>hDqOScIoL@814=n3YpOITUv|3gN>g6R$61!sAX!*AYV=Fyhi+%2jaY9Pw{y$zVC=WU7+!9~1 z{4M%0507NuxUz+o??j#Agc!|+PhKL9?ZOA{2VhGSg_jyP$&tJroI*ibkC3=TdL66H zOi=QAc?Lyrt+`gLk}4%-n|P7}6fBuXQamW6kwOqjg9Fn3TyVP!k_3i~B*KFRi+8?R)({zxMyN5-t|Pcjf9F-SO? zw6=7}g#9^5h6N8JGomuAYlF3P)f!1t-gNwM3m(@52C9bzDyy?|Y3GM^?K<&j_P_xH zG6xMB!razOn>wSaUJ96*Ic{b5nVudU4u%+vyO*4;nl&%LLjHLmDot$zMfkarm_UbX zlg>v+bU-rJRn3@MQqJ6l3>uUl9yoQ!dr(7iKnZFep8@MK{zNvWL*P<=EH9B$TTSE9omOC@^^k-yLMM3^YPzFr zDz|N;U&3sVn?NBEzzXEZLM!Ce^pO@b9luuP;Mv#m8+*F6tXs#3n#2uUpV2* z;Gn3^!9hJn2L+4qH+Svcz3b*jhVbCm)EbEh=1jsgYmC(RF9w_K872BtHAfS z0ljuId;1904uSU7##&Y#=wkHL82to$tr0mQk(vV;D#)-$iHo4+MxrLGGW#Dh7lGwr zJ3k#YX2j^b?+wY#9jZ)V>yKX;S1@bojW?9>D004ia@xp3R;zqFB(3w%m$#HnUgGMr zYtD`X7#Hb;Kj1oH4=(uv1U5RN@-`+YfFooB!j&S3Fr&&frNbcjiLtY~m{S7Rl$Wmw zOfe_UVY%}u6lUn=LxqLK2?P3@6Bs+k_RXqL<|_wkQ^jFJ zp(6J4g^GCCP~dd};4>9?5#36kX%)^0yPNc1JZQ6(ep7sBHf#XTcinz-(UPT$KQZ<7 zc1}$xJGXp5fS>69dRpSDjQ;&IR;^I=oN}!3*}cq}x$fO<)N0sAqrm{1Dz+4d_pm8E z0T(80#CS-SbtHPs-4PHk18KHS^slS4d|3yHvpYNgXeF8K3CHR{j{!XVrN)PX5rH>o zOKt>YH6&QYZ*fOWP0h)3Zt;Uo0c~7r!8w>t&6A`>#o-2M*ysw>MJF-W@~MbTM(_QB z0p7-3H0oSDg8slPEby9Xh=Sow6hbie#els(w`*~RA|hN3TWtjK1n-J7#*{3pQzurFDAP1 zvNegw-~W>LE5);C&6>@&;U^!XjjoXf-NrWmC(VS+N)9gYviNVb^P6w#zPk6%^z-I^ zW zb^t$g*!@@*?&AkvIx-e>_uU}qnmFV|$|41PH?RYRM75<^y9*F|3!UXT4&gvl<>rSaGbcFYx9h z`gRt2QqL+5VhI7?Fq9g7Y{4M{2YJAz$w_|;Rbq?tdVOqc-Y`>atZ7(YEJ_JZ4~dWO zzc4c^D|2E0`1p|NOmupXmX&OZsXovpImK+6-+g9sN@CLZA|@)OH0Y+KAJbrJg&}+% zI9UJjtjAnrAp!hKC5NLUvb&pFK+>(5Yw_^x0BZqQnFy=bh+0p^U;=8v13>$-3fZL+ zTd&L#?Uk{UL!T;RSA4{g?4yw(#Tg4KD;H!Ghm^2rr=rOCCNR4vDQiOQ3dnf(kHD2K*1eyE|*-L2*XGyXx7(S%b~#(C%Z>YNXW@a z9v(I?I(Ey7gsw@crOU<+8Z`aOFFW;~k~%keKyF*#;_ylNs~2^f%B98JTywu5myQ{k z<-4j4hM@3g-xCW|S60j3@&Q@#@xviAhPHPN-D(vXfghFF|CBc?jO(o+>0mE#4i;ws z>8q^fL5jXtnR6s)5kU=!&tT=ur+dog6;Ji|3lKp8;==~``>%g4x!Z&Z>;UfJL@JN*~13rB?emdt_hDII(n*chHM1vI^#qz1AYJxKdhU$ z8=$Wj-EqfYknEYfKANEkcR%jpp(DK-fz`z3+#9jm6cgP!Dk>^^YI1V2EXU40!LGz~ zkVfi){ALm~nG)J**uZYLvT{G|)SE`TVzms7bfz+Krp@g`D#{IxU1kO7!{6Zp zGI{r3Ot+H&%W2ALz_Bmj2&{x`+XS~3MjR{gY7(OTS+Z!03zhrC#7wPRm*(Y_(SLZ+ z^phpU#YLr)i<6^HiqqP~C#26#Nk#$ZzE&CvRqUQ~P{c|%8losqzZMKUIvo~!l z-?VY|nX>JbWoKGmh(i=F_8om&){CM=(R6ElO??Q5&_`R)Zb*l2DadxLahgJp{K zCmPFR8s(8ZQ~izU;jB3hp0_RL=M9}qpbx73@(l$o0#w7QnZ%$KpHe>QGB7N@Y~k4% z%h#+K@6SFIFTn}q!UvWf%Efd0#RY%g7stKL+j|pu=7jcw(YUP%t*TZaHXSq@o!Im# z9_-wf5tF8i(WwEE)1qS8z%@U3d8PSBP8-KAs0}}QddtLJBPV@x@NM2Fmky~P)*W@w zH)>_*KLX8KTLmd%rxCTYVje`ugT2B+PfTwJ)-0%1g&(Z2YdGE)vNsXImO+=!rDz-R1y>vqc@8NG8RkU zxeiFq@6<`0rTppPp7z`;@c{vif|qwxXNWmW*dXr0{?U_8rPU5?wJ9~OkL^2#z^6mf z1-yq{2Q9s7jH47B*wo^hm{9{q_KJ=V^iaN7boThqcRyg6FO$`yL=fO#FR$ zHr9S3qQvX@^>yhjsT1l6Xmyax@p<#LKfnG(t`+ZU-@x;`_!@jJ{Ve{5eMY+QxOmmy z6u-SZLEG6Kb6%c#W;XswKX*&bGpFTsOU)kmb#^vh#rn5=7pEqPOzs{$bi(8={x&;% zz<})8)PnSLcJ|i;vs1g}rJ3`>l zH@9&Q-2*MF#yROLhu}m4U(ci<$t_4MI?g7XIHBwmKL-7XQ1A$2)#69i=jbW^2z|`k z{hTS{Z*mAC-o^`pf}Mr&G~X*!@1YGOLzlKlLrDIGFCEEUh&l?17X!B4xwGw#IEQ}T zf##F?D+9Lo7w2I90`cHde}MC{na#t7naz2c-)HUJJBx0n z4NLP^UY(_>|F z(XXhV*QrBdLSSm!@LmB6XT^8RYumZAtLsV!hhd|l$#~3ITaCYTT$_mKi&xD-f>Gz< zC^MtZ)loKH_0h>!JskazbxhECWP9qe?T`x}8X{{AXq>p>J_w_;91YZYVM_(sj zXI~dzS6{ua!Pn^P*4DkPM_bP}UOv7kuFcdkp1Kfzl2aHC`Qrd0fWKJS#UsciJXBoF zCgw+&!*Jys5z3bEE6s>Rcenn7R&DVMvi$+D0Dto2pJXpi!$H0TraZ?!lV-_CV~>k4 zZc~S(Lh8wQjq;p0r6xRl@o2aOaTzs4? zFfB>N@YOwa{5RzRw$Q_}^EGA4YilL8dKr^$|9x_~B(1*iD~q~wM_F@tdsY^0eXQG1 zoTH1O_Xp?N+8;-JDk-V#nWC9zS!Zc!?>@ukO%=NiQs2qPJ99NrJPM;JsjQVRCroYO zy3;HQO4%{RNyCPwj%v3gHg0Em(xP7GCEarJ0{y19pHi@Xg}GGYJl4}QDk`+S(at-v zL)Nf~?ru{80%AKw!Zcv#F}PpeSOdmuMBnED1KQUTBVvn;mR^a{u}0=x{?4^>W_(!o z+N(H>uPf&sJYaoUhtEH!d5*?=v%sg3PW%7IxgqEO59dZl(6tvdc|_HMxSdV%S6syf z^1EdZp`>KY_PNgXIZ{L83HEE5w5yE8;h|Q~5EnzqZ6yD)GPLuHSoH9KSX8FMzC~ND zpJT5{yB;23agRNRF@>Q$-kN1~nf&g<17*NV;eGHD4O(|2!g4sCu2&qSUX8>%9OBnr z@=xLe!due00FOVx*?5*;&*j(Fvl7ow;@8&wkLv{-udHVbXsV%FtQKUHH1#*H}RtaKaWaYq4+&xB89HkO9OTcUQr zO|xs)wEC+U0_K~hNtZSeo#&Nr!B5M-NlDtveCOFX7@R2F=LC8v?7aS8>zH3`+?Jj( zp7TeThiWfZX*A~0oCG3&3d}IudR40prpMVP?otXJz4xouHFs zrqMCUj>-XCHBhB4K4nxXA@PvDMX#zm<)YJxzg82Q!RCV%K>N+>Qbe#6gRzcP+A4mw z(Lr8Srma$XvDehG{3OlQRv{n7Rsqw-nYy(x4sT&x!h2Znjo^i7Ts+1x2)+>PscWnM zLJrOH&uv|@`RG$!uiIz`xFKA{+~(jnvz?usws3;#6~aXk9gA|@vvJcN$9XOVLxvSN zYT9FsHqcs8-;CV?ZU#dprt=uqOYzdruRbHaMdfZ8`x!j$7uq+-&dBs3@t!!-P2$~O zXUzCjb5UtrB$X>_8&+PJKZo-_#NFf(%zm*xr>t5;Z2_mnulXDW4$#2Mr8{V11e^aI zPs7+Q3;Z&aA2^hFloxo6%(AkhO4nnG=P}xhj9s-bNwz*i3JY)}VlJMs96!dsw>~pV zvq~C`nxDiOk*PjJ`~aS--EmJ(v#`9u>)LAa&wtSnWEj$9)51$l}T=snHGg&HX zePZ)*JX9RS4;tSfIR<(E!@*Ce9KHC#sHICsnfmlmrjA=yvvgdaSW_Pw_c+UODbqS` z)!E7Q#)%Lt#sNQ7w8>ou1cTV{&^+5*;~S{W*S zqCQUnE={6meDxVhMtKd%D3@)q1}dRDk-^;bPGc1Mb~D?7MzkOiAT=5*iMWBSBBBUG zq4Z2+XTCrD%+6ZzGg+|HjHOqwXHmtRI6f*WM6cnX4`JrII#yO!_g-CH9p1OnTh2H7 zpK^jFFj@ALZ+j%a)C# zo3VY;O>ya1MS|&e%NOETjma3Rf%G6Uu+d73uVQ$hCJ(T|-c(+qXV-#PY>&6xge0WB zcW^$-P)3kx%=Uu4-c8UimWW@xc~wtE;2tP%f?;H4=YEKOpUf6Oms-iRqk?Qm*~ABg zM~JT_#m}GHX;{bLjHs^NI(AH*96dbW$>~XhYjo#;VH6sUJ$D#=hfuZ+alQksN2q0% zc!;kD&p-zu3}IA25E7*@o|F$>s;5{vz4_utc@sb+qRW$g9AB- zUwg$@I?%Woa-omek;`taL^mumpwL=6Q+%z`8I85o`&_PUC03%$TNkWDE6H)1Dma3M zDn8P_#-#tvS*ZD+&cZ9UqY&eX!hH5McI9;0N|9BDSK8O={8W5xFM+?uJI5R2!QZd? zKfvGrzhu>wJR67J%&Ie+OiO#DHNSEjJD>QKRN_}|YyqA^#`KqOC{)9<2jQ)H-8c&T z3w%&;od?a$0?7%Vk0tyO*0W18@}8k>&|MUz2yZBYkJ*0ynSjr3sGlK$nTLD>UQYY* zjxA3D-tmfHUTa6n4xt9<7fn3C1v*&w_^8&~U zVt_XpcAMp6wnzElhUH&kxH67;D&NywTkJUvmv-WZiQQbCj>GTMiNzz=CnDmFuN+?P`8zAQwhNq8Ab@cl1 zpLk*{F7VDL;0+#V-=j=2(0P)vA9<#U?yLC}cqk>=1|mf7K)+|oa{4Or@xJPGL5PFjCi)bx_C zgLl-4b45NKfi=2me$kxMC6e4H1Z!knNL*M#td|Vvgo%4g;DG%56LVR^z3;wa4Re<& z|JEM%@p}4~6kp$zU!I2boY{1N9Eac;%Iq0hg@S@#vZxPTL3Qiz-Q z6+Z8)xUkTTSlD(9;$BiB-frHY<0bTZsVP2Jq|0 zd4A%F&+0xx*2rScEnY`^GXWRq7UYAF4Z=mllVR4^6(|DH-gjb@_?1+E_8=3WdURVn zH-JC)nfjci7u~1ot*|@M`**DOkypd|yq4epqUH0Ar(mBP$?tz_y^ns;&WxsUphX%- z!&ctTJGc)f8SVdSeg5BcpJDx^>ogw;tAy2imq3a6gi$-l<)np27G1xHYvh)|H9o=h zhq$KNzgmeHR?+r6{z47elTwr%t<(R0FGe`2IVo1iQTOjfYs`8UrjfBUT1gCJVKOj4 zfB!zd?e2%!Gffcq&no4da!y+HXaRfsk1Bb=qt#VN)xi6E6a7(cDaz$V{X@G;d6#jG zgA>=~xbDlZq2B`r@Z3$v$0h;We1!y@Su%>-hz_xy@qTd6LGheR$CpVARRGPdx(c6d zeyl<~=I4ysHmKE3rDO0PLRx%~7iGd%GvgTDTKp|VE2V71@YOpiSFf(zvHE=~Z1ZP> zkRGFmtXUI0wLl-L^ zsc?>JNVyFb8Bx&uHvq|93|hr@kS#wELLOW?tnnQY%>f?Qj*eZtXza1gitFZMV;3zN zcXTuRb#rEio;^Ec)@Mfc>J_Q!FxM@A)(=0-8sRp(s%o~|2>LtUZ7$a3d3|KB-FtdP z>Md`JiTHcZ?p~2t15h6M9G`zOUjs<8e7gzhwW4hxEVW#hN&D20_X%vvYr^lD7OfWln|7G`QfYC)_f9r*)l%Kp} zAN&*z;VfK44kk*E;4UH=cTjwSk(aj;J=~369{rI+p9TK%8w)}XeI*7t^mpt)4*i3x zSm0|&b~PO}=&rn`d`=nkS-;P|rV>40f2N#927SPm?|a<Ke{}OzJ{YDS)5F}CQ*y-4~Zdv`a zhOF#6IeGm4Ywheq+6U&9jLvOu=sdF1hRZYOKC$6B(f*tJj7={;eS7khTT-O*It#Nr z_eo6q=v}#ydDDhRGI853=FZx$uE1eV=Sv0T-m%&s#HT`gN#+>6MmC5#+0CfYN{H0K zb-auSgir$;bcS7H8`vw%QWI`bNoF*4gOstz~??-Afxa)-&Zg(0TlV00hXk_W< zmHcy3uP62#wG5UgvI;lM3x z4hpO~acB%aL^(1XJ&1PF(H`u?_cQ%&zt>5`vMn>kQ|dYS~2xA?jXJ-S?Ir3TlXz?0W_^)z_k= z`hi)myew8f+A9~ds%B)3QPkXq9?XEbbul~I3r3G#4t7T0RBL(p*ch{meYN1S&KnVi z#+}}k0RmN{yrjQh{j+c$HWq1=9)}#3j{7renj#vl`TU4Kke<|~^<9s^Mx7XMsn?n* zsL`za@EwnMd?2NKvAVKy^%pgF%6IH2my?uv%6esuvVg5-bJ;A0W0$FW6!_*U_`@|r z(7HOK=Ihmlt1)JsbG1;5LiF697__umj}rmGU%V6?I(7K;lR1OfdvbxL!=}#288PlA z!YHt;Sm*oL8#B*BKnAyh`gqvM)j#D3AiXJ0#vq7FUS!MU?D$;v)N@f7Fhc zbY|2{c(_waX}BcEUS7)fh&pQTqLM4`kqdA>lKz$nv(a7;j2m$bVB)B@Mq&a80(1IeaYHjUUrotvOY>JDM#zopN)67KCKWG3#RzT|4SR z`iGT{RB}&lkPB)o*?rSAY^Af)lSjo}4S5p9IPkhlzf70~QTwv8Xlk^FWo4aZl#M;08eM^#8|U~zk^ZVOE!A(jff3* z!o}B14@G~M7_*~pox9*t?OW?^-Hoxd1>xOpBc-tWd6J7>1hMDv%?R=k$F5HAyK&w6 zjR#XceWzmPhbX-{>sL{dUdkSP>((cqJoESRP9FP|ukXFIlyNd>U%8^?l%Jg^WW=SRL8WCqs2pqDh=M-I)(>JzzU-qNMZ-#Go&;wPRc z+R;5GGjqTMseY3sr)bpYpN`Mp{nUEpW992@+m#Zwsd6U{`i@Uc^LxHc#;kK6O_(Ge zVV(Kj8;&{6SNEOeI=h^JjQM*8`gq|Ci!+B+Gb=2;d zbfxhjTWI+}vS(l6bXJ}cJ2w2T1U#`vU6Uu#_5idEZB-angrb*KhaB!sLs!I=!tRom zntNu&f(@rPELd?SH#P0_I#2Vk7m?>+{zscuGi5s4#8z+mNG!7~eQ}uCQ@Tm?D;=^q z#i@gSF(c2+A09#Gb2#L~l4F3GnvlR?A~#t48KIYC`zK>F&JJ1O;l3>IY)0&p=bm83 z_U56%K2<)!L(T1t>+Ju}JjwB3|W^`Xv{+w3x!a~bKrTngw z>*eFDf-SAPsjRrx7~r5-CO;?3+y9`+io$G+C5Mj%6pqoZ!$<&g@)%G9_C-oHgbW2< z7z#PfNo(c!{*w;2ZL@j6cgm+Fzxa1zIj^i8!&V9g2HTR#`$?K z%G&437j>_4$k_jgJ#q7jvQ$}e`PQu~><6X{F5b2K35=5NF5uQIZeFT6QS{VPqt4YFpS*JA=+}qF=j23=tr-?K zXiz(_zMH)lQ0f4em*%!%C=~BKpVA8a_R@Tx7rgqE+fN&_^HaDi-&LOmHX7<`j?BQ-sxrt{%PHesm#8`P0O8$ zStIuDrSXZv9IOrMmVlN6YlLQ<6C>KxT!C6=kjkyCkeuz z#c%$VHSXy0g~M&)MPQfjpI!9qS{BPDXgbW>u3V!6>$$BZjQTxnH!HbztP1_@M1SqE zw$xt`IwYBuzQ|VEvPWduN=#_aAg)vjzgr>Wlohx0VIz+boLa~1$sE%;ZA0rBP_ceZSn7!Dlcanuvp3AcsN zvcqKsFUO2Gh30ge-!+4ESI(~;cc{z6&M}42!^}DIioH)48jbt?{8I-_SKi)WNqgpn zSstGI+XiKf!F&rE8|3AHFDb|+CehjA0dOX|p@be$8JySb%M!`y`v~72PkudUjN1;2 z_Mr7|d9{+yp0IQ*h@2YodU{SZ`h(XdgxEM-|n;n^U}c?WPd2;%_uz|N4M0eu5Y5P}~RuZzgDXoEhDgebPWYFzG4 zq;2f+;e|VQe@dA+qW;|(>vm^oGA!%FehyieCu($v#sAgvx{|1zV419r{X2hP`VW@N zVmuR%6;#K8m@#3vvJw2je8H3E9)gC!BcSz=c!cMo>kxf}l>PG=R_GF|q@NMnj_dpy zq~G7}9GrcifW@H@?S+sm%e&&yr9n^a|LBU6t$ePOv(XP!yp3!84K!jBj|0Kh4+)Ns zQ|rKUM;G|oqR0m)5vEw=?&fF)BH=;D2?;0ce!-Q*;6xUh>OvI4oZrTm`TK)J;HGlB z`KI!vKdS_J2p+hD*{@mHH39S?S`Jg*$j>4If!oTT&9_-veirtvO^)yo0->28))y4Z zTCvrLO%xPp2u1Q}>xMp8viw7ve4t@|?0{0Fc#5~IQiAA5Qb7wrL77!0{;Rz;xjbM& z@*emZ$O*vjbbd{BjP&F;C1l}&W?ehU*U-+i5RW_MlmWXSCMX;*?YwJKPkT#yqf6 zNNoU+@Hjx(J}hi}@#%?UjN%KHeB+pjrtv zwXXa=rD$OPtYy@@C0~4jdM_RyCLMm>$qs#3K0+VHmwcMKc2HscHufA8_JHkP4r{*F z+P1j9z^~V0{xOk|-(kLIzNq~24ERpG_h_$loWHl9 z&W#~>FBfaz&8aLrz~IorC9q~R1er57qad4iX7c2cCvVx%kljtTqMvek#*8ZQAWMC! z6%Kw`C2qE%pjy8db0!;GBKP}Ib4-E8z@v(%g$)W0U)%5Hyf-ghdUI%1e`M@O$=NjJ zqH;HXU;OoMW)_X}!^EP^-LAK9uS|l1cB4`ZS`FN`!82TnCH@FjI#@)S@9QIk1&!nJ ziB?MB_us_&P@Slzx>(YH7WY-XZW8Hr={{_p=afj)4gZkmZX$G{L@p}Ua$b|OsrdP3?(b{1kYH5HpVg9hXULiVj&)rmW)&s z4}Q`&{B+FIt=}<8=$D;$!c#DdUP;5FnI|G)i7cwi6pIi*Skn-k%0|lp7^VIUQe>IoFpUg>NIYs+?M^bItDx%;!{3>PxH{yjM;o2csMz=;+IS0RsE$kMSR*|IO;{#k zk@cVQ9w8U7HUzOFMjwWek65x`w1>w=B+gJaTtDbtcYn=X_ZOdLE?Y&#a^MT4@0Z9n zuUxkL`P2Rl>^U}!)WO&@BnMC*c3gi=ct9a!sG5Kc3)fV9)9O;#;2n|uILhl`IaKDp0<+~Uz_NpKj`iT}a2p95FI=Hfg}r z3%Vpfp~A_&!n2H3IJvt!*@?2?rHR$YI0ylr(cTpnN7- zWf4&(A&8ao!Uu3!?EM2o|Z< z7$N4x_ZU9X2;S9Vj2yt?wCEq^v6E5-E7L^5UW(ab-+xG@Rbe50NJefEJk&YVNxTL9 zZyO=n?2H%n0j|aXXH9^eFFej}BVK?T5*-Z{E@iBZU4^96L|u)&9}DwmbQpJ-CTxmz z1EL1$z-CG!7!y;FoVcK>;mxY7=!gI*w_fSt=j#~7Zd57mtOsCwAN-YoWD4(9DIea! zZoKPf=ZWE9UYyo(c*Ew7dAS1KwHTk9FyHKGM*_V)3qX=r{q2;7lnVq}vr`W{jVKu; z;iRjBHYx=Qq*$*m(HVpD%=UI+_I4T_4757Uk9xZwhcmOAvtWmK2v7kWJKO0sZlXR#{X&frD&HI;A#}7b;$X{*4J*YpXJG((_pD{Ev`8FbIfS{9z9W&-5t=OMAK@6$?5di5BMG)On9sw!fP+GzsS^K zr@8gWBwu^jLB93~$`nq+sIM0L0lS3X=lhDoTh)Kb)-kyXp-@8xII#c+Xl`y29stz# z+6s+O;aKLPiAquNxdok~eZ;=>s<(hRNuBG7B)zJLO(Y3?KnJzYq3ENfKLCxP$&UhX zYGtpdJ*$2WS{Y!r2ZqLI0)%Kg4iq?T$`wMHR;2Mn+hT0XrStWc59_%P0?KgM@T$qi zk3OttF!m348eBszZ??aqPfkCuHts^2*|~>Zg|5;~U*_R%r}sc?7hDqbP*vXNNMc zu^vX|O*U~dio^2H7s{nAtFZUhl^J}53Rj~cO11Z^R`H|G8M#OG8M*mKJ?MuIe&n48 za~s%r0R%w+gCB^9A7cW}QilAfP<^|ZJY?d3G~m0!$?g<}dJH&BB1Gwhe*IpkXO7j? z${+O)->PBu^>l}&NQ>Ise(TC@dFet2rAldp;{Kq+_U#Thn;1C6!48k^wz+-ft=nw~ z_E0Cavi)a+CT+!B9f5;Jtytz@Cs#N+2H42~S}8z)GlrEY!3X0iRK+$rPQ)mi==dsl z@NhDIi^vVZPsO2LXp>@+^>7tn4rR_R_5qG)Fxnlcbn`y^JJ2B94&AVyxQ!zbe^~Q9 zm)Dm}o3k*#zJBhuCr%%cZo+5T=lN{^-s1d+9mHq4dR?MEW?~+wfQ)g6n;jej9PDVk zjK+IgC8Bm(N3jf(Vdw}e6%EQygXdo`O&QPL!Iy39v|E^v(nO!5%+A=4jsf<%01cYO zrle*YICXZ=+KXk5XxW8M8ghV0;b3WM9rH-xtvADl3e?!(Ba&1{J}@}fJcLN>vRI>w z5Mb}p(FgI0tEY54}%=w;)B_tTiem& zd<;NyEyL{Khl7(e8eJLCHyH>xOM{83WsIcf>l=3GPaKf4U|xP*U4AX~{RR<&7yBn| z;{&*5?O(L{{qQ+=FniloI0+RFW%eGq!tJ=e!eg5N2eDR6uamytF^xSjz4lHj)2p!+9w*5Vx?WXf z0Hp*Ndv@#Sj%}~KUNA;uDHCS}q>X#+)$KcuGXK5LKD);stnTJ5-&8U8vD=qi&$)Wd z5?o&oGLV9^YAfU)N9aiVnnS(4TwP?nr&OWe27af~uMI{SQ06BDxCLqge4N`j1^Bhq z15<9s-q#~YcTnC<-`m51HBt8(e$wCj>34(~;!I}EdPO5MwE?%QN>!o+HWB$_u8)~A zWej~=lBPSnT32`Za$Wsdhw1h8;&+d^x9w*=*<`L-TnLBRVwPo@2t>lTAz5(WEjwsv zdYYXb+>y>Qzz`$EI@^2cZ&FAo`XsKwv4?|P;i0K8l)2f{;Xw(rz%!io2y^fZv$uE9 z>A^C9V*n*Ua9J?e4svY`#RX!-7@Pg{Cg!UAy|F_1h?Pz~&a}`_)+?VW`{b}yD@0@Y zqY>hch~vlK`waA9o&_fu=p3&bjGB~c#bDHW2aNk7cGC|2E(vDm;1I#+0>h-e);+ZY z%(FQ2ZxTxAb?Xel)gb}Z?ZkDC=M0q{2p8x;)}w}n9*P$XF_1x$vjWpC0ZBN>eG6Z( zGkKA-2aX_VCDPyD+qjPTTei>t>@#u^c%)%WrxD#l^IuxV{7fO~A*Nr(^?%btjABQX z>|38m%PBwdUFg%_hbZgQ$?(#=9M`S=&J5}9B?m;W1i z%F2HpGhxV-f8Vp^DXY3NX8g)&JWrXVY@U%la5Q^Mxjv+4&!O9P%$UC1#ivZoQ-;F^ zgZmZZ(g>br2ccT3WwM|ZwZK(?7A26tkz+kQ*qIvf7pblxK`z*a`A}}aFL-W17f>eR zi?yPw*2SQ8(rE37HWBz$;-s&3u4S%v)&GSrHo|605|=ybk-3|spBHSiblTQ4F;KjJ zMtREJ&Lw!8lF0%P@o2~xWR;Ez_|kRX~hp~ z|Ct}I{ZD?_i}+!${{#FmY@;@Q7$F!;^f(|izV$PcPMj|~P;~wTlYV|nXoMms8<;fJ z5{H;0gy4=jX8A?D%C;y-c7VAx`vMW$0mc<`YlFGj3*F2P@I|p>8m*X4+%GcQk^7}x z4?&}oYVE=8+1Ow#DyE~=ctM`f3HtAJ`tOE=SI6-Hwmn1|r})&=uy1N=r1lLT;)wlF zYX4|2_09W2e0eyiV@KL`xrw@zm)*%m<&R&*-l18j@IA^Lp`lO4M+nY8K-JT z8W2t;&V>hgxQkjf>4Y(!*-M5RWsGmd*~E|`qdnvTXtnD8cwM>i-L|>R`!IEi+Un?I zC+6)W3^052aL|c%l2B`}b&_;i*_i3%HEBF=j1?YtzNmn2H|UZR5+ z@=?OO`A5(#>#yNFBPj5jYv;Pvuz74A$}@aL|KYQfC7yV+SNuw8%kEmp7}ErQ&UdkD zt-W09fNGW?eeicncWPP(I)rfy^4Y2)bPGU>lEs2`@50`Cv={Jv+_%NH#yY{z?82($ zTEqq;ogUgJhMs`RIe8V5)&-P?)u>w&OGj&D)kTAjsyYCxt{B(p9G-UpPaWV%eK-qJ zwWbz@F(ElJJN@kj9_ba;(2%0;eCWc&cWaclrEuy(s@q1}AARt;x!m7~GzXF}9{R@# zu&=26_jt3x-{|J-;OV2+I!i_eo#5Pp1MinixB=FCo!)Du2MVaZCBbQ<ec zSn zsc@8g1pDLB9`>F`hv(7963k94NW*z-5ZUQQ13x zEnZc=;IEp$*ik0j`0?8hcIAy2F~Xt%t(D}L4jh0cop70C+sWut0>$wXI)Lxi3id`1 zy{vVntQj`G+rgk<*wYK3_M;8D4hPPRM6kYwxD=+(sn((K>M4fF$>N7yY$-+45z7fxrvz z{`k!YmBUAj&a)^jx+B~Jk464wZG{Z8or9yD(FYPB*lkRccq>o0wZ;ps!diAgUgz&n zZRfhq^PGQWAm^}tvKAja=HS}zm~2Pfwu7C@ZL1~$FjzJ-OtW2p%rxN_yKgTzIC`)> z0ziF?y+Cf4(Bi_5(DWKL*(7O3)w8VOAn^|v8Kkwac$#UC#_7Y@~ZkcEzv2hBsX1%tA& zIXzj(xf*ssF~=NOe6;%Ej|&bJFIuy<208TDNhNcGGOJ+x*PkmVm8Uzu;KRI`=l1od zUr`=OH{cfq9#nSZW17mxGS3QZoak7ItlC_ffS zUrpEW_Y(dMdk8W)cngBvNlEXlg*619TWz^`o@}`yd`>9Bk9c%Y!?0LA>>pmhPViAy zy%|Cw=!A*&1f!Pt?z_$&uYcv6)AO|mVyVPmWnIUD*mecD&aLa zRl;ktdY|(tE%?~QfGEc;oL$6AJGQoSTqI^#*$WAR&LM;je8B*7tU(~=L;4>bRfi@8 z2icbDms$nlH!_-qt>06^7WYV?Gw7E7b?-2ZvyzzS8$q^VX zaLB47Hfq^eer@G5p)SOVV0~1ZBV`B!pDAfz13_w!7%l7~TycCAoWSq*uaZrKr)mCB z{7rg^>>?~y3FW2{kUZ>L={L;|f{EElqY95YNRMD6@86~t8qfllAECP-2{P#nlMXcG z$px&dH9k}r0=Ob(5gINvLnR;y0t3VtvVsgTVu;@xYhZ z*0zbV(UVV6bKB54aVgqzWzaXLE+&stJpV+58Tt0>wN}&rToSdktS|t zc2$Axu~b+qSLis&#shyM(v36hMe?>K<*QA|bhX-7RIAH_u2sI=?4p`hU~u6^7fTfB zGn)-B)OIrV!C{P@+9pAjw=K15J6RQ0xd3}DYg-(bU{x`d)F51dts^PDS%_6}uw0qL z?K$D%k<%nYLaODs_%iOJ&MIWfBd^o_8FU|GA=@M3EyGOqmGIrilprB96#iQ)EG zuB3q*g56EQu30O4fbC$vC^ZLw@LbH?){sDy88iVoG{{ed;9f{@CsIMQ;v(*Y2c-K&bble;M;}pu z$3Bb;G*Vp;qH-QV;&s46=^)QiI&n}yWli>UCO{F!<;usOf0yPD2~v5R!(BRj948|B zZMGe!@b^bzAI-*`?1&avqq;_3gl4lJqFXM2ByW+XK00nqwSoSu?;|F{`aI|_(GH@; zVIQ)oY|6(<5OYu-)GL26*!(Qh#LW$FXICjB+5Reyj7+fg+1v(lqNwgO@lAbSxpLvk z66_Di7z~IhmTy&n|M-NTcf$_3P$S0{$=wm7_a%z zG9<#cjn!d=;|bbFy-u928GQZT#&t_S4{nQYVM85AXoPi6#&Z=d&fw{EALA_tiedv3 zR|8e|e-h&kP5WP*<$Zc~3wm5Jj}ro^^grnFQX5G?`}cuQ6e|ec6+TJ-K#*H>P~7z~ zqWozDrxoJ7{~*fYHmYHp18lRDe=DrzQ9^jgSthw}(WEc=F=8bjMapjr`SBr+vAK<4 ztQ3Do{0Q37v^+MN+i7DvF|4G--Fi@n&dt;WH~^d^90;eVtDB_{HEujU@ zO(v9UYKMI9(L$3ilHW;<0SPEOm<=;rmKvg6(hPwvQ3k=q)nJEg1oWQT9`WqO#9vCb z_Ry-li~9$Z@#oru_dm*ce@K6LkNaz=<2KTJ1FYjvYi*7+bm&MVqEH;Y<`~aN!%wsF;Q*5@n`Nw1VV}X zYHTxq{#P3B3~T#s8t=)cY5r^hf6iK)2=S{){CX|mldg-_hdW`Mcn`DU_c_0gT(9Aj z>lOEL2DW&<<#<&%sQi8Ncx}&fcyZsdVXfBFDZtmr*VA`tK(udKK%j3_fZ*#IU|Ubl z5A&Ftd8!PC?%hwi2Kaj5E&HVbGkgaIn0;lAOV%~PC_C{nT6t;A5xg{DV;e(L{J8W< z^K&iM+?l`;qn$R9BI1`nz6hE3>Vw(^XFT_ z5N}|dsw~tD!`9DF!5UrRYtgEGieC{o^ZT~v%h7(XRybIojvx1ZTg-PEjR&;iL(nAR z@$Eq?RJwq3n(YG@L9DjQL);=3g7eZ}aNfT4v&2CWW6uvhu*!H8^XZQMN?MJhP@O04 zPi`@er>JQ>&vBdlbXg9+w%S)96IuB69OXBP@xb{Or#_Fkg|_lMT<7v@v?AZ&d%bJ( zHP;OjCxtpPjhA>%h6r2)FfVAKiRe<%cQ0LM76AuRRQIM^0SKr;!Ji0mx8LA+XZyO4 z;I?Uj=^gVr&NxtVc!9ajt!vTH%(!l2{8*i7Ovkq7K)L^;-$y>v#Te+a$351+SMvPR zi)E)r)g4D>M!P3WiACSbFt%*iqy5l#NPJvpM6A1rYGeb%?Nl)~K=hC!(emUWLyNj1 z4zb~3oq56G+vrZ3@_EPnjOgf${EkXUmC{XiT3kK9YuEYJiy`-te6|?vdXgUys;_}A z2hlXpq>0)zNY=h+QbF?KC3VWbiw`aAkv9L(^pYbBy4SgPEk=(?Zf;3MLz%NU4IQwH zsZZ9g-%z(KIeAxdFl{h6gE@9m2eXGZkK0E<^?o{XEW*s`O=7EW*^YUjQ3D&{C z`fAgh>Y4|xjHP+>w@vGFEDym5`z{-JNHDV2TBkD_JR@I`R1wFP9BFO1jzB~UF=TRA zw>tLr;?wh!Rk$l_t1Pz&^wF6kJARIK3ozbNjJG{+S0>+gN~Rc_D$_z>9WY)37~mzB zMwoN+@B+4%0xRV?GVn2{@< zdu{U4qb1SNB}bRKyC3{{OOGB~epcr*AN>xu?knCW&4u+8*EXQknPAODCQ(Jhd}I@N}PDnQr@2GWUi06bsBydwqd2Z7@o$2CF>f681+73~S> z(F5wR#C2w(70~feW5O4HWzB-V{+D_``TG2MuRYoO$tPonFY4EK;qchl;S2k&@l8Lf z4~`89jteoYfm?wlGp6{J1r4*L7dPL2reDU^&o;*$QNEn=LTR#T>VfYM%}nxMbf~1^ zUk9e8dHZ#rlFj_vm}!hdFvi7zk&3?%m6}JzaX3hWaW{=himzL;r2B#+CDRYhPwTPp zP%(2>{%ynFA;n$YIY5;j8|s!P_ucTphV>t9%Bbp5x_RH089n22rzDCR!ZT1yxf}X~ zMyDmLi6JD-Dec5=%~)HPuxcRfdiK-jHl(tc&`)-FB;gy{+ky5H&>kA+RXl=r)QdM7 z5GnYOs3sFeVUDx$IoCg6F0rX9nQ;+0!J$2CGKgi)q1_6)wskz)rr(P9R%ZF1K6@5M z&X|meslL9c6Eno?mVWbInI0cM{grv5UBf_{Dd3lYwkd|FJyBcuxtUTWnt`e|1!MhzO!Y08;_W49zd_vlc*XWZb0`-`8w zHm`G3r!^MQ5Z1T!#aS7V?y_Te|D~_3bm|bMx%Efdgg#;RMqlHH=?Puq`iACRo6&dv zkf^93^ZQP^kQdwaF}h;u(XC&fw9E~uz1B)gUskRyE_rfd!q`rOM~C+>*;qQTeO8aL z-!b`QNeodMPfwyW-8cVinbL1X->lv#y#WUsT?QOl&}D?v{U=pc7THdk7F4-mPt{{I zS>&-Y3o(DSUPiE1$B=cL&KGjeLD_d~!mINPUe_V1$Ue)@33mHlm!hNotKvGw_<;Nf=o$hn4vv-X&JnZyO1 zM$?)SUhh=b6lth9rQ(~#dO8D3Bu}>TRoh`;I|$$y-mu3;18qkzodeXS8EtODT=+`5 zh=G`f$+{g0L{Ll6&WsC35LgIEBBunPkk~}>rj#YM%I_BzC%+fecjn$%{X*JhmG-k7 z6|;McN^bMS{RQuJpZmgu!k6av^pDHz+-tnKEqiUuD=V_Ho;+C4y>v)S=Rs3b(7x8ClarDrZ5okWG&sf8(5C>(^44>9^B%tg@B1DYrQL zq;XX$)1jVx)Mf$ZO#c2+z-D!>JddABdN9dEWUl8rP){$7M?`0d=sq)r516-aPFASx z$jg|sw)=>rlCVyTOi%P>kA8P<*D1=Q@0`KndksfQVxvorEc5g{^wX9ey|?}N@(aKH zf3$rESX9^cFYBB$Ggj)*q)11KfDAMA-m8d!2#APMEZDH1Sg`lrdx-^&EmkyYVl>7W zQ#8hIqPa<~H&v6|+?&X3-fy276m#=0?|t8kLE&&_@3mK7Ywx|*mK>pnz2*LH&Y#_^ zR(9^F%t0M(qt5-A?_NOWjU36ZSF~BTb{f~XM)0E1vOPc9&am+{U6$=R{5X?88*o|O z*;?bCnKM**42fI+v=)z;+@j(hPgo-x zyA+!n>G~ZMWpfE8sPe#<(@%Gw#=7g9#w z4%t6B*+rY$JJ-`Ex`#TXq#?D3@1SQ~KfcsCz)L%w!%f;t8vkGUg3nLNZM^YvJ37E$PPE>eeRF9X#oSAuAtvxjE9Ku)$y-#6 z=2tAwXn>HUZEE8~;X_z-GTI@-xI+PFHRu=3$87^MBtZGX0e5f1gW9!+bowdc~Ja&MV(NDJgmC z;aBDERbS`7mOCDA{FUHg!NLn2YR>tU`;^8t!+G?U8B*4le4&4#Ub$(G5rlio%XBu@ zy0Y|y0pZcwqT16bH57jiTos%v=HBS#Hk-YylX0Ap|(nL6LU$k%Q7Mq*p}P*+o>OUzm5O(#yN@;5>X&)uTt% zp?MdiV`5#KfviTN?Suo3B7lh8rm%+phrnIkfKRZ*Pp%>Bhd%;F6J%U@P3z`(J%a z_-b=?jJ;Fb(Dg$i?d+mZ8-C5e9TO6gChROL-#Ia{tAno-J9GHgUk{7>dZblNsm}EE zPOFKJsmf@}p~!b=gJt}rg6}zgd;nn#@B@fcrm!AfupzRAfr7H&&1ZOMVc{&2*1#*W z2D1R1(n5>C+}Q5PeJdhIG({!m`J26CrX5o7?s5OJRn;e_9vB{|pAwkpt5*9a(hnB8 zA$fU2bQXer{+78zUCph#NOn#xL+5SDx3U_zwmMAI%wCjSmFU72DH9glrTy1cHohr7 z)=K^9+RZ}(TRzcNt;IP8V{a$DL zd}gxrPqDwU7I%jyY*T@M9!t-}pH!Ya4@}%i2#pa#HHO90r1d@-)zQI|hNTJXy;BB; zCe0oeFFlJI(J#iVi({|eagoCcW6Z3&`DbI?N$8VMq^!cYi4_>ivB%Bh7hcQR z`s`xin)Hm^_f6(_GO2F;T0U zwNL9E)#T`uk?!cUcdzT<*tKKRk^{!Py-HZ1pFR=p;N)*m8EE>m(6H#(uY?)Tx0gr7 zV$M^@ouN}N-}gjT15O#gnr{?Xjj@WI8BQe3Tqx|<7s{3F4m1fTfBkjc(vt_6%`#S~ z?9?=<;t`jjbc{7mnh0Cs@^S^B9rxX_JIzB*H26h3Y;!Lc(W~eBs>&UsqoPLds2s8( z;B-^dY5g~IsSA3l{JJQ=sL#4P^B3OVkXM+$swEJ!NC#Nn-Fvuq4VcH`$1)?#hEZQ0 zq%guPUR}LfhWZ7>`n!A-l;1mfKtB(S>SdV8WEbQMJ=^&DK@)l5azp{y!j?Lxg4eEQ z;krI>_~=;+PM_}8H1^Qc|rMB5Ld0P;sL#TvoKjdSMXG#gXOXoWQp6+mdg-#6kgKy&y;Q1 z%1ab-!s;`GlYCh%BbFHnE0`nzaZ7=3Kb|c|+-FFsA(*x{2Em{#*GW8F0kyf-36vg@+Eo15Lz3x-5j?VXscsI2LnS~WQ)tuD`B+iy&iXS~Kkb*Wo$4|{Vr ztq@qXV@#B9@v=(j>`wb5vU*zf-EeR2vRSWJ`FLjxjnApe^kh*k=@Sao@ROXiKDM0q zK*xE&iy7YyC0Cw=!R%a=t=e1}4jU3u02^DdKSY+Nc)280E`&Bats8Ur>A_JU!6Oeg zkoD;%@p{CFO@k`8kB*EQwY?I-RFArg%lZ^;x!pMCgN-HfF)kUuXMqSPo(T~1Tp6{}BKW}fBKQWctr(-4cj!h#qi|$XMpYd zs9638>uakM>W6qAQ4O?%Gf#5JULjB!>S<-GQjpOt;R@56(_Bg}cJ;K9!Y7{i?Zkxe z=%I^q*|U#V4@2b`wR2)^ZtvP8C#8cnU_(xAQg^9*fAFZ0RlbuyT31l8?xV@`K3I}x zc8pvr*4@yb>bquCeEg_2eKn(Mt9%p2tOGvU;hX!GK!|Y*PZm?{+2(dKs#HH;%@Hm% z{QjGe2Lb&WOM-np2l=s<>w{$e!PodY`ny7CutFXeSep`0A z4-bs11_iKeQ&CK^_OULWnCjT9jxDH(?7yg7bLnJwewc%WrRKeG7qv%lcQ+S@FqY^L z-Y+_PL}GWfZeV8k;B;Sw{~Ks_rk%EOSBbv$fPaS0Ibp({$_rG!N!2qpr-w_dWAB2X zUJgMX)}1XqTJ|STDC`wFpdqPHGil-oZ*9YZH8LM^eK-*EDa$$cvtJx5d!Y^2u%ldu zztD!zsejgmg2^_>P%v=e%e`!ZSu|v~44&pIIKg3~81YpsCHLzOVY(GJf~T%M$n3lmi-Iz%V;y@|Y^?2tQksG&3F|s`^35KZ z)T#H}Q)Bf9n*7s3oZ`l8EM7@|iH@bq8DY&D34H0U_WyC0K8m2 zux_rqjSRuF7)H%qBXa}|YHHKlLbE=NbA=SR?2iV6+J+oPLk?F#4m)Ah7{+i`Nh{oM zKDvi}dmJZ}7hk%u8Qg+jx1SR_Rg0AQ3pO-Z3o>t_@^*|!P2$64ZM^t=yJ1o?IS87$ zOH)jG@qKRiaFBn4{zOEB90?>zA!L@ahr_Gu(FDbG-(ZkA9=T=!f zJap)W!I^88FPJu_JgZF}%utGBV8MyddS}9BX3z(!(88)1ou*LNxgBak#m?`vu zvmlt!$NKZ`(SZ(bQF-OVbv3K(AT*#rsFh zU%qNlV~9)gh^(lF(DE_P{^fz*VV)M9JB}&7{n`0=Yj0;u8Q0ao5kG(azw(FV;PU_7 zAA*+X1cwO!;k+{D^#N@Hcyt1f8-)tmQ3&|~gjaI%K+X+#8f*=61uFR$g5+Z)gjF}E z&YWgmiM^ci(wtn(MUT+9P>=Nbjk#3^r=~DpzrrNn?mcxqy9dY48lL2nIaK(r_r?_q zrj8z%<7DGxsaj_57w(dVg4IP&aec*u~IB?uN$gZ5h(dGLxS_7y;WK4OSE40GSNrRUb`#FZ@ zX~{>gk1dUI>J~j%ydP3LIYnP5l^+-~IA!Xg>b}coP6%H%JEV5f!rb&3gTgrfKnAU) zGWgd;GXGQocflq~*o(32A7dEkNb<$9S2i(=1d%&qBA?h}d*!ZI`gWEc%#!7t|{9oO$E!D#9mrk+q z5uabSHNYWkdpqB$4Usl~w(V_h)ANUI?l5q(g{4U$vTS9z@iBi#z>CXe+}?W{?EM>p zm)@;;8FaC{X3p=x-G8jPEphV7nqTap{IA#i{5a?FR~Id5xyk3x47}eDFigg}9r-?| z=ZmH7N90UL&Jk3Mqrj;iW)^wZqA^A;?aH+Knp zbJ^g*%M^CY@(c4e++R5F?z%pOD8zW^?md=&uWdgXwf?|E*pEg|pa)=R0vQqH3xM_$jgPCaN(Cwsst%39HdnU z>&!Y?kG1PQsKMF3i*tZN9NV$0lb7Wfd;f~Q)-JA2^w!qjrZZ*WYWnm(xhrjY1rKZe zv0>+jamntI%ENKM6jN)WpfRtzM!7kv6fN&-Ti#P9&H5u=xR2Po4K^S67h1s9R+`t= zn!B(@S;pdIxRB5QxHzxHYhSj5P@Iw#UlZ*()$QthcUbPF(E3l-Q&mp*#N+Bh}_zQ({Xq(|k=W9bDY=)7+n5d<9m? zq!>DMqCzdxMegm+X~Vzxey*nmw^}bAKhD58FjbC$)AE#^EnU_4$i?NVD0rH;Xv>8Tqb=RW1kg$*EPYzHVdmF!^ zA(CFKRX&6Nf~+g@7rfemH}Gi7Hyofdu!RIZ0Ko-qXtu4^*(_XRdw6u8Dvz4jl=wKE zqN1y-b$4^gM!m0+ma(_ed)Rfe&npQ=ibOEXt+2q{h&aI}R+`Qn0|p4dq@t$`hQ22_ zmDBhh1o&Ubqlw)5cp{?^ikt%WK3+DOHEx+gW_jBuClbXEluBg>@4%wsv@e>gFO&^B z)_cS(O?Yu}7-MWzLr9dhy*9A0a6#6#cf!KYCZ>$+->Xd9zi?*dM##odlLD!y_&KjH z<;hFnah{QRM~9P?)?U1%3i{L9;1`^;=xAWyq>!Z=t+jLY;EIvOLsB%o%IQjYL|R1g zhkq|PqO@1L+GX|5kI$SC8*OvCyFlH7M%M+KnpwG@j>;`YJ_(ByKT*vx_mXhV%3LK) z16JO_bHo**TBU#Sd^(=bg$>AJT_lZk0?+H@_ow5AXbgX!brBIe8sAq+jTo5gLVNa$ zbX_XJ^KpjvTgU3ZG9jT0kb4RGM&uMm_sK5J%}Vv}-^-s#W>=&mf&=QlT^Ib>6?0{m zNAmN}TQ7^hNZs)K28|JCn=7TUhWA^)myU=o^7Ce4;fwc^`E&XGPia@X=S5h%}Jy^pmhb{NWOP(hKM#+J{&LdT+$H^ z16>7-Z7@7(y(c~qhw(E8a;@w(WyjfFp+u=VEliYr8JPQxAhw9ASDTIxTAu( zAYvLWRDwcMXk9`*#5tX`&A}af*a;N1x2CfXOjpI`5D`(ilp{Ld5xRG{L+{ z4VG$n-&_79E$-;#6_q-6VC8sAtLR-tC_)(+s0()MW+#~YZnreI3F;9L;IT{c>h4#w zE5^0JCMUrz-oAUXCOs&sscceq>5#h5p3Ho_;DBFbTJYrB-DRcUZeHP@D~eOA-+66G zJua9r(qifgwrk$Dtl2Uqly4L0>8>8OH%b9e(Hq*JA`QceJ{0fVw ze{lA|waqJneMBj8*!-H9n`vgDJwOVqMTS|-mU*qWa0)c4#4il@&vrouyYQ3LudKxi zdfBLH+mo17tLbZ+fj-CKt&U&uPkjPdn)>k$<_oG zU7ON!aom8Qo&i04wlen9_t)RpI-z;+*-`JmQ8~+Aat@pM$@J`f@gX&t_I8%ZPR-rc z%sM?DaLMy4Qe>P=1)Y`BP?>L`fuyfZnz>%$^&-{M@2F%A9G-05h5O3aux;x-}BxsWe{hJBcVSPQ@!3CB^p>P8ua{(5|J2wZ9s9d{q@Wh{q;+o_4^hh6? zKR7*{dPu{buVs@{H}^{OEhKSaX0Ko}B#YLyqr z%yYY-zswDs{S3z5T`3ez&hod`Dy<`X1VlO{jSSATzfvDxEbPoK&F+2Du|q|D(NXgD zwF!@~Qx{ouaY#z)altXCTW{Qs`u<>5sBe$evtvE_?(G@2GCmhFZlYr+q$Ogx%md#F zS3$dPW!lMh2K{)=2FZlLLZpicZ4-Y8Fj;}wqeah-9nFa0{Kb^=q&E-$FrNUg?!$EAqD|X8Tw4w0{ zHx6*08fw_+Gs^NHV?uZw>u;wCe7n$-0uJ;%bDj;Ox*d;tP3XBuGw##ynEq+A>@4U~ zxT{B~Uk|A{(jMhJ?;Q%rFKo`LStP3L{3;gQEwQ+OF@ndEUUe#0W?w*tC7T~Li@Sn9dIygOHLA1S_gq`7VAAgtX zh%)SV0md%Ub-8-zSm8q3g zfI6gGR(@GssCjW0kD#!vlF-RbZP&@tU#%G8;j8KzUe+(f+FREf)TEJuB08sVqtBQ@ z-7gJp~~ECv3dyl#b|zq;`)>5Tka zj+4{Ci5^_bV5 z3b8gzbK~O92%W+P8kXkLlP^sWqkS7j)>@917iMbOwlcuVo?u;fWFOB6D|;ftil_?x zR<|pE;n2sLQh!2fuA3H4^K;mN&y+{_1cAvjXO(UMRunr5bU ztu_-yJFnu@?hcCC+1^Pc#0QV6t(Y2?@8)RRttqd+hwfd04%UUIkDH?_>fF&49v<*s zC_NS@qkkdatH&7{ett`BgR?(!18j6F4;D>|8jJA%Y?__Uc4mU4-xOe#ONJI=A&ndlb5czSdpM zeX^#;IoY_SG;-frdJDcY&ZA4qO_sFz(yf=^jW0Jb`8OgE%u|Ye-wDbP+~Y?5b&YK( zf+pv87S5cx_>%M^rChwo&Tw8rKVEuAxFwvGan7T=KOQ^~&i-Ne-CFqcQHbFX`M9EB zyC7;Tt!%`o<6gZsU7D2cLi-+&D~)6i+3HPvEctwD7~aQO8XkG`BJcPNUnD1y2K^)4 z-RK8LTNggU_+*_+hvOZ5D}Eg%4jMLg6SFanxk<5JSW}QYsh0hLap%IuW?@{< zKacx@@G|K&(1OrOAU%C$XD&~2DX@oCP+AA&aZ~HSC{xqpJyJH$cGZMnOQT=^^QgUJ zSi#sSF&(^q)66C@Q0(Xj);~l*-Drqlb)$D@yYZC3-wY;nHLgk{IV69whC` ziW{33l|i3r*%1YmU}|2m zecGjs#X*7)RJ`%huKGgf-zb96nDr`qx2bdICW<5-3TdRXtDG6hq}_O=K?ea27*|dx ziKj!;JJaLNh4s5$4mfRl1yT_hEFC4;bQH;lWbd-8-w>k+$g;^!z!!x2sB$L=uKNtB z7Oqb4M;@L(;o8pdOlbKqdUry#APt_ja${+uX(vmMl1rr?s!ncU!*e1c1d4Rc?kyCE zWhN~#_;hN{`a(d<5ZI7;{z z6|mQDve!TTlnOBJIYlt^(YLbP^ZWw`4M^kV#0}Ok)LKF3a{SFLNYI6qMQb&&2^LOe zuJvr6Vy&gx!?Wi={{SMFA+DA#-Lf4zIaOu9jMJqJ=H60{iLbutFXHrjf(?)Bjq!dm zY`-B7a8EFARsO~EyR^0a^B3{{ePkH_YMlG8y#F!}a6|Al=>z?XJOF%-m(TABADA5e zi|2QRVJ2(;;`x1{;^q5tZ2XDTgxm*&5!yV5D)gs}F>|Ff20qQF!e_!`jDz2|#TW|U z2hT@K9kE`-7@%RN*1d`W@W&A=d7>d6B1jZEltU%5=It=LlN?sG^WeCHCV1_||_n{0F^@hDC)Jgb%%%l$zhYcRVe<&fWPZrAcAV-R%Q|l9ybJUb4~wrq;99=Jygr2T5&aRUZ*;zu5zw zLfx$4Y6^nI@os%ywYp)LUobh)`cKIN_Qpzv;01z>!i-SPR>^fEvRh~%Uzrt}bK?$M$)r-p?kD9A9X+1Hjz_WJU;qqERa6PUGjIYSn`1l-8Uw`T` z$Gy?60QU=ITD<&uq5QMaPT=>80GDVI)B2q>1p7lOM0>s_F>zhpmAD!2fK5^xrMVvp zo?N^3AnMvRxe~C-#745*;OS=`_3O0<*Wx;MvG34hv6Jh0f0Up89#4Wiy{y%|v6X22 z*GkQM*@RkvyxI^r;%LTZj~b03(4(Y|jZGlRlK5P;h%Mm);52+px>`T zLOfAyjHobv({k~{_pd5xbcavg>eGjvZ+TA)-@g>J9nty_bv_njCD>&%aZ?AY_>8(x z4|IJ~LD+Dn1QV+uWjw(W;>op#LW$cbYMR;Dm~`Xpo9pOn64?5a>~Est?-{ppw=SGJ zG*)wMI2%B8{OB!qB{Msg#8Hi_zgjQ|iA=Wdhw+i6eXEv!HfY84-!CtXNSS#~q|mT} zJ2E~eK?mmo9u=$_xKEDoy}aG5Y`E>URa@J5hJ?bPAiavh`RK0cg$;OHU8su+sPg8f z8Q{VKO4MJcunkHl%ju|c(MyNA(}#ThQPHmR*W~(E^YndhY!ZEOwV(b7S9cc$we9QI zuCeh#x!Tf#m^lS`yO9|9V0xpj_osJJ$K?^bg$6jl=qXWb&a|Z6yE}W9ga<6Sa)KAT z;WF|YvlH(FZhK^Ga3Wo%6e{)LTxuwAsI@S6N7Rq*bzZj0P#bUEzji*P%1zg9jq7^O zb<*LPg7WtD+liu(kRXt_XUus0uli-|_otsM>2&=U;R~v12A zl%{!Knu+=Ot(NxlV^VqJ0UXqoKoOqm;WV)dQlX!stBW?IC-2TAGm(;XMtIzB2wzXY zl@btYA$z`0A-#8OfP4MAxyz3Puw86A;gHeS?8~t+G2|hRY6FvfZ+=~%IaA}nR%dTb z>mNS4@>J5DU)YI0G?-F8{r8t6`sIw=CsNPQ!n1(6uJtFWR9XX=!RsVr%iD{`Y@*r~ zf`z^~yjd-PN6SHlY)!aQ4Mn3Oy6xfU+8t<{iH)1MX4Zk3i97dzBqNT$JuN^ej$giH zmAK2r#lwNf)y2b6zxWWL5}f{m{y1KW7HCDE+HWa9pd)7l8hL*PHEYIVlF+XOEzP zx*@k016*()*xkg$1KNmdBr9+<0e?Ppj)Gf7lVENZL@n0>79L!O zTU)?4;O9cjU7;G$lC?1|MrfWqpnyI3^2Y)7>zmo}L-}Lxigk@~EkVmFH&b&NdSdP59sxz3K()nT5gkehs*{}K7F5~m2sI+%CEG=V~H6CK(ITHHK&3X=K*R)n7M zo)p#0x-cj4$432)dzZXUUJ`_}>)7?CYlKVg$MsnZCJaNi%>f_vujhCnp8pqfd_dk( z&GYs06sSXsHT+ZI0N%DW$#_*`DcW&5?xZ1#l*4xmPD-V>xq+70RpQ9>3Ju{lM$6SY z)^CMaOPp=we*H@RjaN4pdL#>1IVB%gwrRhn`g}Y#uxA7y9IwgEM7J%qMZZP+B1V z!C!TA_Hd*&>3IGdrDx>#-Y8Uj@$P%JY*ggz*=T+D!6JoXCSB{$be(9uO|CA!th(gl zD5l(%o6hmZ*Hr<$d6)!YRRG6N_-_}WX|JoLiqe9H|Ae)<lX^bS3f|z-x93<>AMJHYJxHmp!`$PrR(qkyhV7B)Q zq8pEFGM3(_BAHvjG3HOu-qYhj!&wp*ZiUua&Nku@L<1De^&GVqj~?Kw0Itz8T-Y;e zZ`Vk&C$*=SfL#gbG9)U{X&Au;OdM}Vs`7@lp%hqs&Y9FffYN@_Z&6a0zX`&}yt-@7 zlZvWbcKK`XZo(<0Me4s@yUWXP5Z4e}pufpqc_>gmow`M6G`xV}Z0I3sBD=8}gVm#= zewTT46wdWkzy>J{dqptmIs&Hb$=uV+!#l(lwohfFae-xbbx~1nTwGKK_Nxz_Ls2fb zr|bcJeOICs`{^i!e~taaj`ABD=_BgTZtI)bU4b?)`;=}+r+2tRm#%$=`9zb7)}It^ zip`)=Ft5(g9vi3&g>4@l$b=BYpx-S10y_i`&K0fzr9stk%m^7N=v?1P5a?%GI@VF> zJa}uPARGmlTtd(#uJq-Vd+{PNTiYZyBHJ~I8FXI7^okFn{ zX>b~>%&A)=#m5q@kpKCSmCsyEboo5dnJ*rzorKdwdv=XeKhD&@=s=KGbY=y&>qb-KELF42P@qT|EJr*8qf#NGyj zB~TRgHE2c;$4_vD8re-^*Y%5^3zQbV|2EN`R3G=lVATl$Y6DTu8hnv`2MMAwI1 zU}FRtS2h(ge@mbNDLjV+Sq^ITlJ>zzmCsXgUqtjK6K^jRH1qZl1;_}X)yl3h>e_L% zlHl9ecy)&0M|RQn^}A=@W?!m0qQ$Zq(Wf`vE9;6EAFe?wHK}Xk^9^%_9P){_U-0HC zV78W)e{@HbKK$_FkS&)4#kno)W8?=)Ag@EDM&uyhm#+WuKC*K7S3jP^_I#njv2~TI zGx8+ez^VX-Q#Kfi#6|;$3=$=UsKBVUwE|PHlNaG9JwrPP*LZR)T-c;{ObDY`r4wsy z8h)4Vl^ZVBBH;w}uM zQ_ZcrqVIkEcu!;^ylFN}?;w0Y_JtSTdyfvW1tYPi+1lFjE+0!d7P-Z%a&GbNbL{yc zSJ+qjUYe#FD(CyvuGTJ4h5QR!$q;(7BoAmYFF|6s{w=UGY`xO+&1q-}8N=RT7pA?5 zQROkdQCMLNYy9wH47CbJo}j#*gXfje+92Yc zwf+Js`uxW~0haUNfsDhxQX6dWW&avFdCb3pkRG-h)d*z1VO$*f*NF34kD{3i;FR2; zdqf1e+?AALa2`zxZ_SL4FI}$ak#uZ-WlqVpvonZ&JgUUP++*vRoRUT3Z-K^CuU{%| zXgv&j03PDw1Z%B$Mg~#!%fJH8sG#t-wI2IROvbmhGq=t@>Tk{Zt*ndbR5EFNY(sKF z5v8y*7dg))D;%Z8;7R#32HC)-X?31%+}z0q58B=YOlhmuNQ@;xM!jymll9KuzA-bDCu$&zN;cG9*rLdN$MQ5!^hBsHj9Fdt5sATy-H0+gO=!H2Xu zt&)4_PVj_XblPXWM85vmVLow-&1MD5PtleYsr1G#%3AXC6MX!qe$5`v2^g)~GM{MH zsnQ-x{*d{1pmar%tNevm`yw|me=uAWLk@#GD}3WpiStb$FN6>3hO0+wbtF%z8}^zh z_bGV{7`v5KF#+W@f)EoTT_H8u&Lr5Q z+tZ?@uI4o}OFiZcuLz5XBMqPZhS(V-*gANS~URs8FvD{Iyp4O^j5I1@5|F1RmmmM6&9j zwKqSx`N{08e8u_W$FGq2a%>)B{~27UktWNs42=e_9S3;0P6&a%#a^x?X^8b=(Yfaf zpi(W)u?NBlnnpwECuTwK53Ly7kDa34w=$|oy+ecaH>V%6{!)n2277_v7v70Uw8U9e z=xx4d?}UycmaY=lJ5mUXV!dEeX3=X)PE6ZD!_N{96Fwsw>L|GA9|^AXdj7(CM~8F$ z9l}p9pTH(koygX(;h1A2>n9D8tPS}%PY$pp&O?G?IQ^(ZVr3?OxQ(TKOa>|nR93?u^||HE5=5hbG|E};0WcS!Pkdt zfc&Jj4bbg^Ofk|n9REPKjfE7}igSLMCLr*rF z)(@zy&tt!RQSr-Sdiu-NqWZjPRKyytm#Y03<2V*&9^!ZNEDX1+iLcE(RO=PWzfsDR zMNfOdMGW!gCRZl~6VtM=D_3CI^U+PQlu}M(pZcFLJ}w`gZ=y4YkuK{1M=L!;9q|w9 z!_I9gQ1?Vd;L*rPE@$f{*PFtvdz`|8NhtW2)3=*^0s-6Y?m7!Cs_%0eVs@<7Kx{Pl zbystjFks6*!$P{1_kq6)P5s3ApPfIDs5cGcg?_(uBJ%Y&!i8SPvwctw54f0rM}Q7*3eOK5@iy|6hO!%r@i?+qPdF& zM^Xq&W}fuHr6e``>dBk*8hvn9|0UtvJ#mF4bQL;ICE*8Jk36#%o2$>Kb!-8fi8*js zM+#Ov2kyDwAV+AhH@Ku|Z2`H49^s^b9s!#Lvk0PW`iMC%agS@J4^JaH`iU&aM)1%- zpl^kfRI=;{yVpo4t6a_IfZt`kK`;2q9W$uGR0#T1FfBZV2X7YNX5G-+TLGvcF9qv+v0I1TE25TMS>A}^pB#SN3mc+cN@^A@w$%K6$n|GVoKiGo$aNpeT37yen&5bw^Usz5V$I(dwaw`L==IG*U3HE5P|p)F^q7tFXpt z6&x4$h5_*8N+<}9<(mYa^=8=*_0N#&B(`2$ZHZ#mqy9#n#io#`{;0H1dl!?KIdg_# zY*`+a=mUhcz|V3=nPD!CK%A8h|5`xLxqDe?LrgqvB~cS<5Kd|1C-2^wT@=5aC}T?X zH#crTHul=HwfF1_cc+=9Z>I<$f9bC`n(tpA-@Ryi9=(^{-`&!DgY2rG3pov|^VqiN ziV6TgGH+-U&tw}3K9F}3zz!ii3u}v9Fl;1?W`QTk0Vd%3(1?rnX^01={PbbCMKmil1+GSu5L)*NZ9J7G;v{~ zMfoCf-?~G;yDWR>kuA||HO=|g=aqYeb+r2AwT7$Ag=j+~Z5%w9)jrQxmn;=t-^>1} zXSYcq)05lGUZAHl@*^DOG8OTSXl1Uz&aAPs_OxfBI_$HiMu>F)B`0ggm-PppyeVar>R&~NUrkFs;rnOkw#vS8?&{>%~?nF}fErAxMK zFWB_pOsqQM0Cv!tx#Ia3kRA2}2Rz)Nu{#jWAlJ`sxVnGxC5^an0cnUpn#1+#OJ9@M zq;LZJ+gJ$-cMph^2ZCoVPKJGDuEP~NF&k+L_K%}rS@s8ecvPU#G~JnYIp4kL97~>I z;=LMF?r%Q(9>t?`sug=ze?mG>h3viZ?6+>QuNs}_f~JMQQF~X5O3MJTWlf;M4$!P}@4W4&vDd**@{O1$fpNEE7zhMqq)U z+U489>Z501l77Q}vaO)dKPSClUnk_W*ia*zz*ZZ^+X4Hqxs7g|CY(aS7Vhon2Bd|; zsw!M8aPGrHv{bn45Gd$CggW-jy$uE1w=7wzPPsrAi21SPGt@$E!0zwtAJR>V1C>^P z`H8#hjnCK@Gf4lVUQdFV7rZUFmUCbY1^BJ-Pp}?2bH=?(SSYSb72Koq@>YR0U2U8Qy79mgeZp(66YV^p zX0^0tXxUJYbR-=+Y#%(T$_gDBvOA)r2}KUwIW#mae&`?};eGMi1v2^o93}&fL0GQo zUs`|Q7@kr%)4cAJahR^W$$n-(BDU)ybk+YNbQQnS@0d;ce^UdS#c;xh+YP=(={EPl z+UXhKlXHjGQ>(xo8ilndKjeco1+eJh%j2j6eE)a$6FW_*D=C*9xqaS;1<}V-7xy2U ziW>ZsaB$1(^S0L?Z+yajnf}JyscC0U@wp5!m!WnFuxWwF5ex8^6>hNBz?CriJO-1u zzQMVieKBt+)11Z0d$JZrJbylfDxd#ef?K-(*hA`nEZ?|#E7h>|w7s&DeSh;1t({!A zes+P2>nHWyx}9GfsMal*7NH)<=bwPJYQRrO7|3?V+)9Vz!=e(gUa$cQ#M4I4Q^h?H zY_SImyoZ28mg-~o$uKTGL!#Ym^**|+}R5k&gTEp=@qo++-4+bkIG-d z8%L+G&*%>9Q`f&yEI9D%$7~-vw*9iOl;-YQxOq0MSeobRb~H`bYyECFb&qXtI;*`- ztqf8}82IoP(8$K%_u+i62jWQZo&v`LJiL`ESOjpstIPXqa@o%!y-U~F-%FRVf3Lmp z`Eta=&|y$lzeV-mPjP}N>7TK;_m?TIC%m#)$_(dgG{A`kogTxU$$W>o;4gW|)|cyhK2r#H{5-JBj@Vmajo=Wssw^xK09eZc z6?z`JzAO8IH#nQRjA`M7Um@L(4~g3pHE%Y;o2i6;zoj#6^%QYOdk!uA?M4&(Hyb}x z9rK$BVm54CNmDSdtKfr|^*WVg9&?g3=jLan@0~zv*|2fz*_5S!7dwLY&an%3SBq5tloqd8L2Nub zL^}@eWwSn&={+3sPz5+3`>qf~SVee?$S2vVyg4ec0U&#Pa@M$t^#A1MFqM+lpCHBV zPE<|>#14Z1$o8jG+{OylpY~GS*y`zLw}n~9qm5S6%~{#(M{E%JH0Vl4U`o(^hpcaU z$XPRJPE3RIToSAy{5@a+e60Z}7CUgr04EDR`65UZlssG>5$qbtxqiHdh7oK++EO{V94etqdgEJFKf!OlaAF?eBk&l*nz}0aX ziS0T1jjd((wq86+*caOW6C3gtj;)~}^1JM9VK|*8md3u@H-0NNToz|#v2Q5s@A>^G zqt(l&g>Xm(F>&i8aToB&^BacyHrTb(;;xz}Vh9r?cTi;C##Z=g+`yTMGZV*sPhX)Y z-J}&@m~tRTEE{ul$~;m`8kbRJ=X?;jJV9Z4MYK@bncaWwYK8AA@GZHU1dE5nzk!40 zv)TN-yS(33+P*N{NrpUAWE`df&2C|ERCx!F@lBw2gH z@3G~S21^MeKB3R9pZ<=qlpm&yrt$R(4{-J0cs!bQB2VbE^_}Bq-sj_qCO+6ZM*k4R z1ePWV7}45r+6%|>coF1apx4t?Zf}bxDlIQf!RtfgZ=6Q);SNWaTe^$J454At`U$@i#^DiScp2Uhh*X&)a~Hg{{6E_Qnzx^^kdi1zbeKC(}R zHpJ4x?VzKnX-Vmx+STCEqbyfSl7`?+dskRq)QiJKP5e#Jf8uY^`FxmI()&nGbp5e7Jw{)?D z*M=0e(t5#fbmLzamoHho9F6LoDFAIrzr1zt9`+r`WIooGDg??|VROMnKtv`JMoRsS z1+;w#4ef8B$EdUXAwt|DNPEN*?s0M@E+0bR)vQq&4IHNw9viB_oO&Gv2Fp<4o;)Vsv5W$|j9QDuOO7>~V*Vz~PiNcH@>KeY*PZwr9 z9nJrh%25X=g|4{`&6qc;Nt==z*%Y3U9xfM^%&G)GwFsNVTZ%{ct`lYwUC}Pj-P={= zF4UlYIGY{|?GudB94j&4I7X{L~tK7*JMP0;C zK6~e#$87(@xN#(8O@Bx6XyCsGvg-qH-4c@q^6q*v{wNgVY{WPn;Gwu+c69rM40*YW zZ3@EE(DfH7MJ{u$baLIOvcbdFttsi-X8`;Ko8?>j_8l;EFDiRUe(a;<-g#M6)DoK# z8#Z86Wp+`QF5~)-9S42Zejel5N%Xn2GU^u#`gMEb^c~T$cdlK#^Oo@Yl2d0E>n8|* zzjpi92VxSyqAb8U7jW`@3rHLP!;9(Qc>or(nGK<{`pa!={L}kfK;`Cbu3B-f{xY4x z+nZUQ;!(@lffNX|;C+8#vA9d|lbivR^_#hlt3c}jXgs5shH7ymTig{gE$ir&tH+~8 z1cwZZnlhz+if>%E`Pj{T?CbXxZT#A)`#3+J{Ra;1wXl3Vfa92u3EC{KHNr0U?m|Y+ z)xw=38mVmBG`6!*@rdoCel2IwI(01GAAY|mLl7LFGZDXi_49MZU8 zbg%4~$&IAkw7ZgRTU6SAV2R}2Id;HTpB9I(ZDP`t34Lo2*4<9eOv9xo>0@@6vyp@FwT#1f;AA=80|hW6s_@Bm=y~mSq;7b#A%p41wW|2(9XhGA zbfKBnom7n;{=UN#6NdZxdx#H_lYBoq#MBl4nTA9OVS0Vz2oF~m7gu*=4l%6BSAgXQ z%)#vn=Lh^Rx_2h`ucj0apHo{rWl4SG^huy@f4Ts-u?h0m1A+%_Umz`R? z9UB`KJE6wbk8KfA=<2p7p(Wvt+3bdY4RYjcnS zNbvd}=l-;9ZmQyQ7Z3f9xl^(3g;=*a_fC=aX}4PFCP_B1+%k(cgfBoyu+P0{nXVmzS0g>6MsfXH%xOboX%coPB`P zLdJ)Zd(m8R@%z$%SZwoBxrfAUplDv$)URJttK*>f=_`Sea;I_Q!~yd9=|MoRLmM_7 z2@32jR&$-}V0B}uOK{Zx3dfYxvf)oimdEV{JZ}e{4SPy3SM5D$!{90dzlz&g zr}~khladn}!grrOv3~C6aX8c_Co{2r>1Gz%%ZNQ1I$c=eBFZj#Pke}R9g))H>(;D z-4{Bl{hS6j1Ee$>GTx*b*_>B7k~@bt{`)!4|F?63?zBgit&Tje3|_*rIE8HGyZ6S) zqmgm}R~e{yFKdG;OGTCRz z3Ny1Rd;5|KMT%B)c=f6yLBV}wo=B(t;(XNplH&$~F6OQ-7?#Hk{n(vvgxGIRoT#f4 zwhHdKxvVEUI}0BJe!`$PH-PWC?*q%GQE>Z=`@LcH6tskWO9@Na^TK+ii2Y~jdp3!Z z(x1zp^Tg*4fR=9foIy&U{td2t`)`azZG}bF34sME!`%FXJ%@P&2DlF!rjGRvijzL} z@fyDqC+n)`#3eVf4OBfhmj5f%>D=6bJfadhC{DmU$VK4PWc%LKKr1dUU^0!h9FEzD z6T-r4W{eMabWBXm^YOQq%cxtfr2wpFMr(>Xd!1HVT= zmeyhX&hojnHg^m)LkSl-WP)i!gqos~lA``4CEt_R=1r?tZIa%bTtBg)VPgH{e*3oX zXlmNAUB*cf#+rn&cvLOp#Bj;Vz-=;aR8$l&IAm9I^DfPxUIC?%wc{s@h#u%8{b*-* zh+REoYY(F~?a4G(cX_-B@iQ4V?&E~ObwGJQ&P&!5u?c`Ql=Lqu5kK3$Z{PO%$&>4W zD|s#AXR=Sk-3{bRyW}s zu682skGGDB=RH~VtRYJuOoQG?RO`HVI z#+DX_6al~WKX1morOW0|pV$23-?R4gt=OKpX1@RW+DqSlduhblz~+S?-@Z*-QTpG# zg(OFZlL7uak93$?R?03Twf%2)xv+QzUyCtjF;^-eDWKP8xshkMvu}v0jL8p4 z%a+l|mXS1qEvM0JH8LP8g_>RLgJsJ|yNiY{TgKMO<7`JQ(oV|m@_7!<4jr~RCT5!Y<~!o=%Q0k|4Tnq{ zY`7c;8`Pbw8z3V_mRQ?#vJS92Y_+CtVeTn)txbqy>7cTL!ZJ_Atcf>Auidj}?P^?Vv=6q^g!+%} zqYY(0sya*CC+BD4B53)NMYnF8#_`r#0U!g|1qJxVk zPM#gp>z7}~ojp5zj8ZHJ2oKBEKZN=9uO7sCi>LzncNAow+Y8wPcZCLa$KDnqJoqJ{ zJbCxghAR}cdUbeM&GuE{j!wenQhF~}|BuqnvPpAK>CAal_BXo1@Akk*L0WHPr@jBm z;cyjg_Q<|Q!MHy;8!M(!h$(b=m;a~wy*D!n;Q#ymB}|y9sjjZBuCA`G*Im8*Y2tYld+g@+ndd!Dy0v|7dw>n* z23lbKAh&xUH<9m3L6eP2!zsjMM<4_*A$$J(W32m?E8jR@{^plojv2%i^W<+D9Y8u9oMNmQtAkD63b=>c$#zHz?t%{O{~xJK30>^-G_%7DKf_)7mG3g%*uoU34Q{kK%=+i%Ia691zz zS6vPM=o!=F$n#2V4C1SAv{J-gY2-o1W7*(%+Tol@Cl{!jg*Ef%H=S%XvxJ|gtxoJdEe9rw*2@z;5+A$2Y@4&4S)OOG5)gr9S&s)2_Y2kAS zLu@TAt(!kbOeXixqYUj3<7GUxjGIOXke4SXYJPrHMD&z-pd&8tUp8KKpL`e15DHX! z%OIOt*hP1IX4##{w34cic3!6VOd@!E4Buy>J~EgHt7GGchh}H}g}1mqq;HSmaq%|$ zm<7}9;bEHBm@su}aPMTrYb+?-FJG?J7`wIqm5tEYY7?qKckY%PzE@@zM(9VRI5=Po9b-mFjE?3dTt|PyDcKDNEl<^$@cG@)U&Fp=cJu-My=ZZ-M7fZ? z-=%x6#fy4lhZ-K{X9v@u&m6>Vs+NEyb&pB zF)^c)o3pbARjteG-6gZ{_I>m0*~Pt!dezj$Sf+QMKDM-MMR9(f4INOInd#*PR>A9HjK`6XUpIUZL<(u~)i%PC z${JYkW^7vX%-OxOgvs;LV)|wZTiIwfXySxn=>^UT(oluYAkZQI-a>7rpdW+_TAm}D z>wt&1A01V(A}?>s3R;y ztX`oPFb;C*I1ywLD{K&-LOm3hghl69w(@9zmFzqBVX%nG#+|OQETp7n_VL*xikN9f zdHGLMd&*~F9YSyTNOzAYIGh-39t<4#hhqGQIhcw5KtEk3v zm9+xJHWA`{x%u*^&CL4&VK0^nzY4eUb}4gX03XX1Jg&mL#Vpt?uA`k0*tohwzFi;C zDEA&ZhP_I38_}n?f!7dx;P~)CTw0426besc574e2933%Rh9_C&Be)RhHNAhM+^a@4 zBEF3vCa^(5BlN=`dKL+4bZM*uCqUqK2Q%8F6&w<8&7>XN$auO<7$^P{+nE{!t2}U4 z()!Kp-7Z~brXeB`WwAtoTn)(YUq7uT#?E-V?6{xhLC_}3HpGyXb!vxb4zEdQ>Q~)+ z>dB`Hm-fq9R8f#uW=#DkP-DXBa4y~@J9nC^(XuYS|v#zQTCAz>n{Z)36JA(fPri|t=)8Y10F9myWk}%{2DbeApQk9EWcT)|i1Zu~te{wrqH)=x6sCQXiJUKmbVE?(J+EjUXdWBEgW8^ z!q4*=wg0Hm2jlW05f3_3;9u;3{i-x}xyb^t@a76x9r^6i<;E4DET%mvD zDnT{;b#jDC|5zvb5i0&ME<+9fHQ-lq{*MJwd$F=s=|@O)yswXSB{QC&SM7p-%-a#-tGz&PW@c&K_^v(6a5Gec%_Dq{w(*_SmoPFL&_gJp@*iQW3$W^@>5Qx#aFhVN8~T&zQ$K?@v{=D+08aD? zj-Wr_3jR9e3sU$wu3;37=l=x9hl9f5M*%P4{44N*DxBnVRvkk+ zj3EQ%hX$Wl0Y9q1+Y>pwio+UGoKqtaLSbkmPe z@sD-lCql(n#+imc9CBOIL7rG;fd83*&sJ;^=f7IzN5Oa7RA77H2cW&1xixU%Lk>$k z-Y>=DP?`4{~1B|fvI12)P*Wvqe<28&M zXfnGOczApX>#{^`=WA&H0^>ZIBia|SJ1`FIT)re zkKU0kDDvfYI7h)}(*R%TA>Uytoz0Nr1x3Cc@d01yA>R)8iXIcb9;27|!CiB}ciTHX zq|Eu;Ebme2D{|NP=>@n#Ux91%H$Z+B9{Q21(zyhQ#*a|(j}ez{eqdJ>`U+gb-!3=NedwrHvF3RypRWQQ zAvL<-bt-&2=qUJ#eRkv1xFCE5ej~n8?~V8h+=Y++?1gcpjUe)wFoMt$ltf>=iti&l z#}SPne5;kuhurTs_E*c(JO>EMH32@;;1B+m=spB=q}rZ*$o+ng{s6Xu5BN-JEbtXO zrQzdSj3XMSuV5VCftvA*0Q5QB0KY=l?`0#P^#sx2%DBD-{=(uL@w54StYZls>FZB| z{xr%U+ljv04uBhXy)K>gz(>2(an0rC!Y8;#do})p(B79k^te!^k9k?T+k^fn6|Ueb zent@YGf)C@;P@K`JdAD;C2$vV?h5c zzynDB!sI|B=#SR$(XOpZ|JulY0$afcJU|++^lu0JJu1F3@4E5#sQAxvxoPxYg}qYz z8wFme(&yvf@Fn$Q`+nWKr~xC+r4Qk#cag3epqiX{dyO3KM{upZH2-<{m#mLUpU)?T zIM|^!PB#(lQPxO`zPi^)6Vx@50@v0^9AA|q^f<_%|BchR8+76oIerT{>i?tGr}Pu% zH^0|)cR~w6AF~_AfFLU6FfQYb`!T<*g`W3B3oxUhy-GdY-=_JCYVoLt)?y33J?Bx+ zYp7rG{~rsYaSi{R<2M7Y`2UZ=H}~-WA)hK^BOmW6-2X!f)JyB5I)elBm+=0AFVEqe zzS{0k-fl&HoW9cTIBK_3#XpOB6+cyxUz!R(3b^8@DsbpGr@sL329J3M-T;S_KZ-rO zioSt=%>HhC&wemSZhVCw9r!WmReS^5^{DFaZeZBR<;oC^kpKPHv@o!HvQX;767AcEH~bxH5kza&ylI&06K3+WLBVfDnVV^-?ca3W_ zO3?U%{vTHLUs)G<(s%2>M!&TEf219h7fAS%s2JW+>34z~y>1RST)qYT`&+<2y9N9Q zPq^`di=QjEfL~SNyuFotw}*Ga z|IGPs!f!{!z5|^fR5&ak z;hOwA!!`MLhO6>#Uj{y_I6uH7c{;&4+S>_k^itr?^_}o9x9uSO8{pq7aM{=i|FgEw zIX&JlrxV;IpU!YiJ_L{Ups&fNGhEY8PKWoe!jGn( zo#Co}wqqWU$~k?slgksH0_52V4ta98v#1mP<+chgpU&{_RrrBU_@A}i!SPAoJnQ{I zfyAL3udSLJ^LT$4ZPt%1w`%Nz9B1MbpilBWmUaJlUXF3-;J?-e-L zXHR@jefET_`YeN*WZ?2w__?BtqZ{B?6}S>7;PS-C@z8(8-=luvaF_f$!Cm^_8LsJn zXSk;So#C2&IE#6R;jbcSp8fy23eD*UMWsqpCmSM`&UHmUQ- zk0ei{R~zPG*iRbo$~?v425r1!w0401(1u79#&0OWxn3#wR~0(CQpjy1mrq~^`E-K2 zVjKt0gt-{JpSfzq71u`pvhgMufpL!y6dHWHQ*^+XMQ-`+5w&j zI(&Q@k_m1&uhMbDyL-ar=`Q?~TfkF2;qBord{74cG=+Y&_>lX0dw}8W9b)rLll~th(j*4CMJHq?8;1Qhv zzBkZO;21e>`t1YJF7DqLU=cmq>xTFDggc8|_;`-$#`l1ib$}mm;VbelSLEy@c`EfP z@Bs>3oV*ip(3148`@<>2?I}-j47p}Fps2Yc?dCK=V zLy2q}xEPeSmI`0|a?d@#=wFrFn;tlVxhF;+B_2hrjX%xepG(D~#tl4HO+0}EHq>)2 zGpr?EJK7)~E225B6P&jVbKDJZk}01PT{2Z{8Oij0Pkeb3WKqTGz*`|1scZch6>bpT zBN@qvNn@;2AAYXl!PWr&qY5_&7r89gL6*w1Zo+fPQuiO}6kiKj4ewCAfNG*x4VA%N z6{q;RhrUD1E5KkhHW54qWsY(^MkGd+)o#FHy|E5+=_}3ZoK7ym-TLZ+^ZDQSp*H^; zw0b!{;0EC%ULI`*UC2mXPpSH-uBXsvD*RogJ{|dE1`mDwvIE?$k1AX~N%&lbfN)tK zqI%m&)&w^Qm*}%wRz|NIWM$H1h3^t>CM)t@-Lg`B6}POqs629C#Y0vd;9ORKp#M}^ zsXjZ&>JQGN^6Zt?8r~dFi(H> z#yTKewu*it(#36nLHK~n8WvYtzFd|77Jmx^1d-FSw?%VS*5gRT_;{v6j4 zv=E=o(oe$g)K}!qsXp39>QloOl0(P2OTsfU#rNw7Cw%h#Jn{M3gya)QaM!pcA8;e- zq!9ves!#Z(1K!&z+#r0&+fjjf*65#6 z@m%AUeS*7lpX2Ra2nIUZyd2tSj{Be4&p&Tsn_={h9C@G#I8E$|I8#`Oz3G9+b^8Pf z7ySlYJe{QrxOg>_b_*gIfVcC%!pauNQ^m!Yhi{FuIy!b$x`5{rqAuXLa9rm^;f&W& zwC!pp9o&&FT+a}eY$9d&f5r7b2D(I6<;at)C(XaW1K&}&+2?6P6k_aSbXbi97garC;-Vqe_>5vL9$T@n%Hwjs7ukFIEIB&~$@$_0K zyIuZ5_!U+YdDV}iD3Vbgzg21Wd)sTfC$Nn3N@>q}u^-nIFXjkujoc)M1LP-Lz)!YJWDMdJQDwAk8XL4NQifV1)ynHBL(}}UBb^Y941j$4STknW#Jv=sfsTS^pbS@eGGyW zrT2>R#z;X;ZKNq#x(sTVEz?9tbJSOLTbpQaYm+CnwXrPuy!HYu{9sSO{h;fQvlmv( zgGJcYH@~CfviDy!`_A}vKagxJ$WZ&w3;`u!(*1qS5@<>OCaKC$?d?I+vsKgsyU zrhxM^O;%>cX$<#)au11_ZUMg)etDwQ&DvHzrhm!!3H|zyS@Ou@#Rnfde z0WxmM!6l0i9$dWSpy)TQf9crqB?{=#M*$KXLE{GoXrZ;m7w1mbW?P?K##WMQZ5IcNDB9xn4uRq z+=CpkP!H{YMNN=Gi*MG~{!emv2tj{~_gb@-j9X9b+(vS^zJL9h{yyH`KBW_z`ulqE z|2J%Cnpo=N?d98_{}0%NiR&f~F378?$txJl77r;XsK&b?>~`&)v_x(8$@N?e&QL{4 zOCG89>)O??w$`sp7r$DP)KGdibf{m~E?tHmY}TZx$x8hn`hHj%D<;4eh|qVF9iN|g zQ~q2U%NEERXr5sq`2IOO549T8bobFrV@zv@_rm9(J8|1qwelT9yo7LMc<7jCDSFb8 zHf{7z7%qQyj%atFo1xOpxPfkx5nec`W^n38V+K(N-Fn?7F++;SKKJlqKS65K9mcif zx`lcp2D%NJ9q`-L{7e??&4O8un1Kt))8$kt{-pey{M$*kpPu|P)&d$!G#Yx5Xz1BO zjBK)f8VybXhe}%5B{>yT-jm|x#u~ZtB+_;IDKdb^CW#~iog|+l`C!`5##dx7e#3VG z`k!&SD1x37BkvA$$s_Ta(cq7>vpgS{80b)s`v`|$iisULzH#iBDbLNG6=!Lz>!0-6 zTZZ)B=Fq;0Y^(UVmtTCz3pj={cI?9g`}A!X-gjs(=WDX8?a?J}Phszc)$dLD1(Jo|n=Fz@so#m7-)VBf zcO*kzPLrWl4s*&|n5!m3Kf8b-I-?)?NrJwQx{eBw-W1Wi47Lno}Pbh6KV@GDmc2{p$hnnOdw zN)tw;rlqBhsH4AiI|kxs$9)x*l>?>NVsl7{Io8rGm_0mf*pVlO;pd4X!-kEVHS>e_ zXU&{B>-`UA&ca!eayqYR5M4Pf)bpAq$R5{UB-7E*XP%iq9|z?x)1ggP!hJCTS#9@< zoAg(39=3}v=V@P^A2Kt0AN7(9&oLi}BDmPMtDm>8aRjb!^X?jO@nX-@S8Zg~1AgN( zb|3}-KctD%MwT3JW)T+cpFe-Syp*j((%c~Z73VjzpL=cz+_niMFPi8!iAzx*`VhKd z30BWLa;YS_(+DQ<+<|NodtZJaJU4R7(4loBcU9b;nO&6MbIP3glkFLqY5FT;&Ut$c z8n|-Rz=1(Q^TPeRjvqC$$;Y=F{5YIb-6TGYeu+}D$fI~WmQ%83K*hj;>mI)Ena6tc=xo zW#wHfDl5~|t4C+qs;lqWR9$V$%Csg|4otRI4XRAGO5IaacBiJMq*e_|NzDkd*~=yr z78DdtC_^R#Q(oT4xkbfA#dGTO@?P&3pO6sWucSNy3w4rjCgi&o^7W_v`3xt^NWr;` z!IH?+cmPJHNZqIEHQg6#tHEG;b!{rdxiPseV{xxuQPWD+mJg^LxNd)CW&Nnb_+IkQ z&K}*6oo&k+H{O;dKSWZmelV|RMdi9R6%|vae(~Py*6V znJBxKm+kL@Me2&g0Se#H(=#1*oW;?g=^v@z!3RY>mb;l z99H3i^#?B-g%!vTf|*vu%K~g4ho!n;1%U13FwD{_UJ%-Ll5&d(%Uv*cSa`B1il9wJLBY!G0p#6;AaufQ-@`m}#1ozwr5=fO7Z}j`IdAx;jcNBx>>3};LLHWccdj>DGr&(7 zdk}m~VGos+T^iFUzaf7pf3$Z&v^e^KhLMuKHNgM)W1JuSk@~^EK}62v>Kt;+C%E$W4Z?Jp}FKW*Ql%Ik2#Nz{%SG+WON|583ktK>x z>Xu-kNJwvsxq9;C8*jY-ZLgh!2d?dP?|ilfNwGGwtMW^&t*r0n&6~$C{l8%Ss0gDs2;c7B5}a^ySjx9$iuzUVJer zzuq<>6A1%{#SW{SJ=r!g$y%FUQj%2>Gp?q2divPh`e{S-8P4C2{)1HmS+c0Vg!HLG;7j^1Ea@|9nDS&8*a}SIcU>e zETQG$q17o>$puBdi+b1A_nFy!*0{~9`pnO?O)nTxSJc>j>9hwo!dEGv3rG>bLA78PX+ z>^E}t$&+2roLoJ!B*+#O^;+qGSqDuC(y9du^ zQ_jbnyM)P1!ki3wr$C<`g}l2^#tl=VEl3?yh<|lwaRS|bfd~U)U@7dt+ZT5%zeoOc zhjfQL4)2$3W`Uda?~3yK@~84vHvH%Jt{r75EP>6ITYr8}U&Ys4&2+}g&@CuQhv#dE z>(98I#KLrms5cQd!>*fC+_Q`Bf3p0OLjNZu=IPj@kvo$^;*C!mj{58r?~C7+ZBMpl zbx#is2@p;G=B`P)^sp{wQ&*eS6dhwQr)MMLe%f~RwCyxPN{Arw$dZ}A$)}~r*S}pw z=;?JE4?fv0A>Nc}3evepfze{LC_WnA@Uf!I7dkQCVb}6t#5>;0WI}b==QBzTOR8bK;8{raxp$ zOY`p=85O69G= zVcoopUHk&ga(;K=ot;x_W)|4%wk>L!>?n#g+t?q|!X5Fwa*}fsVk2^G`9m|h`T71m z*(MJ1=@w#%D#)o_no!(4bNqkqn!9nuvi`SaWQRt1`=pzae0<`}L;Lg{JNj;MTic#H ziX-wu!dB0!xpVr2rqSd2?Y+J)u4`BSQ2(yz3qjWdW9J_9MR#2e#;g^xWn01oY3$Ec)B8RpAFdlaw)Uy79y@UI)atqWD|&9Po40IA=|?k;49_Ym${cYJ ztl?%{#O3%L8IDYo2{c2REU^@52q6Q9uH{CYJOjKO!Iq?WlLcAK9l2IZ@N4WDwxV(I z7;mq}c}e4zeewO9qww=4`*hGFPC4xRrxqB!oxdX5|KIrq`L{Kfj&vRp=iPSO{0X?? ztKaL_T4Xm9pAUT4E%+B6Xy{fz)(>P}O_~}(e<@t+Q+=Rtb7HqtG@a)-xAK4u9=sDaPJ?kF_V>Yjo zViHO}7?YVMT`v*>gRE@pLFe+?ltlee>CxC3yW|VH~-1ivvO2i^jj z9Z%O9;ZYO31rtfbZnR_|LRrc}9(m^x+?(0w@ZBvZcgyxYue98KxZjapY-R7SPL368 znguWCAI;~Roqy09!K?ZF`SZ;T3j?yNI_Sm)=teF+@DYQKSMMo60;uNV1vI}UDce70fgOT(|QF2Q@hYdmKa3fdk`Yuz>FAGb}vIJHgwBj|yT zyuHiUB18WXqj&a%xp((0{D;;0%bChv&7(5BoAbvvuPYhwL3;YyRHEZf5b0uMCyd z+o~M7wQqfNbWrnzS1xZYEA(-G>tLS*WLIwaw?luaxq5l?>fw#S-5icbxufZUq26a!A$8;lTy7t- zbW5*M%f6jG)ysF?YCoTqj^ebH`hn~a@)XTuJF=r!q!eUUd38OC%V*BL6zEIsm2`&o z^U^ywmllSoSu&k(S28tqP$R`=ha}=^1lMiz0X-Oh+C?dP+3AAP_{!nKE8|NG(ued| zcJGdrDb?)FHO|&G!mGUo4CvLfqT<-EYuEm|M!)lDcJ$tRw?7b*{Zw33+l7mNMpXX! zmMA^AZR7GFyhK5=4+%ydIRuN*oWjt>}{?qMX-69hivAqXtl z*PK{`E6qlaSbo&fe1c`1m|uBh{D$4W!g1V*@ps9m%sOPmbBCO34Beb9iN zI|{U6tjSJO6?_>(?~GPjnI@X`?2VnTZP*=*I)c<1zWdBq&N`96BD>13h$mj%x}yI~ zs;K;KUW@d2|M7#bzch0E1jt0tAu1u=&1Hg!QX-2-_?62A4uur!EIT1Q+x8^_!v_b+ zC!F1d4=?zYUvLR!2r;81UHO1j7zW@`EgDM9en>y{-{gngnJ2rj!$My9MqmF;PZ0X0xM>W*ff1I?v zrmn7rZnxUDW5>4b3#9+4xbMWYDSxj-wEcdRJ8@sd-XP({#CwH%qmD7S(l<>!!QE0*;?=G-*; z>S+8M6%)C7b)?W79kF_KM1*|#Um|0VuyIJV`G`D9eh?QB-{WhuNgvp3*QZHCqY{rh z_Z~}>a;_hVN;ob|IGzB15d%qj5pwXxjF*JC3|S0r2w@-XA}(w)S(GImhA1BexZg_= z5>Gk@{t_WJ@pzwtf=NkzhA;Ws=jmf}9+x-lFIqS$P<~A4^U?cF-JQR(Zowu~@Li6? zft3kP+hMkRXJ%H$S^1yB;ILK8U^-pPws*#N7ambWY33qiy@z#Ar@>Eh6ktZSOOwE_ z5gIq8IM?6X$GfYKk9VM#w^x9-w^!f5uHGW^5Awsajt_jibZdhH{PEOOAJ}EAZ{S#y zZj3Ni8e_<4ldoR->HVJq&HO0{J%7g*gVXq!Sy@|W4A7r71|WkCf9cPTjALqy#o}@C zMj$)Bf8KuKnRQDK&)e%bh&iTFj$~gqw!?ThUt(YKM~TrwU+|38q_m6cnli?5EsZNn z*?8gjYtD*#sUJ+l+3P!DlSZq9yy@D%oA4ITyvRn-UMK_YnZoCF_)Ph7w7fdhhqMpX zpj*Rbj%!?f=jt zCt3d|o{*n^(lo$iVsonPHAAuoQ(uX+QWal@eI~1f^%Ap)Si3naxHH#IFJnCGD_CB~ z<)3Y{Ow981d#hGIy?XG8^b^w9HmRveyuWRVc)t+(9dC1l{FOA((2QrN3v_4OhGTE- zY5oMY8JCdng-n$1H{S65e2?$zsl2hzEz8#%P`=am9n0VN{Q{M~5BR$YePgjl{nL2; zeQ#O+O};nwah3lPic9>L+@d^vPyBWKUgIx9zG?aYKl;XgTK((~-o6fUhpPA0{Zra3 zE~VUirW|HAV!kmO`?C1@ed3(9E&J*PuNwN$vagaj2+$h2d5&4gn4 zQw8fYH-}Wh-41_zKnoae3#tibR`IBFCK0A0!ggW{b+Ie-hPRErs{yD(`#>iVHO5oj zXrUc#6`lj;XEnqE$|lrMn=ju$cpv9qcLHNNOdQAM>cAR=8DWG@6tKNt3A5%qw=EZ~ z1BUaB>leRc0W*m!xZ z=8#LA*J_AAO|OU!TH=6aDZSwUO&0Jr%K#m=Qtgd>a@4)|uqz53r8o8|bVjlb(qeHO zt-vWwsggkx=8*sLC~OFBy~kpcY@ib1P~sy2%U-~Ty4)XW+iwd!3I=V-g&5_Bu zh5dq3LrmCuQxKb0V2#3-fz&%cXL}3KAx!7VCluU_KBNT|MFj9m5f^Twu?+U)+@nR} zygFL! z4znM`!yw@ndzE?W&T*lj7wFQ*JCJKxe>>rX-+EbX<0c_<^z^5XZ-E4rt;gPK;bC zqYPfok5!?pSOwxoNb0~3B0#W)R!`-B;Me+V&aXAe2$2v?7C@eoam$y=qi#>7&jzv( zscF3PYgc(!TRh|ePlHA@hK|}j;twq?&TLohE3Y}HxT^;19x@;=MKf9$?~o(Sbi6xzPmY!5$X#nsC4PHxK^L@rvF3 zhV^73^_8keAcGhRagMHWF^@hY{;9V@T}}8FP$H(v9{arDozrdz`sG`G$T;Ls^i+$V zVqCh!+7umbHU+{3^$7|HH;45epPmwe)nZy=L1v5-vxPcutn~2?3N(j?MFg9J0(^a1 zQc{z1vU}#`*m@*|2NN%RD)Epd_~;HkT(VRQ0goLLV_40ReNY0p#2K3@^mnysdrW3Q zVp_N0kdT!0tgPN)=J0?ZaOe|gGKYKgKyY|c4_i)N&+MG!)ZpM2AK!o=b8tjhs5vmm z8;eTvx49h#FA02Y*HH+#%hau3xH(A?8PA0c#&A18Cn1V6I!I?{i~P1GABIf1-P1F( z@&m&|g8cowXLpdQ6yHHymoB*kwzM$Y0p7bEK->HyLc*7J6m!QmBRbRNW!C3N@-`oW*!qFf$ngOxV6D`G%OoBQR4$n?ig=qcJcj&=?IB^4D5!@H2QD zBZ4D(M?{2#c>%-Q%jD%{G>Tr~!I9y;BS6U8;A>QSSy(9s1jc#$`g;5MrC8zv0t17i z6RdvNo964C;_WAiF4MsDdY{BDfq_A>)U*oE{HqJAu6S0sC=VBx zMmw*vR!-yZpb@U0$oDsC?j@XGb}wrBj66YMb&L3hi-+qw#5ZmzXQ5c9+Mb?rY>Ti8 z_zCbQ#W&jWrRg1b_N)(21p`%k#qMQawm5HBD`gLgZ(QG@ReD2x+W4RaeowWkea<^t z*n?VC`=se@*i!=Cd=Bk1OEuKKM7|kcvE#xLxsNbGL%%FsXldI(pWsWQ7|LNp;?CL8 z%05#MJ|l&9TiVvU_+%%Y4|L#j2&itm@bc&Wu+_s_JuMC(CNBu6;saw}iwV-SZvEnemAx z)BP+uw!ks4WW><2iu|6@2~5aQE8Ax-OSUB>b;AYZCUb%{Gs7{obU;C_B`PX9zp%Wv ziexHK3`crM3g_!?oyoO&5HX{AtRPlPGu(>^p{N@B6u7nj)#uDiUC?1k5oo8l zBs5lCfPKT4L+6w!xur$ax3rK!b7s?gFFsA*!tW!0O}M}9Ar|kPqWEqAQoqB7NlU~( z`STAlTl@(l%uxqJYzBa0iTI_dg!b9dlSjod7k5NeBqk=k5>{P$}2Cl4*TQ!395}qS6Sj1m{+O>ekyyfPN^3}tv zNSieTEZV4kr41BIQ23*DHyn6vkuR)lCgoCmO;7&Fv|-2zAw=aftu^2cI|YS*D!f^^ zKWP{Ksn8&4h;!V!eh0=0yhm4L!CP7TlYF%5m9|{xO09%7L?h>iSa-hZj&NX~2K4$- z9^U{>SLDH4l_O*%+FUURDyhajI8RDfXfmcsNzUYh(U?^ER3!r`Cb~waC!cNaD-BeL zu?5`CfOKAQjYw723Qbz?SY3e|MJsZc?^zcSHI4%n>3vphs4}pzOovWs?d9txigIv8 zP_)4=Own4%izL*DtIm?#czDM%$V0x3n;)~%`Dmh|Ey3dJHz`K^D4n3heQw|<5dlUu z@}p=8o-mx@;g^ zPM)i0&56RYUPRQ^Dp+K>rsm3--9!jYuKFrwW5gY5eO0G=Y|O|0_?jAFWlhcR1f{;I zdN6jGR&UkEvGQ*%sQiZZQL7N)fqoEz#_wU}Epi$gqmLjf@05*e}Yu@*=DiMWAYTNT>_&BF7H zuz4(^s;1_0$F{U>q4I7S>!C$DM%v=YK#-3svKA3QToWC(y{1LuUJlfR!bJkO+K(>b z5N(%i6xvo}pxI$^ai}c7h39K)YHEkL_|zl@>D2IA`?%|3|5ED*qq;rquS>b&IGm+G z+%K3%Jt+!D@y~k@?JRJfquG3xU@s89L>#n0$eBY^wews7joS|8VbLjcNK-c6<%s;vT9$Q3;9~Ej&DG7ysTF{olmTKW52I1X=YWO3J`w$Frj_&8=oyrk069_8T! zFuK1GzxH6Gm400-#JdW1-gn=9g_Z{V-8pJ3O@c6n!peS+LZV&Z5vx$BwkUP*zIN$h82XCV@akoHS||~_c5qJ? zT#{?}A-9Cjws`--3oo?HZ}~&3@(+9<-SMP{*cr-F`FK|-P@xZ3L!qZd1Fu~Zx4ifw zXka<11bhC=32HW$o{cEazg$L0Pt@@uo2nIJ%b#z4UUkEidA0>V;7fGzrP0xXTqdJA z-eC%kcX-6-u-EYscA$j`vl!Mgipwp_OP_yUe)IX~U3TBi6DC>3D9}b2?8CAPPu`@U zM?Y|;Zo-php>XYGu!xsO><)(_58zzn6_3UW;E3gdBgkEyi=$1HJ)oYC2u^#>fXeDt0Zc}DHcdApt6z&&pxnmG&g{0 zqdkm4A!#EHwiSD$4Z_=vr%yGU!$zDs-U76Qea_~bIwfzBf8DsT6bG_)r;L z$ijzcVoLyM2F4=*n;6LH5qApBGeV=B0GWW|o6eATg=MEsIah!p`;JpH(@`(zsU}-r zaEbBFu<@GHgH~iP?2&L&{ru;O1`vI-@s9Gci7vw8?g}C+ENd<+a}Mf29Q?ZJlYbWq z`U-gy=CA1c@wgNhh+U-r97dvU z=8B@q*=y42Q%#MBRq~`X!dl4XB`D3Q#>Yu8XPj>c`5t`xU?)io^&SZsEL)9TPU38ar&phdHecQ->^$q-e|9tmjr`MD;rp{tU8pcfLVs~$K-wsk z!Y+UC%1Tr0dTQzzJ?nL(?(7{(~gV4lYQu()n1k2|~lE(~TGjA*#^i^%z=Wwe$T` zr-YPKrv`JColiD`bV_?>8I7H!*z>`(aE7vF)2;;1U5}^|>9GO@V)fXTh|Phx7xgt$ zcFn@YRarsPr<-hp7v)d3#zq>XA6<5Qmv3NZS&1#kmnF%c`1z++l;i}mE5-Ke!M46F zeY0!QlIi&!%_z#ss9RuGR$#XlQ(#7B0OYQ%)p&c=RWbZFleTJOY@fP3sz0SIOcPuS z!Fn-;?5XR~JnVKm7V`RWe0(ZPH3*;P6Qh~_DgLe))M>eQ7C#yxR)mF^x_mo(7Rxb( zZ;v^F)|DNeGGHkbEJnA;kGLkzQ7u>qUEx!_@)YITH9nua`h#eIGfcRy*$xinQMz5b zg*CXO+kzEnj;g8;E2b}@8MN=Y!T>4)srsSHu7EQrTXRM z8Sq!I_-<#n;zep`hoe>+N7+JaC1pj$TvDZyvd&IT|=`y+D$g5GhZEv=CBy8 zD;`~)x0*l5r~W;J4;@6%u@U~E!7N*O)3Iz}@dHR^dm`a|^z zwWpi~G?v*hqQYxkO>~rs$+uJJ5#M~z74~%DBoyX5lf}faRUAn%gejNg;iF{7g&BhH ztP8T^sLgcK5YZ$d%tcg?)hNr=S43Mb;e8?EpW2i5Mr}rnP{1v)}LTYk4y$ zV(?x1X57fny z_0i+Oj&{(%teq&x$+asN*9t}hQ_r2FQf`L?zfBD@$4)r9pdmN0OKjN-WwYi_VSe*+ z!io;uDZi4IQC@5>&q)gzxqDSXLe#K{e}C!T`v;_!4{2Ca^?2H$nBV6=K6j;jV(;y& zwkbD1z4yf0ksmyPUG=0(M`7=yAS*l@aFB8oZhyhm0fLRKeR$dqV8z> zeksb3gQy&3!@wMeP205Z-Grj_a@hSD*2LIG7brzJ*GKFQuV24G{(+UOmu*ar*b|wt z{*rusJ=?6mbS<^9Q6)WgY^xm1esE5gyRoa_OVka}jhEI-2N3_r)X|ecvvxEe8$sx? z7y=XM8~$9gH!k1|F&oHS(4rlq6_3)91`R_oxwFI^r}oVReog7gUO zW1oWm9w_TyP?#SX7%n6yBp-2p7@t&jptO`g0n+{n3-gM{%$Yf6%;2i(4?zbs|nfIhe&DU2*<#VG5h;j3MN6 z5)3Hm!d>9A8aIxG;{)F$jPV|q1ntkY(>ur)7byp`Os}}K`|H_V&%RajG5xdNO_8Z(1@6sB9Ddqf&6jfNKY z)jjEz@uau?Ngw-Ddg;ffFsVOflzx1YJ*f})>`B4)lnwwh06|ac05I8}>}Gq)AFu$t z0;L~WW)=(PZUVKa2MfUFc6tY4NmXq>hV+_nH<#5nt5<)+Wp($2ULnH!tpoB$wJ!gZ z37;-+9hHv<1s&y2`-gE6pW{febaCdMB)sc~&5BZmrK>m+G z{>@KplV4`@f)+PaRP>1TlHbez(o_{f*mHHbUK>Mcenql4_sAveg+uH`xu5u5>-CvzKr0(4KhrAzy}eyG31`1? zG6s8*gZRGPgSsP9sx%C_g|NDpClU;2Zpy@i;wix9As@lJ99G13i(AF-kq;^fc}$tE zu>B)xpJ5+n*NozDAFP9QdSAWdWxz2(FQX(1M!n8g&wO#J6dB66bS|EL`Q;$&;5Jzk zF&V?bix-=^v-nTgd-rC@hULEtmzR!rChAYF{PP7dpYz7+FfOD$!|fB<>L7y`W_7ed zfltI<+F~~xvUyH-O)`r=qu+q1p7rNxy%-K=QxXNt6?9g_jM0h17C8KD7h3ZgdY0GM zl$1bq*_vV#w6Yici^R9)mvuWiW)8BvO@wacg zYr*o33+`CkMEWA)8TU2m5UQ2n{kcMF%yd zWO6+W%*PLuv5n`=qijFW8L*?~F*6u3@NpW1Gj9U7TB1A8RtU%QNA)TjHMF$v)VJ~) z@UFI`-?U{J+ea-rd|+AaomG8S4O@Ef0W?LpZEe%)8Po4vFkfwmu6@DsPxd`}(bXLE z=TchPEQFL5n9Iyn884+K-t| zX9pUVYb~tmM>goBd|kdS?Z4hA9&Q_oIz8}Ac6tOC-*S@anf|2w^pDd1wxQzT>y2a+ zHM|7)&gv#6b+JY{3e>#>>U=?I3tGa$3-iYen>wwvZ+=whVLu;ZRAt$~;XP}EyGVYI z3nkx-pInd^8&yzfpV9D>^95o5=sx*f^JAlfy{oG&~pcDFb_&fQ|W zEzu>3{~cVc$x5GVt4N5mMcC9gk@5>Sfj#H?+V$mf!|0i{$XXJ0PuHqH56m8-zWqNy zVY{B!t(L;1RRLBn%1oU=|I6>nBLa+GyIHn8g4?$jfD^3X=tO)+IPU?Ma55Q20ZM+W zTP=L+frIae9xv}v2dAx-$NyA^Cmm((0i7f-tR(3hOm7LWX%*mMjkF5yC_g5iH3Y`P zrN<-0V2ik+tqrTDwpWDjogvaH`MlgDpBIK;dP4g~pxjayJ*x3ua8CcZOV^1(M+zNwA1N-hu=t6dj*wW%H@7ErtOIQm8DF?o z3e8}p1|AP_fK7w#lLz^R%&i~1xl#-&>Y3{+#fCU~K2cm4 z8YlVK9cTy9);)oCmGKxLc{bYNVepHcX~eRcPe-&0p;6{+mFwKB^r)(}wRHnZ*HxfJ zLz-&W3f1sIIP1Q?er!aHyfv<85t`Ipz877_eFB^STq5pAUq!(}qKEWcQk2faU9X+X ziMtY#g$v74J0YuTQ^nwIHDgyW%ly$L>&5-8El(Ea+5HpDJ^MV-+u`tc^dg^wjRpNz zK_3+oefAeU;aS7Yx}ix%mEhBfn!qwhfv+ptPaqsQyDsYgTlLdR>|;e{M>M z>wDCe93Fl2F}Z2?WB-$=mtvCh4-Yhj2x5*tfWfmu3+r?*qu*$qX2hOa-dYO&->k)? zdY(ch-|Ge~v{{EMYAAeo_~pam`3^1j^^Q}Nk^DOJA?h_zY#`C&dAqi=;4e8~L;hq7 zHpn`mdCJ_hKjjS@1f6r$#~b7eI#* zXby>?Wt)da^X`Jo@SJZ7&W#W1FVAA{RC*iSL(^ujC>XwHh_9cb-7j*o*I8cDQx^RoDfGuCh2O${L%MnJVT)GGEC*%y(aq zE^J>{DJ6Daj&)y;$h@q~NL@np)|)8v@( z>)8QcZV_^!P<-&&X7OdbADs&b=3kic&~i`}}V?8J@wB1Zf# z+wIX;E}O@&cBNOKIw!)^lDpk;QdE|j*RQB^<8Z6(hRG2Y@34ID;lpA)pCqxdyu&Oh zz*o2oSzD2V3r_%av57g7*_Ifri`54wSmX3LVwOBdKF;b-Jj;eVli3zFKz{VZv-01B zkMsSKgsE96sS&{v8~%lNSj32mnyNuHv0>g{un|&lc$%f4z>*doEXjZS!VnqKP+mK* zdQhU-_Y1jI42eihxguh}YeC~7TS1?mc6)AFUiP8Jf^uuLSS&?b%Zo-HiXGUi*ly3L z%IwL%z&cf(Ulrah&^U^)A;xxd?r1y+Q~#0&=Sy7k<8M);^Xpdf)A*dO55t`Uu`a*w zS%M?);1U;H@yDK3{jz5jzs&g@$Ggh$$g{iG`J$T+vJDcQ5$#u{+d+qa&z|-8ewOn^ zousQ^J)||Fl54`3Vi}ZP9jmH%y{df`SMekDYP&A#+pY_}<)4K|<)5EDe3;$W+Iq9{ zcs_`yi+DZ>2~jXaT7&X!N2s($fd#Ogn2-Ww$6=u_+*M8XUU`0j23DtQ*v?p*tQ`5GliRA?|tSKpf zyS=&P5IIhLTZO~pOZ$%xofgfsvh!~+@yoP zdFz9ZKm7Dvm0<18qdUEY2aoOq&ng|<3r7AA_E>2gJLpKbFZT44QN`>1@ArSV`LTlv ziC=|!=Rwvg55IMJlO0F%#dvr59S0xV{M~+~yoig(SgZ4(yM84%EUbc7zX?bCEk={o zXmXKwl64t6jQM>$?9)$%s!e&E>DqMC9J(^yU=M1+n0;}Y3ftcCi)VWXGKs;S zNzl}|lM>aTT~$D%&_NOpM;R!8eRfiuiybMuI6iXb%zi~hMI}GV??@GWlgbhjDwD>| zojz*Fn7*tqE3dEqjeh-ti_!-)Gz>^DI@fb*&z@6N))O32i3xUj9~*0rEa@e;#+Hb(xWX!O_!Wy-69_dxEc(#0ul@A^?dWifcE3Y2d zh^%Qs;xJn#IXK#Q`Iz(IOIba&-Y3~2FrAHTqdb?d%iF=YeL$xR-al`+oVFef2BEz~68X$v1kZ0hneRkl85h0yV`SvG!Abp7Q_T@w ze4@j-ua$_o=`#HBp2e|U{y*Bj1Tcys`+KUoduDQHGMP*WIhdS;DB{$e)!max0C(O0 zev`~hPj}U;SFc{ZdiCnnt8iF2Ra=ccJTkN<#vbjAjfsp1cf!o+4AG)&GB|LaVdR8@ z>F=^XT6Ebj)k&;52E2o5=M!nrm3-N63m!f!cGq&dKIiO$hYzuSwYpF?v(A(LzWvk= z@!I6~cbuX&k#mvDOnOLa&|HKhNT9OR8I7sM5=b=C5krCZd6H&mhHM5?1G`Tmfhp*n!;g0|4RMRQRBoyiLGS_&kB<^QHuPZ zgMfoD7sGo6+K9#=j}4u}|EU7VY|kE6v5l42el0>VAmDWYd|E=YY4)!azz<OgJ8p!3muQkA1^CN#ccSVL%{AI0LJ_BoU+XlIz-^MV(|XKciWuWVQ{cf*I9 zuX>TCh(|trdBaWf*B`6l$6{{Vz1_(c^%o+$@9wM9UXj1WP5l{f*>CscG~xxUwa?L7 zK(oL)2g@kTKtIgzXo}{^KpC2seJ*D4yy|<)8BU{_z~0lv4flR2KKhp3eczT7?AqL) zXYW}do_k{NVX-ooAD=Ny@>e668lYtrYk-_lsG$}aS^P9xuD=bK;$1dthc>?K%8Mc$B5Cq z+sp_1v*zOA0T^}D2JqJU#zC9;cm2BR8@IERrQ4onV+(&6UOVCE`Fqx#+WxOXNe`nO z*p;aqj}|bhk7TD-XI(Jg3D`^e z8O-`?qlt`ZFk!X;*HXJ!<@#u6cm_qlv#j!RQGl#Prjj2=Mm}b6F$(X~+n8hZgwv2$q z53~(#PQzYcTK{Oufk`>|alz%%Z0Yfop?!N$`!*9>2eC&*+GX)cWXH5-fGrZoY=#+E z|NB5`6y!&jZhMA}DLhqKJN_56_Yr4Qk(`qQ-^eiWX`%9Hxr_zYfS=rf$cn+dU<0#B zFcS(Qoa}~%ovj-Sum@jy=8b%IkN#HY_zG#%DlO~RyTYL1pe|Q$z9J=wh*;PuReZ>< z9w5ruH#a=UhxhKhe$lpFwOR^nUCGJap6rlJv`mi>2jENV2$uwn)uxWxGv&L5wfC~C z3XL}H2VQ#L@ZHUqEhbNJ!B8;FY8FFK`aiXrKnZ3G$rnK|;Itse5v%bH_Nup8z$}hp zV=ZuySCHA_I<)C7KuebUaI_S3o(%L$>iiC)^P3G^jC&9QH;ecD53wa;Kr?n&zwg@3 z73WyNATggk6ECpgYWn7iU&Y(!S)239$}9WjT)*eG0e5VBS=^Uql=} zI%d_LwHs?{pZ7o8A(@XaPDZid@ApBA9P+5bz^XEjEu%1n5JnGx-VD zQ|&I+UpY=}{)xS|Zp+;a8>OL_AnzO_ue;EuVSZg`%Sf+eJ^2YeQ#^~ax^{?>YWJT+ z$Gf+z6PI&0<=NuIuEWfEf?X%>();gai9fJ$;?dv5mwT~8>~1mbzJo{n zpWMH+!@(kD^-qV_EhyR2amhW0eqyPkFkvw2vqsjZxvka3Wn@4^Hm>1CM5VRB(eGjv zezK9=G%Sni;EPmU()d5bsR=dy04INT18u(EXVB*2C|Ojx`%RNd)aD~Vqpk2%r?JY= z4;%^woh5G1%tDhZ#fTBA6g)KfzH4iqx#HWGcZ;Jno4365E$jW;_!cGucpGkH99VD6U77K!JlW_a92TLhJ(nVJW|kE8J%<*5$01KxM+-iC5m zD_M?s)+pzZJT^=g!#uJW9-gP4kj1c4qZs0S+e6Ts#~>meZ0MHT9~4Mh;fL`U22TBj zLn~IUTyYSq#Lq8(am?7;cVaEhfb5FL63eZe~NsFIi7 zHg?R5%dwakq1^P_5krk{eVvE{M@0Xgxvdc|&U;c>tmB1c@jC)# zNxhOJHpvO7)0dz$iT#UEd;9k78=4T@oKL_Z!h%`C$pNbg(P>h00o@5)6Vgk1v;pmp z!bX`%oM7x1g%%%7e3&6k_cxJxTaKR$X9 z+NWgj_U#`OZrZ-1#c?c?Zuvs|gygpr#0Tgvr%V z8B#@A+A$BM9x5&1!}RNWZ7TeNHP08j*-gj7!->%{)B0`{&&PuC#>6M62U_GwR@)#E z+OUq_&emzi3jH04568ws7nfrJ)-ga=jAdvk_?)5WVp7?pKP<7H*)eECmO4koZ@qai z>>1z8zqL^>8Mlm=id{V}-@g5wsguxrs}2PE%eumeLFJ?dmt&VbrfD-e8W$Ap(qG`E z%fmzi&;wo?IIy8##8 zifpHvvs25LzKSRYE{UcuFR>_{TcED2JGGs^1i-}Gk-+y1cstD2$F`H_>{J3dcZNzY z$FRIzPM{cqD%f{AQIsRks*|jOlD|{U-x-!qo|2R@x4mT#2(nNZ6{_8?p4_glrz$lm zyPs{RQ7iJWM9oku@~}j$OsG3Ub~Ggc!&_W7e*dfEUwvi#EBOD@HF!KI^Z$zWDGb}5{}k=pj2H3a|1|F9 zlq;BD$WH|PLOwk){{`=}Z~cDPpJ90=8va3l`;)v5d$83{BQd7u*(!iBu$5=J8LK66 z#-V~3k@C*k_v_Y`T|S7FZeZ={0o3lGcBM5Y zAFbC~Yj*z?H@4>U^jqkC)IaDK=393O2B_ zQr3$DtFUZSL;&gh>;`!74-CM=coKl4RO|f%`S}<*1_b8=H(2@H#Uad#fWs6MB9MQ_ zcoxRO$HVC99FH>>ejCq11K^aj@rb8N55?K>%qe~!&q6MO7s)uysw?Cc4>RjXGU+?3 zZc@)O?9vW!qe&8GQ|9=WZPQf!{q6euuvy~~^rk>Mkgt$jrImO6%al3Wc-!r~?Ro!2 z(tyC+BYI-FxKyp$zP)Zs<1|=}1l4?Q{sLn!U}fWZrm1yXptMvW=E1i-hkvDv1;stj z!ZngTgR^#%Y%09S;XaO?3{*i9$cV*q1o$y0yH7c!7R%jwSbIWX5v-YFyIT0rAuRl( zp&x%dMCpL_|Bdw1S4OyH=)(dJUa&i$ZOML3>r*x+A+kcWj5^C$)G_Rh ze7Oa|$|rfk%7^G)R5N5WRwRuzCBEFM4EqhsRZZ+#EFH#I&91?k1{;TI)AGOo1i$*! zU5CZl6W9wooj(PO)(>J6yYhEfv<#z}Q6xMjVF)=XZ9c*z^OeTWUhUfL7;XxdTVB)L;V|$`Py7S@vw~ zyl4g5d0{qzIa%6lvK-Q4hY`y#-r!V8s$n-~*l;Fn?muv1Kr9C_U*CC^RS~f!bIPsC6p1u7+mF#&3J+b=1d_JIi z^1+Ng4^_2=NiRt}d`-Fs))u0(iC4Oe8f#c}q8OR>ut(7_`E-NJ4a|MTL>CR-jE>?= zC1dj=8=kAT9WH$r`^)b7EbhV0SI(+h_2_`F?|&0(Oya9!AWrL?YqiuUV5R>nzr~i; zLq436d$4Fjl)$EkxXDxe>*xHwY{yTBr!JcK6&l7H`$?ozG5D+!_N_VER;*1y0)keU z^V0}O>%%S|B2l@NK^upEiBl#|^2_wO)wt%jip?xROxCt`!#1k!+r^jNj;pc$b^Im0 z`z2uF@I<-ZOgpQ+7EA*gYsnJy7x}F-#YwiFK-QfifHXA(aQ+gIf}N9?v;a+0JMmtN!E9_`hJLlaOFcsqy@W|}Qob0-HGbb*HMNT>X@>Mk{9L zHF#Nfy)EBzvW^RXZ>wBa{%+5_Pc2XD({Ox-{o5=X)*EBh7|V57Q39)zGl#+6jWDv7 zDnz%kuEB-%Y>JY#*t|Mg{LoM)%W6RCgRQ8(!_GTwC(q?`#e1yZD+qfg z_Pj!Eau>#pZt8w$wopOxX}dZiwS=&{*im-W|2D4`4~vKSGG3y;s?V9r{>~l~SI9E% zQo5;KwX?M63IRv(&nL5^4~e(LTMubx_1^4&z&<$Oa+ml;?aFo->1d-ApDbEEg#A+a z4~bv+KGA_4l)OQBbXC?sR{$Q=Yc&b=eu_oK-n2j~YpTavz!iymSM@fj7gBs5cjMJyPeOb6M=W@7KeXh|QbXhSbqwoMtmL%hts2b^(?tJi5U;Ik-D zKV9Q)H6w<_C~5|Gr+>|EVmB>cE*6PJ%f-*NwcNp-wYBT!au-R15 zn+|!(DeC?e%MPsiapRQ2q7NTfH0sUE-@5Fma%lO1Wy@b>F*EXS8L<9n*_)TYIdc93 z9|DdY-gw`tD>RBs&=zy&9@x7y6s(1#5nXT(lYW&54=%m!@(@;>{PXhSVzK^!0~5)C zEH$%)A#yEAZfv;3#&gV{fmtDK$AnuRoZgJzNWs~WBTM$)bkp$Jvxnbw)7~XVmeej@ zTs3=k)#AmqOT?kF_Bmx`xqtafZduvbGPdc)oU+n!Wo6?^%X0YUcf`S2Rf}&LS+(Sy zC3|jKTs4b+?ZJ<#k@Snz7`epQvYhq+!aV>{maBhHw*eLvYQ#&%9!==u+mtzMCi`Bz z3{s#!wdU_C&wwvwe#y<0jWmf!v&BqkZ^T+kqWEqKgzQuT+&G6WV{PETLjl8oy1UPUeY-)vL8nrUR z{=9_1{#Dp4+F_(rxF^@enG*iu8-pfvFK(R}A7u}Tp6qf8o90Zvi7V{+p*@PaxuY|q z`e1kV`~3WRD%Un&B=7@{RE`;k?e*V|=n{-{22H^5* zSX-`L1GpS#5PqvpQ4fJHF_U#mU5w$3F^_LD8_Dj3xwcx&_=1mPHDauK$baHRCH2J@ zG5DfiwM0Mb3%MVPUJ*l)wMct|3YVrJ)QGp(2ao3FEX$!D7MJ_KQ{tE=-p@LCFiZ4V zx>U^Q*zw?@rAzsrx%h&YJolXbDz3kfvDY;0%Wa8$xm1P|*hNc?5nJ&v zv%{$&4J9aFOgnh+1Uy#$q2EccuepX`vkkn2pjIos>PB!|+w#~`h(VnSm|l46^XLTz0dy1eqwbTW2W1ehi#f^zSKfjf!Af6V^x5kZcl7$mRiCJIwN35&~{IL-g+I^+K{{H!4O!FBmxT?fPeU(w`0f#b+aVrJ`63+7*{Ej9VnN2${wNJftI zmyaw-QJzUo_Lrwji%N;Y|0v^YMN~?3bV^h$-nbeWog9t-TH|Y^@vPxX<}*@miJlS_ zH6_~rngIrBf*y`&^lPLEyAd=h4fieBR`J1DnE6aZ%@U{-{5LMoD&e9~0tHdN+0mV% zqB=$6H7O=Js;iMVQ^Z(F76Vd+#L>v|pMT0+ zCh|rV{`j-MtmYr534U7sUtwk7KQd}gR8-fTnD$(@UuD(|HxbnF_#d^O< zd8^sJ9ayJb4Hy_>n!q570qr!P02%>k7=eHM6)zDV3{ai%n~3>UY?Lthvh7M`Bb=PJ zaI(a?LtqC+_#lvzyL_)AI_VZsC8CwjMU;qEhtzc@knA-3*`LBc5mjsp+ftX#_lszD z+W&^*T0fqNX#Tm>I}KcM_8&}<(e{vV)F7A+6v;7>cK62M_)PM|#Oajq&_wx`%O z#+b6o%Cgb=YmRI6ZDUGtJ%)V^To8RpY*r6D@-dD!Cok0)Xu~)&%@yZWqcyt&x)5UB z06Q;G%5VV_pa>1Qdgl7-nJiDdJ+pfK%<8>ohT_G#4;}jJuS3~<{?g9NT3#`#RHbhv!#VQRi=|JK`NrgOusJWY8Mdt*%A zgp(wiz{Q%f=G!J~R)X_-A6a z(p!C3(@0f7*8uKH__XP5e>z!I+vVV0TXA-_cFIy;7;P_kSk?{S$8c(Qbc-CPon?ZEk~$ znVs2T{YiI4XJqAjiFH+1wC2WqzQ`pRoVd88tC)6#uerDiAfk6xbyrIxDqwu$(`a`^%wtNS22w>TisjI zDg(T{1H4QzSV1dN#j&f2lzyDwtN1WgPF$bE4hiRa5yB3&`;D#n?Kkc3Y_!;XzBTNL zqY-}X?-bijAvHLNUZiWH72RaXC7Wl&}1M0h|Wj!psx60kaHZ14zEYTzDJcoD!e1LY%)lU|1$r zNP$%~LYsU3R_%izylC$Qpt;d@Bt@AcOQBH95FdcknLo`oiQX*Mh(H`G`q&?YEVVBe zr>bhsmub&|H)7AtqIx!=8zODW*%ZR+;;%V#xp`tcQOtf{&(4bCob|u`wmyh#_T@w{ zlV}b6YSIj9xgkqsHD@=Gq8qoc2mC4EQMJ78DKXD+ZQWL7wf`?TCg%dWg+tf3F${5% za3DXUAwyZAKhIM2jRxJs!sB8gv8~n`WLqN1rhNdS%^gt{+@2=gs4vO$+k7re+vw~I z&`tjd{pb{XR)0ZUh4B)!lD*SjcOIveiBlNQW)VqAZW&`AVn=0$zfJNTt$`QW8%X}h z`)|>Ge!S8BZb(n}9UD|S zELUj39(xtAHxc8G)||mULx0M4eg525E%W+?#g%noQ_B0KW$yd+BX3;qzWvHxQI~xf z7FMQjzGr^hJa1@!gbipd2J(=w6fM*jQT;^c=8+D46Mx+vn$+!yj?MWTy_=>bU#FjB zwGnZlsxO=qZpL1j)0hdig6Dy>?zrXp4abqhKtQ4uQ=CEGP>^pDaSY!)E0e_-19>q? zKx1;x=CBjHJh@!tT3W^V&MeTr)%jlS^!}~l9aroVF;QaY)BE>tW9?lY{9uEgN?$+oZ6ywME9NZYuJ!s7 zaqO=3xW}=dz!wk9VIzS|oCBFi27ALSFUNE;?idkcXl%!LZ-s2=eZ~5eW(`pg+}`!0 z2Owt5+$TC0xA3=AJz@6n&fT7%ATJK(NZr4(5D$gf#OKPp*td>&Z72nHKQ}_~lj%`L z!7Qfb*a-hv_`@%2y}`5X^;|VeAkyfOebqyTRPRHshH>6O`=DqlFSW>v>=lFr@uyUy zyZ_F$*Cs68EPh?fHtKZ;CM>OC&b4A@Py`Vn<(v|VA6 zXI~VYJrr+g-xhVmO-HsJQss{ z?$iIK8jDh8i(JK~Oi7*Ccic=g39A@lwh2}A<7&Kkvp=lkfci`EGzZeE7=`eWX41S$+8vnQj3mMC16cJdS|*I$C0-Zksa-Vh(K zHpW|D+iWH7`teW$DH7i|(Z~TkR)z#1A8~ird)dWgTPaCQD3wGH)mDmbEKL zNy=*#;@Gy$5z;CzX=zF#emS>obK+Ox^N&6n&09VCsH?+adu&n%w|ml+lgb7TDrJ+d zygJt1At}~=SU!k}opj|yUOH%C8Jl?Jq}UjGa4G-45NMlUs^$Hx?O<$1|GHj*RWs|;^|@sFp{5!G56 zM)0l-I}H^CuT5s&xL(87zH#D>wZn|B#M3Xm{F5U-^~RdrH8-ZlD^(94>5xC@#?)pa z{_RH`%~Ee1l+Rra$&m}r8SB~PE*%ElSXz4HpbneG5@#Heb;Kgl!fqXr6-T#d0USAO z(TUh&fJjoz?Xv|V8WT(Cc;WF-jP;*(2t)yNG2`ya5k`?u{+CD)?>54<8Okdt7Eh~6 zN50eL?hKSWyZO7~>EZ$)ld7=(SfB34Xf zW$Z_eL#D7$%~&(w@~nwVVKm~d=Et~WTps@0qAKC9*|M*OP;v7ZHkU^TU4KU;`=@+| zHJRUZKk_XHCzHf-bt$3m0*48-(kQC!pv%^Z!$?RuwH6ZcIo7j-2iOzA&;-^7;u7lac%Eq&&fWbGS&-yNei--j-w@O?n+NeYYJ7Qe?^^Tt}!udDl}L)B8GD|BMeo6pMwg0ROuip9|BCwwB+nJg7HjPLu6E1Gvhr6ltZzlx71 zb&A*U^tvwWEYWox^wUnzPaU?zy{g?FqS%=;`jb=mZ*P0rwnw$|oGwx|1=9iNb=&yR zZHNZ2j5Jbxj-+w@DRx@@ijzOCO@Rg#tDa-0ckHm9ZNRf%vEVdWO0FLDt=Ts05W~#Pc*YH>thtVg>%6ST^1Tgao~S z2<5TxF!GR^ZT>02c_ea#phQv$!qLo!6=cwX-Zljs`d1>qkk z53)fT>!>b>G%nv4$*k6YAD}1YjUuX=r*xR#p68!_>gnB2zhKo+)=`ypJSk~yK5L^-Z6^CjWa;vg+FWf?cL~R=`9&x| zl(-}~$s>}t0vzk2b_=bveNt_Wut7H$~sw(PX_;rS1C5N(L>gPs%D;`s)9ySi5L zXfdKqFbwnx4{<0vZUHgq7Yv7bj+v$b5bDiN%l-^pAP2xZvAj(UcvNe1o}AN&KLgJJ z!F�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

    b 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 literal 0 HcmV?d00001 From fa5a42fc0c2264fd6aa49b3d9a4af2b825442bb0 Mon Sep 17 00:00:00 2001 From: ABDALRAHMAN MOLOOD Date: Wed, 14 Aug 2024 15:27:06 +0300 Subject: [PATCH 083/841] Update radius.php --- radius.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/radius.php b/radius.php index 09e09bff..183f2e0c 100644 --- a/radius.php +++ b/radius.php @@ -233,7 +233,7 @@ try { $v->status = "1"; $v->used_date = date('Y-m-d H:i:s'); $v->save(); - $tur = ORM::for_table('tbl_user_recharges')->whereRaw("BINARY `code` = '$username'")->find_one(); + $tur = ORM::for_table('tbl_user_recharges')->whereRaw("BINARY `username` = '$username'")->find_one(); if ($tur) { process_radiust_rest($tur, $code); } else { @@ -324,7 +324,7 @@ try { $d->dateAdded = date('Y-m-d H:i:s'); $d->save(); if ($d->acctstatustype == 'Start') { - $tur = ORM::for_table('tbl_user_recharges')->whereRaw("BINARY `code` = '$username'")->where('status', 'on')->where('routers', 'radius')->find_one(); + $tur = ORM::for_table('tbl_user_recharges')->whereRaw("BINARY `username` = '$username'")->where('status', 'on')->where('routers', 'radius')->find_one(); $plan = ORM::for_table('tbl_plans')->where('id', $tur['plan_id'])->find_one(); if ($plan['limit_type'] == "Data_Limit" || $plan['limit_type'] == "Both_Limit") { $totalUsage = $d['acctOutputOctets'] + $d['acctInputOctets']; From e85ad38d1df9885182eaa19033bbd13701adaf05 Mon Sep 17 00:00:00 2001 From: Focuslinkstech <45756999+Focuslinkstech@users.noreply.github.com> Date: Wed, 14 Aug 2024 14:32:01 +0100 Subject: [PATCH 084/841] Update user-header.tpl fix omitted "/" --- ui/ui/sections/user-header.tpl | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/ui/ui/sections/user-header.tpl b/ui/ui/sections/user-header.tpl index 2e32285d..29db609e 100644 --- a/ui/ui/sections/user-header.tpl +++ b/ui/ui/sections/user-header.tpl @@ -5,15 +5,15 @@ {$_title} - {$_c['CompanyName']} - + - + - - - - - + + + + + {if isset($xheader)} - {$xheader} + {$xheader} {/if} @@ -318,81 +318,81 @@ {$_MENU_AFTER_DASHBOARD} {if !in_array($_admin['user_type'],['Report'])} -

  • - - {Lang::T('Customer')} - - - - - -
  • - {$_MENU_AFTER_CUSTOMERS} -
  • - - {Lang::T('Services')} - - - - - -
  • +
  • + + {Lang::T('Customer')} + + + + + +
  • + {$_MENU_AFTER_CUSTOMERS} +
  • + + {Lang::T('Services')} + + + + + +
  • {/if} {$_MENU_AFTER_SERVICES} {if in_array($_admin['user_type'],['SuperAdmin','Admin'])} -
  • - - {Lang::T('Internet Plan')} - - - - - -
  • +
  • + + {Lang::T('Internet Plan')} + + + + + +
  • {/if} {$_MENU_AFTER_PLANS}
  • {if in_array($_admin['user_type'],['SuperAdmin','Admin', 'Report'])} - - {Lang::T('Reports')} - - - - + + {Lang::T('Reports')} + + + + {/if} @@ -569,11 +571,11 @@ {if $_c['maintenance_mode'] == 1} -
    -

    {Lang::T('The website is currently in maintenance mode, this means that some or all functionality may be +

    +

    {Lang::T('The website is currently in maintenance mode, this means that some or all functionality may be unavailable to regular users during this time.')}   {Lang::T('Turn Off')}

    -
    + href="{$_url}settings/maintenance">{Lang::T('Turn Off')}

    +
    {/if}
    @@ -585,19 +587,19 @@
    {if isset($notify)} - - {/if} \ No newline at end of file + +{/if} \ No newline at end of file diff --git a/ui/ui/user-activation.tpl b/ui/ui/user-activation.tpl index 7f36045b..87698b44 100644 --- a/ui/ui/user-activation.tpl +++ b/ui/ui/user-activation.tpl @@ -8,7 +8,7 @@

    {Lang::T('Order Voucher')}

    - {include file="$_path/../pages/Order_Voucher.html"} + {include file="$PAGES_PATH/Order_Voucher.html"}
  • diff --git a/ui/ui/user-pages.tpl b/ui/ui/user-pages.tpl index 7d6bb8a9..f4fdf2bd 100644 --- a/ui/ui/user-pages.tpl +++ b/ui/ui/user-pages.tpl @@ -6,7 +6,7 @@
    {$_L[$pageHeader]}
    - {include file="$_path/../pages/$PageFile.html"} + {include file="$PAGES_PATH/$PageFile.html"}
    diff --git a/ui/ui/user-selectGateway.tpl b/ui/ui/user-selectGateway.tpl index 6fd37475..701bf1a8 100644 --- a/ui/ui/user-selectGateway.tpl +++ b/ui/ui/user-selectGateway.tpl @@ -1,8 +1,16 @@ {include file="sections/user-header.tpl"}
    -
    -
    + {if file_exists("$PAGES_PATH/Payment_Info.html")} +
    +
    +
    {Lang::T('Payment Info')}
    +
    {include file="$PAGES_PATH/Payment_Info.html"}
    +
    +
    + {/if} +
    +
    {Lang::T('Available Payment Gateway')}
    +
    + +
    + +
    +

    + {Lang::T('OTP is required when user want to change Email Address')} +

    +
    diff --git a/ui/ui/user-ui/email-update.tpl b/ui/ui/user-ui/email-update.tpl new file mode 100644 index 00000000..e79a3e34 --- /dev/null +++ b/ui/ui/user-ui/email-update.tpl @@ -0,0 +1,79 @@ +{include file="user-ui/header.tpl"} + + + +
    +
    +

    {Lang::T('Change Email Address')}

    +
    +
    +
    +
    + +
    +
    + + + +
    +
    +
    + +
    + +
    +
    + + + + + + +
    +
    +
    + +
    + +
    + +
    + +
    +
    + + + + +
    + + Or {Lang::T('Cancel')} +
    + + + +
    +
    +
    +{include file="user-ui/footer.tpl"} \ No newline at end of file diff --git a/ui/ui/user-ui/phone-update.tpl b/ui/ui/user-ui/phone-update.tpl index 2f69a782..12cfa75e 100644 --- a/ui/ui/user-ui/phone-update.tpl +++ b/ui/ui/user-ui/phone-update.tpl @@ -14,7 +14,7 @@
    + + value="{$_user['phonenumber']}" readonly placeholder="{Lang::T('Phone Number')}">
    diff --git a/ui/ui/user-ui/profile.tpl b/ui/ui/user-ui/profile.tpl index cede2f77..e63402b5 100644 --- a/ui/ui/user-ui/profile.tpl +++ b/ui/ui/user-ui/profile.tpl @@ -8,14 +8,14 @@
    - +
    +
    @@ -24,14 +24,14 @@
    + value="{$_user['fullname']}">
    - +
    {if $_c['allow_phone_otp'] != 'yes'} @@ -41,7 +41,7 @@
    +
    @@ -53,7 +53,7 @@
    +
    {/if} -
    - -
    - + + {if $_c['allow_email_otp'] != 'yes'} +
    + +
    + +
    -
    + {else} +
    + {/if}
    From df5e03a827d1534c0aa11ec353e8c2df352019f0 Mon Sep 17 00:00:00 2001 From: Ibnu Maksum Date: Mon, 19 Aug 2024 14:58:52 +0700 Subject: [PATCH 135/841] add user_language to attributes --- init.php | 5 +++++ system/controllers/accounts.php | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/init.php b/init.php index d3da03d8..0a875ba9 100644 --- a/init.php +++ b/init.php @@ -136,6 +136,11 @@ if (!empty($_SESSION['user_language'])) { $config['language'] = $_SESSION['user_language']; }else if (!empty($_COOKIE['user_language'])) { $config['language'] = $_COOKIE['user_language']; +}else if(User::getID()>0){ + $lang = User::getAttribute("Language"); + if(!empty($lang)){ + $config['language'] = $lang; + } } if (empty($_SESSION['Lang'])) { diff --git a/system/controllers/accounts.php b/system/controllers/accounts.php index 4fb44e3d..5a1e4726 100644 --- a/system/controllers/accounts.php +++ b/system/controllers/accounts.php @@ -328,7 +328,7 @@ switch ($action) { $_SESSION['Lang'] = $_L; file_put_contents($lan_file, json_encode($_L)); } - + User::setAttribute("Language", $selected_language); r2($_SERVER['HTTP_REFERER'], 's', ucwords($selected_language)); From d11cd830893db6b5963f230fdfb224af7c0f7f51 Mon Sep 17 00:00:00 2001 From: Ibnu Maksum Date: Mon, 19 Aug 2024 15:01:25 +0700 Subject: [PATCH 136/841] allow set default attribute in the getAttribute --- system/autoload/User.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/system/autoload/User.php b/system/autoload/User.php index e9358620..e8e6e65f 100644 --- a/system/autoload/User.php +++ b/system/autoload/User.php @@ -123,7 +123,7 @@ class User return 0; } - public static function getAttribute($name, $id = 0) + public static function getAttribute($name, $id = 0, $default = '') { if (!$id) { $id = User::getID(); @@ -135,7 +135,7 @@ class User if ($f) { return $f['field_value']; } - return ''; + return $default; } public static function getAttributes($endWith, $id = 0) From e908ade918a5c574422cac03958e494fcd2a160b Mon Sep 17 00:00:00 2001 From: Ibnu Maksum Date: Mon, 19 Aug 2024 15:58:51 +0700 Subject: [PATCH 137/841] payment Info --- system/controllers/order.php | 63 +++++- ui/ui/sections/header.tpl | 414 ++++++++++++++++++----------------- 2 files changed, 263 insertions(+), 214 deletions(-) diff --git a/system/controllers/order.php b/system/controllers/order.php index ac4151e2..f8a2db2f 100644 --- a/system/controllers/order.php +++ b/system/controllers/order.php @@ -48,24 +48,71 @@ switch ($action) { } if (!empty($_SESSION['nux-router'])) { if ($_SESSION['nux-router'] == 'radius') { - $radius_pppoe = ORM::for_table('tbl_plans')->where('plan_type', $account_type)->where('enabled', '1')->where('is_radius', 1)->where('type', 'PPPOE')->where('prepaid', 'yes')->find_many(); - $radius_hotspot = ORM::for_table('tbl_plans')->where('plan_type', $account_type)->where('enabled', '1')->where('is_radius', 1)->where('type', 'Hotspot')->where('prepaid', 'yes')->find_many(); + $radius_pppoe = ORM::for_table('tbl_plans') + ->where('plan_type', $account_type) + ->where('enabled', '1') + ->where('is_radius', 1) + ->where('type', 'PPPOE') + ->where('prepaid', 'yes')->find_many(); + $radius_hotspot = ORM::for_table('tbl_plans') + ->where('plan_type', $account_type) + ->where('enabled', '1') + ->where('is_radius', 1) + ->where('type', 'Hotspot') + ->where('prepaid', '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('plan_type', $account_type)->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('plan_type', $account_type)->where('enabled', '1')->where_in('routers', $rs)->where('is_radius', 0)->where('type', 'Hotspot')->where('prepaid', 'yes')->find_many(); + $plans_pppoe = ORM::for_table('tbl_plans') + ->where('plan_type', $account_type) + ->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('plan_type', $account_type) + ->where('enabled', '1') + ->where_in('routers', $rs) + ->where('is_radius', 0) + ->where('type', 'Hotspot') + ->where('prepaid', 'yes') + ->find_many(); } } else { - $radius_pppoe = ORM::for_table('tbl_plans')->where('plan_type', $account_type)->where('enabled', '1')->where('is_radius', 1)->where('type', 'PPPOE')->where('prepaid', 'yes')->find_many(); - $radius_hotspot = ORM::for_table('tbl_plans')->where('plan_type', $account_type)->where('enabled', '1')->where('is_radius', 1)->where('type', 'Hotspot')->where('prepaid', 'yes')->find_many(); + $radius_pppoe = ORM::for_table('tbl_plans') + ->where('plan_type', $account_type) + ->where('enabled', '1') + ->where('is_radius', 1) + ->where('type', 'PPPOE') + ->where('prepaid', 'yes') + ->find_many(); + $radius_hotspot = ORM::for_table('tbl_plans') + ->where('plan_type', $account_type) + ->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('plan_type', $account_type)->where('enabled', '1')->where('is_radius', 0)->where('type', 'PPPOE')->where('prepaid', 'yes')->find_many(); - $plans_hotspot = ORM::for_table('tbl_plans')->where('plan_type', $account_type)->where('enabled', '1')->where('is_radius', 0)->where('type', 'Hotspot')->where('prepaid', 'yes')->find_many(); + $plans_pppoe = ORM::for_table('tbl_plans') + ->where('plan_type', $account_type) + ->where('enabled', '1') + ->where('is_radius', 0) + ->where('type', 'PPPOE') + ->where('prepaid', 'yes') + ->find_many(); + $plans_hotspot = ORM::for_table('tbl_plans') + ->where('plan_type', $account_type) + ->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); diff --git a/ui/ui/sections/header.tpl b/ui/ui/sections/header.tpl index 52c566fd..a75b6de3 100644 --- a/ui/ui/sections/header.tpl +++ b/ui/ui/sections/header.tpl @@ -248,7 +248,7 @@ } {if isset($xheader)} - {$xheader} + {$xheader} {/if} @@ -318,81 +318,81 @@ {$_MENU_AFTER_DASHBOARD} {if !in_array($_admin['user_type'],['Report'])} -
  • - - {Lang::T('Customer')} - - - - - -
  • - {$_MENU_AFTER_CUSTOMERS} -
  • - - {Lang::T('Services')} - - - - - -
  • +
  • + + {Lang::T('Customer')} + + + + + +
  • + {$_MENU_AFTER_CUSTOMERS} +
  • + + {Lang::T('Services')} + + + + + +
  • {/if} {$_MENU_AFTER_SERVICES} {if in_array($_admin['user_type'],['SuperAdmin','Admin'])} -
  • - - {Lang::T('Internet Plan')} - - - - - -
  • +
  • + + {Lang::T('Internet Plan')} + + + + + +
  • {/if} {$_MENU_AFTER_PLANS}
  • {if in_array($_admin['user_type'],['SuperAdmin','Admin', 'Report'])} - - {Lang::T('Reports')} - - - - + + {Lang::T('Reports')} + + + + {/if} @@ -569,11 +571,11 @@ {if $_c['maintenance_mode'] == 1} -
    -

    {Lang::T('The website is currently in maintenance mode, this means that some or all functionality may be +

    +

    {Lang::T('The website is currently in maintenance mode, this means that some or all functionality may be unavailable to regular users during this time.')}   {Lang::T('Turn Off')}

    -
    + href="{$_url}settings/maintenance">{Lang::T('Turn Off')}

    +
    {/if}
    @@ -585,19 +587,19 @@
    {if isset($notify)} - - {/if} \ No newline at end of file + +{/if} \ No newline at end of file From d83c2ec0376ba95a938eec15e5d90f5e1d8fe586 Mon Sep 17 00:00:00 2001 From: Ibnu Maksum Date: Mon, 19 Aug 2024 16:13:51 +0700 Subject: [PATCH 138/841] Payment info --- system/controllers/order.php | 12 ++--- system/controllers/pages.php | 91 +++++++++++++++++---------------- ui/ui/page-edit.tpl | 6 +-- ui/ui/user-ui/selectGateway.tpl | 12 ++++- 4 files changed, 63 insertions(+), 58 deletions(-) diff --git a/system/controllers/order.php b/system/controllers/order.php index f8a2db2f..19aae154 100644 --- a/system/controllers/order.php +++ b/system/controllers/order.php @@ -403,7 +403,7 @@ switch ($action) { _log(Lang::T("Payment Gateway not set, please set it in Settings")); r2(U . "home", 'e', Lang::T("Failed to create Transaction..")); } - if (count($pgs) > 1) { + if (count($pgs) > 0) { $ui->assign('pgs', $pgs); if ($tax_enable === 'yes') { $ui->assign('tax', $tax); @@ -416,13 +416,9 @@ switch ($action) { $ui->display('user-ui/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]; - } + 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..")); } case 'buy': $gateway = _post('gateway'); diff --git a/system/controllers/pages.php b/system/controllers/pages.php index 6dd8e73b..9b18fd1e 100644 --- a/system/controllers/pages.php +++ b/system/controllers/pages.php @@ -1,4 +1,5 @@ assign('_system_menu', 'pages'); $action = $routes['1']; $ui->assign('_admin', $admin); -if(strpos($action,"-reset")!==false){ +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"); + _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"; - if(file_exists($temp)){ - if(!copy($temp, $path)){ - file_put_contents($path, Http::getData('https://raw.githubusercontent.com/hotspotbilling/phpnuxbill/master/pages_template/'.$action.'.html')); + $action = str_replace("-reset", "", $action); + $path = "$PAGES_PATH/" . str_replace(".", "", $action) . ".html"; + $temp = "pages_template/" . str_replace(".", "", $action) . ".html"; + if (file_exists($temp)) { + if (!copy($temp, $path)) { + file_put_contents($path, Http::getData('https://raw.githubusercontent.com/hotspotbilling/phpnuxbill/master/pages_template/' . $action . '.html')); } - }else{ - file_put_contents($path, Http::getData('https://raw.githubusercontent.com/hotspotbilling/phpnuxbill/master/pages_template/'.$action.'.html')); + } else { + file_put_contents($path, Http::getData('https://raw.githubusercontent.com/hotspotbilling/phpnuxbill/master/pages_template/' . $action . '.html')); } - r2(U . 'pages/'.$action); -}else if(strpos($action,"-post")===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"); + _alert(Lang::T('You do not have permission to access this page'), 'danger', "dashboard"); } - $path = "pages/".str_replace(".","",$action).".html"; + $path = "$PAGES_PATH/" . str_replace(".", "", $action) . ".html"; $ui->assign("action", $action); //echo $path; run_hook('view_edit_pages'); #HOOK - if(!file_exists($path)){ - $temp = "pages_template/".str_replace(".","",$action).".html"; - if(file_exists($temp)){ - if(!copy($temp, $path)){ + if (!file_exists($path)) { + $temp = "pages_template/" . str_replace(".", "", $action) . ".html"; + if (file_exists($temp)) { + if (!copy($temp, $path)) { touch($path); } - }else{ + } else { touch($path); } } - if(file_exists($path)){ - if($action=='Voucher'){ - if(!file_exists("pages/vouchers/")){ - mkdir("pages/vouchers/"); - if(file_exists("pages_template/vouchers/")){ - File::copyFolder("pages_template/vouchers/", "pages/vouchers/"); + if (file_exists($path)) { + if ($action == 'Voucher') { + if (!file_exists("$PAGES_PATH/vouchers/")) { + mkdir("$PAGES_PATH/vouchers/"); + if (file_exists("pages_template/vouchers/")) { + File::copyFolder("pages_template/vouchers/", "$PAGES_PATH/vouchers/"); } } - $ui->assign("vouchers", scandir("pages/vouchers/")); + $ui->assign("vouchers", scandir("$PAGES_PATH/vouchers/")); } $html = file_get_contents($path); - $ui->assign("htmls",str_replace([""],"",$html)); - $ui->assign("writeable",is_writable($path)); - $ui->assign("pageHeader",str_replace('_', ' ', $action)); - $ui->assign("PageFile",$action); + $ui->assign("htmls", str_replace([""], "", $html)); + $ui->assign("writeable", is_writable($path)); + $ui->assign("pageHeader", str_replace('_', ' ', $action)); + $ui->assign("PageFile", $action); $ui->display('page-edit.tpl'); - }else + } else $ui->display('a404.tpl'); -}else{ +} else { if (!in_array($admin['user_type'], ['SuperAdmin', 'Admin'])) { - _alert(Lang::T('You do not have permission to access this page'),'danger', "dashboard"); + _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)){ + $action = str_replace("-post", "", $action); + $path = "$PAGES_PATH/" . str_replace(".", "", $action) . ".html"; + if (file_exists($path)) { $html = _post("html"); run_hook('save_pages'); #HOOK - if(file_put_contents($path, $html)){ - if(_post('template_save')=='yes'){ - if(!empty(_post('template_name'))){ - file_put_contents("pages/vouchers/"._post('template_name').'.html', $html); + if (file_put_contents($path, $html)) { + if (_post('template_save') == 'yes') { + if (!empty(_post('template_name'))) { + file_put_contents("pages/vouchers/" . _post('template_name') . '.html', $html); } } - r2(U . 'pages/'.$action, 's', Lang::T("Saving page success")); - }else{ - r2(U . 'pages/'.$action, 'e', Lang::T("Failed to save page, make sure i can write to folder pages, chmod 664 pages/*.html")); + r2(U . 'pages/' . $action, 's', Lang::T("Saving page success")); + } else { + r2(U . 'pages/' . $action, 'e', Lang::T("Failed to save page, make sure i can write to folder pages, chmod 664 pages/*.html")); } - }else + } else $ui->display('a404.tpl'); -} \ No newline at end of file +} diff --git a/ui/ui/page-edit.tpl b/ui/ui/page-edit.tpl index 9346aa3c..9d0153fb 100644 --- a/ui/ui/page-edit.tpl +++ b/ui/ui/page-edit.tpl @@ -31,7 +31,7 @@

    {Lang::T('Sometimes you need to refresh 3 times until content change')}

    + value="{$app_url}/{$PAGES_PATH}/{$PageFile}.html">
    {else}
  • {Lang::T('Location')} {if - $plan['is_radius']}Radius{else}{$plan['routers']} + $plan['is_radius']}Radius{else}{$plan['routers']} {/if}
  • {/if} From 5ae4dde522312efa2773b964ac65e515dfb9db93 Mon Sep 17 00:00:00 2001 From: Ahmad Husein <48185559+ahmadhusein17@users.noreply.github.com> Date: Tue, 20 Aug 2024 19:23:14 +0700 Subject: [PATCH 139/841] Update hotspot-edit.tpl --- ui/ui/hotspot-edit.tpl | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/ui/ui/hotspot-edit.tpl b/ui/ui/hotspot-edit.tpl index 75de4635..1100e4aa 100644 --- a/ui/ui/hotspot-edit.tpl +++ b/ui/ui/hotspot-edit.tpl @@ -15,8 +15,8 @@ data-content="Customer cannot buy disabled Plan, but admin can recharge it, use it if you want only admin recharge it">?
    - Enable - Disable + {Lang::T('Enable')} + {Lang::T('Disable')}
    @@ -28,9 +28,9 @@
    - Prepaid + {Lang::T('Prepaid')} Postpaid + {if $d['prepaid'] == 'no'}checked{/if}> {Lang::T('Postpaid')}
    @@ -42,9 +42,9 @@
    - Personal + {Lang::T('Personal')} Business + {if $d['plan_type'] == 'Business'}checked{/if}> {Lang::T('Business')}
    {if $_c['radius_enable'] and $d['is_radius']} @@ -234,7 +234,7 @@
    -
    on-logout / on-down
    +
    {Lang::T('on-logout / on-down')}
    @@ -333,4 +333,4 @@ }); -{include file="sections/footer.tpl"} \ No newline at end of file +{include file="sections/footer.tpl"} From fa27ccf5cac8589f51e818d471df08cef12b0dc3 Mon Sep 17 00:00:00 2001 From: Ahmad Husein <48185559+ahmadhusein17@users.noreply.github.com> Date: Tue, 20 Aug 2024 19:31:18 +0700 Subject: [PATCH 140/841] Update orderBalance.tpl --- ui/ui/user-ui/orderBalance.tpl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ui/ui/user-ui/orderBalance.tpl b/ui/ui/user-ui/orderBalance.tpl index d7f5edc9..d68316ae 100644 --- a/ui/ui/user-ui/orderBalance.tpl +++ b/ui/ui/user-ui/orderBalance.tpl @@ -23,7 +23,7 @@
    Buy + class="btn btn-sm btn-block btn-primary">{Lang::T('Buy')}
    @@ -34,4 +34,4 @@
    -{include file="user-ui/footer.tpl"} \ No newline at end of file +{include file="user-ui/footer.tpl"} From e4c8be2c16c2a50fa30726bb73e07040d035510e Mon Sep 17 00:00:00 2001 From: Ahmad Husein <48185559+ahmadhusein17@users.noreply.github.com> Date: Tue, 20 Aug 2024 19:35:07 +0700 Subject: [PATCH 141/841] Update orderPlan.tpl --- ui/ui/user-ui/orderPlan.tpl | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/ui/ui/user-ui/orderPlan.tpl b/ui/ui/user-ui/orderPlan.tpl index 74dda812..bb435c1c 100644 --- a/ui/ui/user-ui/orderPlan.tpl +++ b/ui/ui/user-ui/orderPlan.tpl @@ -39,7 +39,7 @@
    Buy + class="btn btn-sm btn-block btn-warning text-black">{Lang::T('Buy')} {if $_c['enable_balance'] == 'yes' && $_user['balance']>=$plan['price']} Buy + class="btn btn-sm btn-block btn-warning text-black">{Lang::T('Buy')} {if $_c['enable_balance'] == 'yes' && $_user['balance']>=$plan['price']} Buy + class="btn btn-sm btn-block btn-warning text-black">{Lang::T('Buy')} {if $_c['enable_balance'] == 'yes' && $_user['balance']>=$plan['price']} Buy + class="btn btn-sm btn-block btn-warning text-black">{Lang::T('Buy')} {if $_c['enable_balance'] == 'yes' && $_user['balance']>=$plan['price']} Buy + class="btn btn-sm btn-block btn-warning text-black">{Lang::T('Buy')} {if $_c['enable_balance'] == 'yes' && $_user['balance']>=$plan['price']} Buy + class="btn btn-sm btn-block btn-warning text-black">{Lang::T('Buy')} {if $_c['enable_balance'] == 'yes' && $_user['balance']>=$plan['price']} Buy + class="btn btn-sm btn-block btn-warning text-black">{Lang::T('Buy')} {if $_c['enable_balance'] == 'yes' && $_user['balance']>=$plan['price']} Buy + class="btn btn-sm btn-block btn-warning text-black">{Lang::T('Buy')} {if $_c['enable_balance'] == 'yes' && $_user['balance']>=$plan['price']}
    -{include file="user-ui/footer.tpl"} \ No newline at end of file +{include file="user-ui/footer.tpl"} From 49f3c1a1419cfe45c7e7a3734c17a98b48dd8b2c Mon Sep 17 00:00:00 2001 From: Ahmad Husein <48185559+ahmadhusein17@users.noreply.github.com> Date: Tue, 20 Aug 2024 19:40:17 +0700 Subject: [PATCH 142/841] Update selectGateway.tpl --- ui/ui/user-ui/selectGateway.tpl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ui/ui/user-ui/selectGateway.tpl b/ui/ui/user-ui/selectGateway.tpl index 621fdb24..aa61a529 100644 --- a/ui/ui/user-ui/selectGateway.tpl +++ b/ui/ui/user-ui/selectGateway.tpl @@ -15,7 +15,7 @@ @@ -66,4 +66,4 @@
    -{include file="sections/footer.tpl"} \ No newline at end of file +{include file="sections/footer.tpl"} From d0b60d5e7d482326728850b3a48fd2f16638025f Mon Sep 17 00:00:00 2001 From: Ahmad Husein <48185559+ahmadhusein17@users.noreply.github.com> Date: Tue, 20 Aug 2024 19:48:29 +0700 Subject: [PATCH 144/841] Update logs.tpl --- ui/ui/logs.tpl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ui/ui/logs.tpl b/ui/ui/logs.tpl index c43864db..3aba4804 100644 --- a/ui/ui/logs.tpl +++ b/ui/ui/logs.tpl @@ -32,12 +32,12 @@
    - Keep Logs + {Lang::T('Keep Logs')} - Days + {Lang::T('Days')}
    + onclick="return confirm('Clear old logs?')">{Lang::T('Clean Logs')}
     
    @@ -63,4 +63,4 @@ -{include file="sections/footer.tpl"} \ No newline at end of file +{include file="sections/footer.tpl"} From c41fe7435fdddf21f63adb57dbe0c82f9edc494e Mon Sep 17 00:00:00 2001 From: Ahmad Husein <48185559+ahmadhusein17@users.noreply.github.com> Date: Tue, 20 Aug 2024 19:54:22 +0700 Subject: [PATCH 145/841] Update message-bulk.tpl --- ui/ui/message-bulk.tpl | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/ui/ui/message-bulk.tpl b/ui/ui/message-bulk.tpl index e28230ce..3dc59c12 100644 --- a/ui/ui/message-bulk.tpl +++ b/ui/ui/message-bulk.tpl @@ -90,24 +90,24 @@ {if $batchStatus} -

    Total SMS Sent: {$totalSMSSent} Total SMS - Failed: {$totalSMSFailed} Total WhatsApp Sent: - {$totalWhatsappSent} Total WhatsApp Failed: +

    {Lang::T('Total SMS Sent')}: {$totalSMSSent} {Lang::T('Total SMS + Failed')}: {$totalSMSFailed} {Lang::T('Total WhatsApp Sent')}: + {$totalWhatsappSent} {Lang::T('Total WhatsApp Failed')}: {$totalWhatsappFailed}

    {/if}
    -

    Message Results

    +

    {Lang::T('Message Results')}

    {nl2br($data['commit']['message'])}{Lang::dateTimeFormat(str_replace(['Z','T'],'',$data['commit']['author']['date']))}{Lang::dateTimeFormat(str_replace(['Z','T'],'',$data['commit']['author']['date']))} - update + install {nl2br($data['commit']['message'])}
    {nl2br($data['commit']['message'])}{Lang::dateTimeFormat(str_replace(['Z','T'],'',$data['commit']['author']['date']))}{Lang::dateTimeFormat(str_replace(['Z','T'],'',$data['commit']['author']['date']))} - update + install {nl2br($data['commit']['message'])}
    - - - - + + + + @@ -139,4 +139,4 @@ -{include file="sections/footer.tpl"} \ No newline at end of file +{include file="sections/footer.tpl"} From 1d4eff11baeac8d21660dbf8130fbd0a9233c3fd Mon Sep 17 00:00:00 2001 From: Ahmad Husein <48185559+ahmadhusein17@users.noreply.github.com> Date: Tue, 20 Aug 2024 19:58:09 +0700 Subject: [PATCH 146/841] Update paymentgateway-audit-view.tpl --- ui/ui/paymentgateway-audit-view.tpl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ui/ui/paymentgateway-audit-view.tpl b/ui/ui/paymentgateway-audit-view.tpl index a72838a7..77bfd923 100644 --- a/ui/ui/paymentgateway-audit-view.tpl +++ b/ui/ui/paymentgateway-audit-view.tpl @@ -10,7 +10,7 @@
    • - TRX ID  {$pg['id']}  + {Lang::T('TRX ID')}  {$pg['id']} 
    • {Lang::T('Invoice')}   @@ -65,7 +65,7 @@
      - Response when request payment + {Lang::T('Response when request payment')}
    NamePhoneMessageStatus{Lang::T('Name')}{Lang::T('Phone')}{Lang::T('Message')}{Lang::T('Status')}
    @@ -80,7 +80,7 @@
    - Response when payment PAID + {Lang::T('Response when payment PAID')}
    @@ -94,4 +94,4 @@ -{include file="sections/footer.tpl"} \ No newline at end of file +{include file="sections/footer.tpl"} From 34ea48fd7d3bce17df3af7409d9c77e7d13df3a8 Mon Sep 17 00:00:00 2001 From: Ahmad Husein <48185559+ahmadhusein17@users.noreply.github.com> Date: Tue, 20 Aug 2024 20:00:19 +0700 Subject: [PATCH 147/841] Update paymentgateway-audit.tpl --- ui/ui/paymentgateway-audit.tpl | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/ui/ui/paymentgateway-audit.tpl b/ui/ui/paymentgateway-audit.tpl index e10de7d3..08d49722 100644 --- a/ui/ui/paymentgateway-audit.tpl +++ b/ui/ui/paymentgateway-audit.tpl @@ -17,8 +17,8 @@
    - - + + @@ -46,7 +46,7 @@ @@ -63,8 +63,8 @@
    TRX IDPG ID{Lang::T('TRX ID')}{Lang::T('PG ID')} {Lang::T('Username')} {Lang::T('Plan Name')} {Lang::T('Routers')} {if $pg['pg_url_payment']} open + rel="noopener noreferrer">{Lang::T('open')} {/if} {$pg['payment_method']} - {$pg['payment_channel']}
    {include file="pagination.tpl"} - kembali + {Lang::T('back')}
    -{include file="sections/footer.tpl"} \ No newline at end of file +{include file="sections/footer.tpl"} From ee7aa609796d3d8f0b40860df4d537b5bac083fc Mon Sep 17 00:00:00 2001 From: Ahmad Husein <48185559+ahmadhusein17@users.noreply.github.com> Date: Tue, 20 Aug 2024 20:08:05 +0700 Subject: [PATCH 148/841] Update plugin-manager.tpl --- ui/ui/plugin-manager.tpl | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/ui/ui/plugin-manager.tpl b/ui/ui/plugin-manager.tpl index 3a3e20d5..4a4f48c9 100644 --- a/ui/ui/plugin-manager.tpl +++ b/ui/ui/plugin-manager.tpl @@ -1,8 +1,8 @@ {include file="sections/header.tpl"} {if empty($_c['github_token'])} -

    To download from private/paid repository, Set - your Github Authentication first

    +

    {Lang::T('To download from private/paid repository')}, + {Lang::T('Set your Github Authentication first')}

    {/if}
    - +
    @@ -31,7 +31,7 @@

    - +
    @@ -41,10 +41,10 @@
    @@ -61,7 +61,7 @@
    {$plugin['description']}
    - {if $_c['radius_enable']} -

    For Radius, you need to add Pool Name in Mikrotik manually

    +

    {Lang::T('For Radius, you need to add')} Pool {Lang::T('Name')} {Lang::T('in Mikrotik manually')}

    {/if}
    From aeeb9a2b63ed9712f42659ceeda96c58ba51dc9c Mon Sep 17 00:00:00 2001 From: Ahmad Husein <48185559+ahmadhusein17@users.noreply.github.com> Date: Tue, 20 Aug 2024 20:13:33 +0700 Subject: [PATCH 150/841] Update pool-edit.tpl --- ui/ui/pool-edit.tpl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/ui/pool-edit.tpl b/ui/ui/pool-edit.tpl index 38673927..6e0f722f 100644 --- a/ui/ui/pool-edit.tpl +++ b/ui/ui/pool-edit.tpl @@ -32,7 +32,7 @@
    {if $_c['radius_enable']} -

    {Lang::T('For Radius, you need to add')} Pool {Lang::T('Name')} {Lang::T('in Mikrotik manually')}

    +

    {Lang::T('For Radius, you need to add')} {Lang::T('Name')} Pool {Lang::T('in Mikrotik manually')}

    {/if}
    From 1801b5b43655a8d4d5e8716d8c9f1ee0acdffa2f Mon Sep 17 00:00:00 2001 From: Ahmad Husein <48185559+ahmadhusein17@users.noreply.github.com> Date: Tue, 20 Aug 2024 20:19:34 +0700 Subject: [PATCH 151/841] Update pool.tpl --- ui/ui/pool.tpl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ui/ui/pool.tpl b/ui/ui/pool.tpl index 3d537b81..f40708b4 100644 --- a/ui/ui/pool.tpl +++ b/ui/ui/pool.tpl @@ -65,12 +65,12 @@
    {include file="pagination.tpl"}
    -

    Create expired Internet Plan

    -

    When customer expired, you can move it to Expired Internet Plan

    +

    {Lang::T('Create expired Internet Plan')}

    +

    {Lang::T('When customer expired, you can move it to Expired Internet Plan')}

    -{include file="sections/footer.tpl"} \ No newline at end of file +{include file="sections/footer.tpl"} From 7643b24f312c687ab28d0c90e08f126305b68d79 Mon Sep 17 00:00:00 2001 From: Ahmad Husein <48185559+ahmadhusein17@users.noreply.github.com> Date: Tue, 20 Aug 2024 20:21:49 +0700 Subject: [PATCH 152/841] Update pppoe-add.tpl --- ui/ui/pppoe-add.tpl | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/ui/ui/pppoe-add.tpl b/ui/ui/pppoe-add.tpl index 9403da6a..1c5d54d0 100644 --- a/ui/ui/pppoe-add.tpl +++ b/ui/ui/pppoe-add.tpl @@ -13,8 +13,8 @@ data-content="Customer cannot buy disabled Plan, but admin can recharge it, use it if you want only admin recharge it">?
    - Enable - Disable + {Lang::T('Enable')} + {Lang::T('Disable')}
    @@ -24,8 +24,8 @@ data-content="Postpaid will have fix expired date">?
    - Prepaid - Postpaid + {Lang::T('Prepaid')} + {Lang::T('Postpaid')}
    @@ -35,8 +35,8 @@ data-content="Personal Plan will only show to personal Customer, Business plan will only show to Business Customer">?
    - Personal - Business + {Lang::T('Personal')} + {Lang::T('Business')}
    {if $_c['radius_enable']} @@ -198,4 +198,4 @@ {/literal} {/if} -{include file="sections/footer.tpl"} \ No newline at end of file +{include file="sections/footer.tpl"} From a96f808318325bf8a58f8e381d67ba6342d5e017 Mon Sep 17 00:00:00 2001 From: Ahmad Husein <48185559+ahmadhusein17@users.noreply.github.com> Date: Tue, 20 Aug 2024 20:26:43 +0700 Subject: [PATCH 153/841] Update pppoe-edit.tpl --- ui/ui/pppoe-edit.tpl | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/ui/ui/pppoe-edit.tpl b/ui/ui/pppoe-edit.tpl index b737dea5..448b9b6b 100644 --- a/ui/ui/pppoe-edit.tpl +++ b/ui/ui/pppoe-edit.tpl @@ -14,8 +14,8 @@ data-content="Customer cannot buy disabled Plan, but admin can recharge it, use it if you want only admin recharge it">?
    - Enable - Disable + {Lang::T('Enable')} + {Lang::T('Disable')}
    @@ -27,9 +27,9 @@
    - Prepaid + {Lang::T('Prepaid')} Postpaid + {if $d['prepaid'] == 'no'}checked{/if}> {Lang::T('Postpaid')}
    @@ -41,9 +41,9 @@
    - Personal + {Lang::T('Personal')} Business + {if $d['plan_type'] == 'Business'}checked{/if}> {Lang::T('Business')}
    {if $_c['radius_enable'] and $d['is_radius']} @@ -187,14 +187,14 @@ {if !$d['is_radius']}
    -
    on-login / on-up
    +
    {Lang::T('on-login / on-up')}
    -
    on-logout / on-down
    +
    {Lang::T('on-logout / on-down')}
    @@ -252,4 +252,4 @@ }); -{include file="sections/footer.tpl"} \ No newline at end of file +{include file="sections/footer.tpl"} From 75907d5c3f887383b34cedb7364c3bfc692a7834 Mon Sep 17 00:00:00 2001 From: Ahmad Husein <48185559+ahmadhusein17@users.noreply.github.com> Date: Tue, 20 Aug 2024 20:30:08 +0700 Subject: [PATCH 154/841] Update pppoe.tpl --- ui/ui/pppoe.tpl | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/ui/ui/pppoe.tpl b/ui/ui/pppoe.tpl index a35904e0..dc1da881 100644 --- a/ui/ui/pppoe.tpl +++ b/ui/ui/pppoe.tpl @@ -26,9 +26,9 @@
    @@ -88,8 +88,8 @@
    @@ -133,13 +133,13 @@ {foreach $d as $ds} {$ds['name_plan']} - {$ds['plan_type']} {if $ds['prepaid'] != 'yes'}Postpaid{else}Prepaid{/if} + {$ds['plan_type']} {if $ds['prepaid'] != 'yes'}{Lang::T('Postpaid')}{else}{Lang::T('Prepaid')}{/if} {$ds['name_bw']} {Lang::moneyFormat($ds['price'])} {$ds['validity']} {$ds['validity_unit']} {$ds['pool']} {if $ds['plan_expired']}Yes{else}No + href="{$_url}services/edit/{$ds['plan_expired']}">{Lang::T('Yes')}{else}{Lang::T('No')} {/if} {if $ds['prepaid'] == no}{$ds['expired_date']}{/if} @@ -168,12 +168,12 @@
    -{include file="sections/footer.tpl"} \ No newline at end of file +{include file="sections/footer.tpl"} From 24e49e4eb933ea1f7dfae4f855a81735aa627c4b Mon Sep 17 00:00:00 2001 From: Ibnu Maksum Date: Wed, 21 Aug 2024 13:39:06 +0700 Subject: [PATCH 155/841] compability for old plugin --- system/controllers/settings.php | 8 ++++---- .../libs/sysplugins/smarty_internal_templatebase.php | 2 ++ ui/ui/{users-add.tpl => admin-add.tpl} | 0 ui/ui/{users-edit.tpl => admin-edit.tpl} | 0 ui/ui/{users-view.tpl => admin-view.tpl} | 0 ui/ui/{users.tpl => admin.tpl} | 0 6 files changed, 6 insertions(+), 4 deletions(-) rename ui/ui/{users-add.tpl => admin-add.tpl} (100%) rename ui/ui/{users-edit.tpl => admin-edit.tpl} (100%) rename ui/ui/{users-view.tpl => admin-view.tpl} (100%) rename ui/ui/{users.tpl => admin.tpl} (100%) diff --git a/system/controllers/settings.php b/system/controllers/settings.php index 986b68fd..2363b257 100644 --- a/system/controllers/settings.php +++ b/system/controllers/settings.php @@ -377,7 +377,7 @@ switch ($action) { $ui->assign('d', $d); $ui->assign('search', $search); run_hook('view_list_admin'); #HOOK - $ui->display('users.tpl'); + $ui->display('admin.tpl'); break; case 'users-add': @@ -386,7 +386,7 @@ switch ($action) { } $ui->assign('_title', Lang::T('Add User')); $ui->assign('agents', ORM::for_table('tbl_users')->where('user_type', 'Agent')->find_many()); - $ui->display('users-add.tpl'); + $ui->display('admin-add.tpl'); break; case 'users-view': $ui->assign('_title', Lang::T('Edit User')); @@ -413,7 +413,7 @@ switch ($action) { } $ui->assign('d', $d); $ui->assign('_title', $d['username']); - $ui->display('users-view.tpl'); + $ui->display('admin-view.tpl'); } else { r2(U . 'settings/users', 'e', Lang::T('Account Not Found')); } @@ -450,7 +450,7 @@ switch ($action) { $ui->assign('id', $id); $ui->assign('d', $d); run_hook('view_edit_admin'); #HOOK - $ui->display('users-edit.tpl'); + $ui->display('admin-edit.tpl'); } else { r2(U . 'settings/users', 'e', Lang::T('Account Not Found')); } diff --git a/system/vendor/smarty/smarty/libs/sysplugins/smarty_internal_templatebase.php b/system/vendor/smarty/smarty/libs/sysplugins/smarty_internal_templatebase.php index 918362e9..a7a83a6f 100644 --- a/system/vendor/smarty/smarty/libs/sysplugins/smarty_internal_templatebase.php +++ b/system/vendor/smarty/smarty/libs/sysplugins/smarty_internal_templatebase.php @@ -131,6 +131,8 @@ abstract class Smarty_Internal_TemplateBase extends Smarty_Internal_Data public function display($template = null, $cache_id = null, $compile_id = null, $parent = null) { // display template + $template = str_replace("section/user-",'user-ui/', $template); + $template = str_replace("user-",'', $template); $this->_execute($template, $cache_id, $compile_id, $parent, 1); } diff --git a/ui/ui/users-add.tpl b/ui/ui/admin-add.tpl similarity index 100% rename from ui/ui/users-add.tpl rename to ui/ui/admin-add.tpl diff --git a/ui/ui/users-edit.tpl b/ui/ui/admin-edit.tpl similarity index 100% rename from ui/ui/users-edit.tpl rename to ui/ui/admin-edit.tpl diff --git a/ui/ui/users-view.tpl b/ui/ui/admin-view.tpl similarity index 100% rename from ui/ui/users-view.tpl rename to ui/ui/admin-view.tpl diff --git a/ui/ui/users.tpl b/ui/ui/admin.tpl similarity index 100% rename from ui/ui/users.tpl rename to ui/ui/admin.tpl From 14c4ab8fbc209eb7075ca1124a24e13b84505a85 Mon Sep 17 00:00:00 2001 From: Ibnu Maksum Date: Wed, 21 Aug 2024 14:00:44 +0700 Subject: [PATCH 156/841] show bandwidth plan in the customer view admin --- ui/ui/customers-view.tpl | 4 ++++ version.json | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/ui/ui/customers-view.tpl b/ui/ui/customers-view.tpl index f1840ca9..6d7de98c 100644 --- a/ui/ui/customers-view.tpl +++ b/ui/ui/customers-view.tpl @@ -133,6 +133,10 @@ {Lang::T('Type')} {if $package['prepaid'] eq yes}Prepaid{else}Postpaid{/if} +
  • + {Lang::T('Bandwidth')} + {$package['name_bw']} +
  • {Lang::T('Created On')} {Lang::dateAndTimeFormat($package['recharged_on'],$package['recharged_time'])} diff --git a/version.json b/version.json index 9bd82d26..08511041 100644 --- a/version.json +++ b/version.json @@ -1,3 +1,3 @@ { - "version": "2024.8.19" + "version": "2024.8.21" } \ No newline at end of file From 02e19897455b7dc2abbb19c6a4f9fe49aa421564 Mon Sep 17 00:00:00 2001 From: Focuslinkstech <45756999+Focuslinkstech@users.noreply.github.com> Date: Wed, 21 Aug 2024 08:09:37 +0100 Subject: [PATCH 157/841] fix typo error --- ui/ui/user-ui/sendPlan.tpl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/ui/user-ui/sendPlan.tpl b/ui/ui/user-ui/sendPlan.tpl index c756a0f3..601b35a5 100644 --- a/ui/ui/user-ui/sendPlan.tpl +++ b/ui/ui/user-ui/sendPlan.tpl @@ -64,4 +64,4 @@
  • -{include file="suser-ui/footer.tpl"} \ No newline at end of file +{include file="user-ui/footer.tpl"} \ No newline at end of file From 8e9aeec5178e3756828389ff2c90f19a9152cfd7 Mon Sep 17 00:00:00 2001 From: Ibnu Maksum Date: Wed, 21 Aug 2024 14:33:11 +0700 Subject: [PATCH 158/841] fix logic compability --- .../libs/sysplugins/smarty_internal_templatebase.php | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/system/vendor/smarty/smarty/libs/sysplugins/smarty_internal_templatebase.php b/system/vendor/smarty/smarty/libs/sysplugins/smarty_internal_templatebase.php index a7a83a6f..8d41ebcf 100644 --- a/system/vendor/smarty/smarty/libs/sysplugins/smarty_internal_templatebase.php +++ b/system/vendor/smarty/smarty/libs/sysplugins/smarty_internal_templatebase.php @@ -131,8 +131,13 @@ abstract class Smarty_Internal_TemplateBase extends Smarty_Internal_Data public function display($template = null, $cache_id = null, $compile_id = null, $parent = null) { // display template - $template = str_replace("section/user-",'user-ui/', $template); - $template = str_replace("user-",'', $template); + if(strpos($template, "user-ui") === false){ + if(strpos($template, "section/user-") === false){ + $template = str_replace("user-",'', $template); + }else{ + $template = str_replace("section/user-",'user-ui/', $template); + } + } $this->_execute($template, $cache_id, $compile_id, $parent, 1); } From c1d93f1fe2ef6ed63fbcadbf94b1c6bc62f87d24 Mon Sep 17 00:00:00 2001 From: Ibnu Maksum Date: Wed, 21 Aug 2024 14:33:26 +0700 Subject: [PATCH 159/841] fix logic compability --- version.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.json b/version.json index 08511041..c053e2b5 100644 --- a/version.json +++ b/version.json @@ -1,3 +1,3 @@ { - "version": "2024.8.21" + "version": "2024.8.21.1" } \ No newline at end of file From d4584e62882286e2f132b3d70fc390121f7a40ea Mon Sep 17 00:00:00 2001 From: Ahmad Husein <48185559+ahmadhusein17@users.noreply.github.com> Date: Tue, 20 Aug 2024 19:23:14 +0700 Subject: [PATCH 160/841] Update hotspot-edit.tpl --- ui/ui/hotspot-edit.tpl | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/ui/ui/hotspot-edit.tpl b/ui/ui/hotspot-edit.tpl index 75de4635..1100e4aa 100644 --- a/ui/ui/hotspot-edit.tpl +++ b/ui/ui/hotspot-edit.tpl @@ -15,8 +15,8 @@ data-content="Customer cannot buy disabled Plan, but admin can recharge it, use it if you want only admin recharge it">?
    - Enable - Disable + {Lang::T('Enable')} + {Lang::T('Disable')}
    @@ -28,9 +28,9 @@
    - Prepaid + {Lang::T('Prepaid')} Postpaid + {if $d['prepaid'] == 'no'}checked{/if}> {Lang::T('Postpaid')}
    @@ -42,9 +42,9 @@
    - Personal + {Lang::T('Personal')} Business + {if $d['plan_type'] == 'Business'}checked{/if}> {Lang::T('Business')}
    {if $_c['radius_enable'] and $d['is_radius']} @@ -234,7 +234,7 @@
    -
    on-logout / on-down
    +
    {Lang::T('on-logout / on-down')}
    @@ -333,4 +333,4 @@ }); -{include file="sections/footer.tpl"} \ No newline at end of file +{include file="sections/footer.tpl"} From 0d97d0d753b3432c25778533c87409d1b476b196 Mon Sep 17 00:00:00 2001 From: Ahmad Husein <48185559+ahmadhusein17@users.noreply.github.com> Date: Tue, 20 Aug 2024 19:31:18 +0700 Subject: [PATCH 161/841] Update orderBalance.tpl --- ui/ui/user-ui/orderBalance.tpl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ui/ui/user-ui/orderBalance.tpl b/ui/ui/user-ui/orderBalance.tpl index d7f5edc9..d68316ae 100644 --- a/ui/ui/user-ui/orderBalance.tpl +++ b/ui/ui/user-ui/orderBalance.tpl @@ -23,7 +23,7 @@
    Buy + class="btn btn-sm btn-block btn-primary">{Lang::T('Buy')}
    @@ -34,4 +34,4 @@ -{include file="user-ui/footer.tpl"} \ No newline at end of file +{include file="user-ui/footer.tpl"} From a1ec9e80401f3b6843ef58814afb3375291d7c87 Mon Sep 17 00:00:00 2001 From: Ahmad Husein <48185559+ahmadhusein17@users.noreply.github.com> Date: Tue, 20 Aug 2024 19:35:07 +0700 Subject: [PATCH 162/841] Update orderPlan.tpl --- ui/ui/user-ui/orderPlan.tpl | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/ui/ui/user-ui/orderPlan.tpl b/ui/ui/user-ui/orderPlan.tpl index 74dda812..bb435c1c 100644 --- a/ui/ui/user-ui/orderPlan.tpl +++ b/ui/ui/user-ui/orderPlan.tpl @@ -39,7 +39,7 @@
    Buy + class="btn btn-sm btn-block btn-warning text-black">{Lang::T('Buy')} {if $_c['enable_balance'] == 'yes' && $_user['balance']>=$plan['price']} Buy + class="btn btn-sm btn-block btn-warning text-black">{Lang::T('Buy')} {if $_c['enable_balance'] == 'yes' && $_user['balance']>=$plan['price']} Buy + class="btn btn-sm btn-block btn-warning text-black">{Lang::T('Buy')} {if $_c['enable_balance'] == 'yes' && $_user['balance']>=$plan['price']} Buy + class="btn btn-sm btn-block btn-warning text-black">{Lang::T('Buy')} {if $_c['enable_balance'] == 'yes' && $_user['balance']>=$plan['price']} Buy + class="btn btn-sm btn-block btn-warning text-black">{Lang::T('Buy')} {if $_c['enable_balance'] == 'yes' && $_user['balance']>=$plan['price']} Buy + class="btn btn-sm btn-block btn-warning text-black">{Lang::T('Buy')} {if $_c['enable_balance'] == 'yes' && $_user['balance']>=$plan['price']} Buy + class="btn btn-sm btn-block btn-warning text-black">{Lang::T('Buy')} {if $_c['enable_balance'] == 'yes' && $_user['balance']>=$plan['price']} Buy + class="btn btn-sm btn-block btn-warning text-black">{Lang::T('Buy')} {if $_c['enable_balance'] == 'yes' && $_user['balance']>=$plan['price']}
    -{include file="user-ui/footer.tpl"} \ No newline at end of file +{include file="user-ui/footer.tpl"} From 31253fd14d147437de609156ca8478ea9412897a Mon Sep 17 00:00:00 2001 From: Ahmad Husein <48185559+ahmadhusein17@users.noreply.github.com> Date: Tue, 20 Aug 2024 19:40:17 +0700 Subject: [PATCH 163/841] Update selectGateway.tpl --- ui/ui/user-ui/selectGateway.tpl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ui/ui/user-ui/selectGateway.tpl b/ui/ui/user-ui/selectGateway.tpl index 621fdb24..aa61a529 100644 --- a/ui/ui/user-ui/selectGateway.tpl +++ b/ui/ui/user-ui/selectGateway.tpl @@ -15,7 +15,7 @@ @@ -66,4 +66,4 @@ -{include file="sections/footer.tpl"} \ No newline at end of file +{include file="sections/footer.tpl"} From 83efa89dfcf4fa7ccdb17cf48e6b702c7ae5ba43 Mon Sep 17 00:00:00 2001 From: Ahmad Husein <48185559+ahmadhusein17@users.noreply.github.com> Date: Tue, 20 Aug 2024 19:48:29 +0700 Subject: [PATCH 165/841] Update logs.tpl --- ui/ui/logs.tpl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ui/ui/logs.tpl b/ui/ui/logs.tpl index c43864db..3aba4804 100644 --- a/ui/ui/logs.tpl +++ b/ui/ui/logs.tpl @@ -32,12 +32,12 @@
    - Keep Logs + {Lang::T('Keep Logs')} - Days + {Lang::T('Days')}
    + onclick="return confirm('Clear old logs?')">{Lang::T('Clean Logs')}
      @@ -63,4 +63,4 @@ -{include file="sections/footer.tpl"} \ No newline at end of file +{include file="sections/footer.tpl"} From 1c2f9ddca53d4afd480853e7e086b7443bf5244a Mon Sep 17 00:00:00 2001 From: Ahmad Husein <48185559+ahmadhusein17@users.noreply.github.com> Date: Tue, 20 Aug 2024 19:54:22 +0700 Subject: [PATCH 166/841] Update message-bulk.tpl --- ui/ui/message-bulk.tpl | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/ui/ui/message-bulk.tpl b/ui/ui/message-bulk.tpl index e28230ce..3dc59c12 100644 --- a/ui/ui/message-bulk.tpl +++ b/ui/ui/message-bulk.tpl @@ -90,24 +90,24 @@ {if $batchStatus} -

    Total SMS Sent: {$totalSMSSent} Total SMS - Failed: {$totalSMSFailed} Total WhatsApp Sent: - {$totalWhatsappSent} Total WhatsApp Failed: +

    {Lang::T('Total SMS Sent')}: {$totalSMSSent} {Lang::T('Total SMS + Failed')}: {$totalSMSFailed} {Lang::T('Total WhatsApp Sent')}: + {$totalWhatsappSent} {Lang::T('Total WhatsApp Failed')}: {$totalWhatsappFailed}

    {/if}
    -

    Message Results

    +

    {Lang::T('Message Results')}

    - - - - + + + + @@ -139,4 +139,4 @@ -{include file="sections/footer.tpl"} \ No newline at end of file +{include file="sections/footer.tpl"} From 267095d68bf0e73370a21714371734dee276125c Mon Sep 17 00:00:00 2001 From: Ahmad Husein <48185559+ahmadhusein17@users.noreply.github.com> Date: Tue, 20 Aug 2024 19:58:09 +0700 Subject: [PATCH 167/841] Update paymentgateway-audit-view.tpl --- ui/ui/paymentgateway-audit-view.tpl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ui/ui/paymentgateway-audit-view.tpl b/ui/ui/paymentgateway-audit-view.tpl index a72838a7..77bfd923 100644 --- a/ui/ui/paymentgateway-audit-view.tpl +++ b/ui/ui/paymentgateway-audit-view.tpl @@ -10,7 +10,7 @@
    • - TRX ID  {$pg['id']}  + {Lang::T('TRX ID')}  {$pg['id']} 
    • {Lang::T('Invoice')}   @@ -65,7 +65,7 @@
      - Response when request payment + {Lang::T('Response when request payment')}
    NamePhoneMessageStatus{Lang::T('Name')}{Lang::T('Phone')}{Lang::T('Message')}{Lang::T('Status')}
    @@ -80,7 +80,7 @@
    - Response when payment PAID + {Lang::T('Response when payment PAID')}
    @@ -94,4 +94,4 @@ -{include file="sections/footer.tpl"} \ No newline at end of file +{include file="sections/footer.tpl"} From 4b29fab73fe322ebb6e5fcf92ab20cc4267041c3 Mon Sep 17 00:00:00 2001 From: Ahmad Husein <48185559+ahmadhusein17@users.noreply.github.com> Date: Tue, 20 Aug 2024 20:00:19 +0700 Subject: [PATCH 168/841] Update paymentgateway-audit.tpl --- ui/ui/paymentgateway-audit.tpl | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/ui/ui/paymentgateway-audit.tpl b/ui/ui/paymentgateway-audit.tpl index e10de7d3..08d49722 100644 --- a/ui/ui/paymentgateway-audit.tpl +++ b/ui/ui/paymentgateway-audit.tpl @@ -17,8 +17,8 @@
    - - + + @@ -46,7 +46,7 @@ @@ -63,8 +63,8 @@
    TRX IDPG ID{Lang::T('TRX ID')}{Lang::T('PG ID')} {Lang::T('Username')} {Lang::T('Plan Name')} {Lang::T('Routers')} {if $pg['pg_url_payment']} open + rel="noopener noreferrer">{Lang::T('open')} {/if} {$pg['payment_method']} - {$pg['payment_channel']}
    {include file="pagination.tpl"} -
    kembali + {Lang::T('back')}
    -{include file="sections/footer.tpl"} \ No newline at end of file +{include file="sections/footer.tpl"} From e94d3cdb4a953c4bb093d0c1c60c9fda7513c8de Mon Sep 17 00:00:00 2001 From: Ahmad Husein <48185559+ahmadhusein17@users.noreply.github.com> Date: Tue, 20 Aug 2024 20:08:05 +0700 Subject: [PATCH 169/841] Update plugin-manager.tpl --- ui/ui/plugin-manager.tpl | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/ui/ui/plugin-manager.tpl b/ui/ui/plugin-manager.tpl index 3a3e20d5..4a4f48c9 100644 --- a/ui/ui/plugin-manager.tpl +++ b/ui/ui/plugin-manager.tpl @@ -1,8 +1,8 @@ {include file="sections/header.tpl"} {if empty($_c['github_token'])} -

    To download from private/paid repository, Set - your Github Authentication first

    +

    {Lang::T('To download from private/paid repository')}, + {Lang::T('Set your Github Authentication first')}

    {/if}
    - +
    @@ -31,7 +31,7 @@

    - +
    @@ -41,10 +41,10 @@
    @@ -61,7 +61,7 @@
    {$plugin['description']}
    - {if $_c['radius_enable']} -

    For Radius, you need to add Pool Name in Mikrotik manually

    +

    {Lang::T('For Radius, you need to add')} Pool {Lang::T('Name')} {Lang::T('in Mikrotik manually')}

    {/if} From be33c6ae016a86fc5d1f1f33bec928c9da0c88b7 Mon Sep 17 00:00:00 2001 From: Ahmad Husein <48185559+ahmadhusein17@users.noreply.github.com> Date: Tue, 20 Aug 2024 20:13:33 +0700 Subject: [PATCH 171/841] Update pool-edit.tpl --- ui/ui/pool-edit.tpl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/ui/pool-edit.tpl b/ui/ui/pool-edit.tpl index 38673927..6e0f722f 100644 --- a/ui/ui/pool-edit.tpl +++ b/ui/ui/pool-edit.tpl @@ -32,7 +32,7 @@ {if $_c['radius_enable']} -

    {Lang::T('For Radius, you need to add')} Pool {Lang::T('Name')} {Lang::T('in Mikrotik manually')}

    +

    {Lang::T('For Radius, you need to add')} {Lang::T('Name')} Pool {Lang::T('in Mikrotik manually')}

    {/if} From 0a66553112b20b9530da823e8e8cf3c0ac4986f2 Mon Sep 17 00:00:00 2001 From: Ahmad Husein <48185559+ahmadhusein17@users.noreply.github.com> Date: Tue, 20 Aug 2024 20:19:34 +0700 Subject: [PATCH 172/841] Update pool.tpl --- ui/ui/pool.tpl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ui/ui/pool.tpl b/ui/ui/pool.tpl index 3d537b81..f40708b4 100644 --- a/ui/ui/pool.tpl +++ b/ui/ui/pool.tpl @@ -65,12 +65,12 @@ {include file="pagination.tpl"}
    -

    Create expired Internet Plan

    -

    When customer expired, you can move it to Expired Internet Plan

    +

    {Lang::T('Create expired Internet Plan')}

    +

    {Lang::T('When customer expired, you can move it to Expired Internet Plan')}

    -{include file="sections/footer.tpl"} \ No newline at end of file +{include file="sections/footer.tpl"} From ae8815c668c496752acd2c2fc1e9197fc431568f Mon Sep 17 00:00:00 2001 From: Ahmad Husein <48185559+ahmadhusein17@users.noreply.github.com> Date: Tue, 20 Aug 2024 20:21:49 +0700 Subject: [PATCH 173/841] Update pppoe-add.tpl --- ui/ui/pppoe-add.tpl | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/ui/ui/pppoe-add.tpl b/ui/ui/pppoe-add.tpl index 9403da6a..1c5d54d0 100644 --- a/ui/ui/pppoe-add.tpl +++ b/ui/ui/pppoe-add.tpl @@ -13,8 +13,8 @@ data-content="Customer cannot buy disabled Plan, but admin can recharge it, use it if you want only admin recharge it">?
    - Enable - Disable + {Lang::T('Enable')} + {Lang::T('Disable')}
    @@ -24,8 +24,8 @@ data-content="Postpaid will have fix expired date">?
    - Prepaid - Postpaid + {Lang::T('Prepaid')} + {Lang::T('Postpaid')}
    @@ -35,8 +35,8 @@ data-content="Personal Plan will only show to personal Customer, Business plan will only show to Business Customer">?
    - Personal - Business + {Lang::T('Personal')} + {Lang::T('Business')}
    {if $_c['radius_enable']} @@ -198,4 +198,4 @@ {/literal} {/if} -{include file="sections/footer.tpl"} \ No newline at end of file +{include file="sections/footer.tpl"} From ca2df9c02e229adc86043bb4489ef7b72a6630b1 Mon Sep 17 00:00:00 2001 From: Ahmad Husein <48185559+ahmadhusein17@users.noreply.github.com> Date: Tue, 20 Aug 2024 20:26:43 +0700 Subject: [PATCH 174/841] Update pppoe-edit.tpl --- ui/ui/pppoe-edit.tpl | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/ui/ui/pppoe-edit.tpl b/ui/ui/pppoe-edit.tpl index b737dea5..448b9b6b 100644 --- a/ui/ui/pppoe-edit.tpl +++ b/ui/ui/pppoe-edit.tpl @@ -14,8 +14,8 @@ data-content="Customer cannot buy disabled Plan, but admin can recharge it, use it if you want only admin recharge it">?
    - Enable - Disable + {Lang::T('Enable')} + {Lang::T('Disable')}
    @@ -27,9 +27,9 @@
    - Prepaid + {Lang::T('Prepaid')} Postpaid + {if $d['prepaid'] == 'no'}checked{/if}> {Lang::T('Postpaid')}
    @@ -41,9 +41,9 @@
    - Personal + {Lang::T('Personal')} Business + {if $d['plan_type'] == 'Business'}checked{/if}> {Lang::T('Business')}
    {if $_c['radius_enable'] and $d['is_radius']} @@ -187,14 +187,14 @@ {if !$d['is_radius']}
    -
    on-login / on-up
    +
    {Lang::T('on-login / on-up')}
    -
    on-logout / on-down
    +
    {Lang::T('on-logout / on-down')}
    @@ -252,4 +252,4 @@ }); -{include file="sections/footer.tpl"} \ No newline at end of file +{include file="sections/footer.tpl"} From 57ce1c816c5f85c37e67079f4386e54418f5429d Mon Sep 17 00:00:00 2001 From: Ahmad Husein <48185559+ahmadhusein17@users.noreply.github.com> Date: Tue, 20 Aug 2024 20:30:08 +0700 Subject: [PATCH 175/841] Update pppoe.tpl --- ui/ui/pppoe.tpl | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/ui/ui/pppoe.tpl b/ui/ui/pppoe.tpl index a35904e0..dc1da881 100644 --- a/ui/ui/pppoe.tpl +++ b/ui/ui/pppoe.tpl @@ -26,9 +26,9 @@
    @@ -88,8 +88,8 @@
    @@ -133,13 +133,13 @@ {foreach $d as $ds} {$ds['name_plan']} - {$ds['plan_type']} {if $ds['prepaid'] != 'yes'}Postpaid{else}Prepaid{/if} + {$ds['plan_type']} {if $ds['prepaid'] != 'yes'}{Lang::T('Postpaid')}{else}{Lang::T('Prepaid')}{/if} {$ds['name_bw']} {Lang::moneyFormat($ds['price'])} {$ds['validity']} {$ds['validity_unit']} {$ds['pool']} {if $ds['plan_expired']}Yes{else}No + href="{$_url}services/edit/{$ds['plan_expired']}">{Lang::T('Yes')}{else}{Lang::T('No')} {/if} {if $ds['prepaid'] == no}{$ds['expired_date']}{/if} @@ -168,12 +168,12 @@
    -{include file="sections/footer.tpl"} \ No newline at end of file +{include file="sections/footer.tpl"} From 8bf5c71800b320fec6d1c7bed209c3180a945e80 Mon Sep 17 00:00:00 2001 From: Ahmad Husein <48185559+ahmadhusein17@users.noreply.github.com> Date: Wed, 21 Aug 2024 15:01:00 +0700 Subject: [PATCH 176/841] Update radius-nas-add.tpl Update translation --- ui/ui/radius-nas-add.tpl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ui/ui/radius-nas-add.tpl b/ui/ui/radius-nas-add.tpl index 8f109d40..2215bf35 100644 --- a/ui/ui/radius-nas-add.tpl +++ b/ui/ui/radius-nas-add.tpl @@ -4,7 +4,7 @@
    -
    Radius - Add NAS
    +
    Radius - {Lang::T('Add NAS')}
    @@ -34,7 +34,7 @@
    - +
    @@ -67,7 +67,7 @@ {/foreach}
    -

    Assign NAS to Router

    +

    {Lang::T('Assign NAS to Router')}

    @@ -83,4 +83,4 @@
    -{include file="sections/footer.tpl"} \ No newline at end of file +{include file="sections/footer.tpl"} From 26d14794e2574a97cd518adb669e1896bdc2a0a5 Mon Sep 17 00:00:00 2001 From: Ahmad Husein <48185559+ahmadhusein17@users.noreply.github.com> Date: Wed, 21 Aug 2024 15:03:34 +0700 Subject: [PATCH 177/841] Update radius-nas-edit.tpl Update translation --- ui/ui/radius-nas-edit.tpl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ui/ui/radius-nas-edit.tpl b/ui/ui/radius-nas-edit.tpl index 1f1416e8..1dbce21d 100644 --- a/ui/ui/radius-nas-edit.tpl +++ b/ui/ui/radius-nas-edit.tpl @@ -4,7 +4,7 @@
    -
    Radius - Edit NAS
    +
    Radius - {Lang::T('Edit NAS')}
    @@ -34,7 +34,7 @@
    - +
    @@ -67,7 +67,7 @@ {/foreach}
    -

    Assign NAS to Router

    +

    {Lang::T('Assign NAS to Router')}

    @@ -84,4 +84,4 @@
    -{include file="sections/footer.tpl"} \ No newline at end of file +{include file="sections/footer.tpl"} From 95620da151227b2573bfb0f29122dfb12495654b Mon Sep 17 00:00:00 2001 From: Ahmad Husein <48185559+ahmadhusein17@users.noreply.github.com> Date: Wed, 21 Aug 2024 15:05:41 +0700 Subject: [PATCH 178/841] Update radius-nas.tpl Update translation --- ui/ui/radius-nas.tpl | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/ui/ui/radius-nas.tpl b/ui/ui/radius-nas.tpl index 2cdee539..6812017b 100644 --- a/ui/ui/radius-nas.tpl +++ b/ui/ui/radius-nas.tpl @@ -24,16 +24,16 @@
    New NAS + class="ion ion-android-add"> {Lang::T('New NAS')}
     
    - + - + @@ -67,11 +67,11 @@ {include file="pagination.tpl"}

    RADIUS REST

    -

    For Radius REST, you don't need to add NAS, NAS need to add to client.conf manually

    +

    {Lang::T('For Radius REST, you don't need to add NAS, NAS need to add to client.conf manually')}

    -{include file="sections/footer.tpl"} \ No newline at end of file +{include file="sections/footer.tpl"} From b0b687dd38b138a3b5a4c20821f4f8882b41733f Mon Sep 17 00:00:00 2001 From: Ahmad Husein <48185559+ahmadhusein17@users.noreply.github.com> Date: Wed, 21 Aug 2024 15:07:18 +0700 Subject: [PATCH 179/841] Update recharge.tpl Update translation --- ui/ui/recharge.tpl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ui/ui/recharge.tpl b/ui/ui/recharge.tpl index ee767c7b..1e0e441f 100644 --- a/ui/ui/recharge.tpl +++ b/ui/ui/recharge.tpl @@ -54,7 +54,7 @@ -

    Postpaid Recharge for the first time use {$_c['currency_code']} 0

    +

    {Lang::T('Postpaid Recharge for the first time use')} {$_c['currency_code']} 0

    @@ -69,4 +69,4 @@
    -{include file="sections/footer.tpl"} \ No newline at end of file +{include file="sections/footer.tpl"} From 505bb1dd71b6a2af4cbf252e9734a8b058ce226d Mon Sep 17 00:00:00 2001 From: Ahmad Husein <48185559+ahmadhusein17@users.noreply.github.com> Date: Wed, 21 Aug 2024 15:08:11 +0700 Subject: [PATCH 180/841] Update recharge.tpl Update translation --- ui/ui/recharge.tpl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/ui/recharge.tpl b/ui/ui/recharge.tpl index 1e0e441f..b896ab50 100644 --- a/ui/ui/recharge.tpl +++ b/ui/ui/recharge.tpl @@ -60,7 +60,7 @@
    - Or {Lang::T('Cancel')} + {Lang::T('Or')} {Lang::T('Cancel')}
    From c4281f1d548e12e4f055906066005b9fcf71babc Mon Sep 17 00:00:00 2001 From: Ahmad Husein <48185559+ahmadhusein17@users.noreply.github.com> Date: Wed, 21 Aug 2024 15:09:22 +0700 Subject: [PATCH 181/841] Update reports-activation.tpl Update translation --- ui/ui/reports-activation.tpl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ui/ui/reports-activation.tpl b/ui/ui/reports-activation.tpl index 0f57b49a..2845f27e 100644 --- a/ui/ui/reports-activation.tpl +++ b/ui/ui/reports-activation.tpl @@ -4,7 +4,7 @@
    - Activity Log + {Lang::T('Activity Log')}
    @@ -67,4 +67,4 @@
    -{include file="sections/footer.tpl"} \ No newline at end of file +{include file="sections/footer.tpl"} From e21b766a7a9ed0773a1caa50fb58f958e08a102a Mon Sep 17 00:00:00 2001 From: Ahmad Husein <48185559+ahmadhusein17@users.noreply.github.com> Date: Wed, 21 Aug 2024 15:15:27 +0700 Subject: [PATCH 182/841] Update reports.tpl Update translation --- ui/ui/reports.tpl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ui/ui/reports.tpl b/ui/ui/reports.tpl index fbc88bc0..21a39b9f 100644 --- a/ui/ui/reports.tpl +++ b/ui/ui/reports.tpl @@ -11,7 +11,7 @@

    @@ -73,7 +73,7 @@
    -

    {Lang::dateFormat($sd)} - {Lang::dateFormat($ed)} Max 30 days

    +

    {Lang::dateFormat($sd)} - {Lang::dateFormat($ed)} {Lang::T('Max 30 days')}

    From a265b6e766854f9517b78af528dd81c3acc41537 Mon Sep 17 00:00:00 2001 From: Ibnu Maksum Date: Wed, 21 Aug 2024 15:16:29 +0700 Subject: [PATCH 183/841] add placeholder user-header --- ui/ui/sections/user-footer.tpl | 1 + ui/ui/sections/user-header.tpl | 1 + 2 files changed, 2 insertions(+) create mode 100644 ui/ui/sections/user-footer.tpl create mode 100644 ui/ui/sections/user-header.tpl diff --git a/ui/ui/sections/user-footer.tpl b/ui/ui/sections/user-footer.tpl new file mode 100644 index 00000000..439abe2b --- /dev/null +++ b/ui/ui/sections/user-footer.tpl @@ -0,0 +1 @@ +{include file="user-ui/footer.tpl"} \ No newline at end of file diff --git a/ui/ui/sections/user-header.tpl b/ui/ui/sections/user-header.tpl new file mode 100644 index 00000000..c482fc27 --- /dev/null +++ b/ui/ui/sections/user-header.tpl @@ -0,0 +1 @@ +{include file="user-ui/header.tpl"} \ No newline at end of file From e54e5641e62278ba60eeb8f9e03016c9573e635c Mon Sep 17 00:00:00 2001 From: Ibnu Maksum Date: Wed, 21 Aug 2024 15:17:39 +0700 Subject: [PATCH 184/841] add comment --- ui/ui/sections/user-footer.tpl | 4 +++- ui/ui/sections/user-header.tpl | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/ui/ui/sections/user-footer.tpl b/ui/ui/sections/user-footer.tpl index 439abe2b..dbbeff3f 100644 --- a/ui/ui/sections/user-footer.tpl +++ b/ui/ui/sections/user-footer.tpl @@ -1 +1,3 @@ -{include file="user-ui/footer.tpl"} \ No newline at end of file +{include file="user-ui/footer.tpl"} + +{* Don't include this file again, change to user-ui/footer.tpl *} \ No newline at end of file diff --git a/ui/ui/sections/user-header.tpl b/ui/ui/sections/user-header.tpl index c482fc27..a43e5b14 100644 --- a/ui/ui/sections/user-header.tpl +++ b/ui/ui/sections/user-header.tpl @@ -1 +1,3 @@ -{include file="user-ui/header.tpl"} \ No newline at end of file +{include file="user-ui/header.tpl"} + +{* Don't include this file again, change to user-ui/header.tpl *} \ No newline at end of file From d152124eea18b63778e7b33098c9635d5b90f46f Mon Sep 17 00:00:00 2001 From: Ahmad Husein <48185559+ahmadhusein17@users.noreply.github.com> Date: Wed, 21 Aug 2024 15:29:55 +0700 Subject: [PATCH 185/841] Update router-error.tpl Update translation --- ui/ui/router-error.tpl | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/ui/ui/router-error.tpl b/ui/ui/router-error.tpl index 44321cd5..81a8f2ca 100644 --- a/ui/ui/router-error.tpl +++ b/ui/ui/router-error.tpl @@ -49,29 +49,28 @@
    Mikrotik troubleshooting:
      -
    • Make sure you use API Port, Default 8728
    • -
    • Make sure Username and Password are correct
    • -
    • Make sure your hosting not blocking port to external
    • -
    • Make sure your Mikrotik accessible from PHPNuxBill
    • +
    • {Lang::T('Make sure you use API Port, Default 8728')}
    • +
    • {Lang::T('Make sure Username and Password are correct')}
    • +
    • {Lang::T('Make sure your hosting not blocking port to external')}
    • +
    • {Lang::T('Make sure your Mikrotik accessible from PHPNuxBill')}
    - If you just update PHPNuxBill from upload files, try click Update Database + {Lang::T('If you just update PHPNuxBill from upload files, try click Update')} Database
    @@ -83,4 +82,4 @@ - \ No newline at end of file + From f0f9daf72a540134e59db876e1a3c59233f2a8c0 Mon Sep 17 00:00:00 2001 From: Ahmad Husein <48185559+ahmadhusein17@users.noreply.github.com> Date: Wed, 21 Aug 2024 15:35:13 +0700 Subject: [PATCH 186/841] Update routers-add.tpl Update translation --- ui/ui/routers-add.tpl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ui/ui/routers-add.tpl b/ui/ui/routers-add.tpl index 186588f1..5fab1556 100644 --- a/ui/ui/routers-add.tpl +++ b/ui/ui/routers-add.tpl @@ -12,10 +12,10 @@
    @@ -56,7 +56,7 @@
    - +
    @@ -73,4 +73,4 @@
    -{include file="sections/footer.tpl"} \ No newline at end of file +{include file="sections/footer.tpl"} From 803c85c6f4b73e4d84d5f7a2d23bdb6d79929b20 Mon Sep 17 00:00:00 2001 From: Ahmad Husein <48185559+ahmadhusein17@users.noreply.github.com> Date: Wed, 21 Aug 2024 15:36:16 +0700 Subject: [PATCH 187/841] Update routers-edit.tpl Update translation --- ui/ui/routers-edit.tpl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ui/ui/routers-edit.tpl b/ui/ui/routers-edit.tpl index df2ffba2..52e9c97c 100644 --- a/ui/ui/routers-edit.tpl +++ b/ui/ui/routers-edit.tpl @@ -12,11 +12,11 @@
    @@ -148,4 +148,4 @@ } {/literal} -{include file="sections/footer.tpl"} \ No newline at end of file +{include file="sections/footer.tpl"} From e15faf605d1ceee136cca3508f61362320435420 Mon Sep 17 00:00:00 2001 From: Ahmad Husein <48185559+ahmadhusein17@users.noreply.github.com> Date: Wed, 21 Aug 2024 15:40:29 +0700 Subject: [PATCH 188/841] Update routers.tpl Update translation --- ui/ui/routers.tpl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ui/ui/routers.tpl b/ui/ui/routers.tpl index 53c2dd4d..526c4446 100644 --- a/ui/ui/routers.tpl +++ b/ui/ui/routers.tpl @@ -58,7 +58,7 @@ - + - + @@ -135,6 +136,11 @@ + - + @@ -155,7 +155,7 @@ From e78a1ca15e276510fa49ffe83d58844f0b6aea25 Mon Sep 17 00:00:00 2001 From: Ahmad Husein <48185559+ahmadhusein17@users.noreply.github.com> Date: Mon, 26 Aug 2024 17:58:22 +0700 Subject: [PATCH 220/841] Update hotspot-add.tpl --- ui/ui/hotspot-add.tpl | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/ui/ui/hotspot-add.tpl b/ui/ui/hotspot-add.tpl index c596ab2a..9baeb77f 100644 --- a/ui/ui/hotspot-add.tpl +++ b/ui/ui/hotspot-add.tpl @@ -13,8 +13,8 @@ data-content="Customer cannot buy disabled Plan, but admin can recharge it, use it if you want only admin recharge it">?
    - {Lang::T('Enable')} - {Lang::T('Disable')} + {Lang::T('Active')} + {Lang::T('Not Active')}
    @@ -24,8 +24,8 @@ data-content="Postpaid will have fix expired date">?
    - Prepaid - Postpaid + {Lang::T('Prepaid')} + {Lang::T('Postpaid')}
    @@ -36,8 +36,8 @@ data-content="Personal Plan will only show to personal Customer, Business plan will only show to Business Customer">?
    - Personal - Business + {Lang::T('Personal')} + {Lang::T('Business')}
    {if $_c['radius_enable']} @@ -49,7 +49,7 @@

    {Lang::T('Cannot be change after saved')}

    From 502a0a2b0c53042fc3be4b3f6951dedcb4105c6a Mon Sep 17 00:00:00 2001 From: Ahmad Husein <48185559+ahmadhusein17@users.noreply.github.com> Date: Mon, 26 Aug 2024 18:01:13 +0700 Subject: [PATCH 221/841] Update hotspot-edit.tpl --- ui/ui/hotspot-edit.tpl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ui/ui/hotspot-edit.tpl b/ui/ui/hotspot-edit.tpl index 1100e4aa..96b18e9f 100644 --- a/ui/ui/hotspot-edit.tpl +++ b/ui/ui/hotspot-edit.tpl @@ -15,8 +15,8 @@ data-content="Customer cannot buy disabled Plan, but admin can recharge it, use it if you want only admin recharge it">?
    - {Lang::T('Enable')} - {Lang::T('Disable')} + {Lang::T('Active')} + {Lang::T('Not Active')}
    From e31aeca2dd315926507f268bddc6e134dcb54792 Mon Sep 17 00:00:00 2001 From: AGSTR <144728914+agstrxyz@users.noreply.github.com> Date: Mon, 26 Aug 2024 19:15:40 +0700 Subject: [PATCH 222/841] Update order.php fix gagal beli voucher paket radius rest --- system/controllers/order.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/system/controllers/order.php b/system/controllers/order.php index 19aae154..144b44aa 100644 --- a/system/controllers/order.php +++ b/system/controllers/order.php @@ -205,7 +205,7 @@ switch ($action) { if (!$plan['enabled']) { r2(U . "home", 'e', 'Plan is not exists'); } - if ($routes['2'] == 'radius') { + if ($plan['is_radius'] == '1') { $router_name = 'radius'; } else { $router_name = $plan['routers']; From 1a70e2232c33b23c14277074fa6b12067237ac5c Mon Sep 17 00:00:00 2001 From: AGSTR <144728914+agstrxyz@users.noreply.github.com> Date: Mon, 26 Aug 2024 20:09:45 +0700 Subject: [PATCH 223/841] Update order.php --- system/controllers/order.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/system/controllers/order.php b/system/controllers/order.php index 144b44aa..0d4b2a3c 100644 --- a/system/controllers/order.php +++ b/system/controllers/order.php @@ -436,8 +436,9 @@ switch ($action) { run_hook('customer_buy_plan'); #HOOK include $PAYMENTGATEWAY_PATH . DIRECTORY_SEPARATOR . $gateway . '.php'; call_user_func($gateway . '_validate_config'); - - if ($routes['2'] == 'radius') { + + $plan = ORM::for_table('tbl_plans')->where('enabled', '1')->find_one($routes['3']); + if ($plan['is_radius'] == '1') { $router['id'] = 0; $router['name'] = 'radius'; } else if ($routes['2'] > 0) { @@ -446,7 +447,6 @@ switch ($action) { $router['id'] = 0; $router['name'] = 'balance'; } - $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")); } From 76ac9431b3090d40b30c104a3364247be0c79222 Mon Sep 17 00:00:00 2001 From: Focuslinkstech <45756999+Focuslinkstech@users.noreply.github.com> Date: Tue, 27 Aug 2024 00:26:52 +0100 Subject: [PATCH 224/841] added router online status, also add monitor and also report to admin when goes offline, report depend on cron runtime --- install/phpnuxbill.sql | 2 ++ system/cron.php | 61 ++++++++++++++++++++++++++++++++++++++++++ system/updates.json | 4 +++ ui/ui/routers.tpl | 50 +++++++++++++++++++++------------- 4 files changed, 98 insertions(+), 19 deletions(-) diff --git a/install/phpnuxbill.sql b/install/phpnuxbill.sql index 659194f0..d6645f60 100644 --- a/install/phpnuxbill.sql +++ b/install/phpnuxbill.sql @@ -138,6 +138,8 @@ CREATE TABLE `tbl_routers` ( `password` varchar(60) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, `description` varchar(256) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL, `coordinates` VARCHAR(50) NOT NULL DEFAULT '', + `status` ENUM('Online', 'Offline') DEFAULT 'Online', + `last_seen` DATETIME, `coverage` VARCHAR(8) NOT NULL DEFAULT '0', `enabled` tinyint(1) NOT NULL DEFAULT '1' COMMENT '0 disabled' ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; diff --git a/system/cron.php b/system/cron.php index caae5c05..a0862d23 100644 --- a/system/cron.php +++ b/system/cron.php @@ -78,3 +78,64 @@ foreach ($d as $ds) { echo " : ACTIVE \r\n"; } } + +$routers = ORM::for_table('tbl_routers')->find_many(); +if (!$routers) { + echo "No routers found in the database.\n"; + exit; +} + +foreach ($routers as $router) { + [$ip, $port] = explode(':', $router->ip_address); + $isOnline = false; + + try { + $timeout = 5; + if (is_callable('fsockopen') && false === stripos(ini_get('disable_functions'), 'fsockopen')) { + $fsock = @fsockopen($ip, $port, $errno, $errstr, $timeout); + if ($fsock) { + fclose($fsock); + $isOnline = true; + } else { + throw new Exception("Unable to connect to $ip on port $port using fsockopen: $errstr ($errno)"); + } + } elseif (is_callable('stream_socket_client') && false === stripos(ini_get('disable_functions'), 'stream_socket_client')) { + $connection = @stream_socket_client("$ip:$port", $errno, $errstr, $timeout); + if ($connection) { + fclose($connection); + $isOnline = true; + } else { + throw new Exception("Unable to connect to $ip on port $port using stream_socket_client: $errstr ($errno)"); + } + } else { + throw new Exception("Neither fsockopen nor stream_socket_client are enabled on the server."); + } + } catch (Exception $e) { + _log($e->getMessage()); + $adminEmail = $config['mail_from']; + $subject = "Router Monitoring Error Alert"; + $message = "An error occurred during the monitoring of router $ip: " . (string) $e->getMessage(); + Message::SendEmail($adminEmail, $subject, $message); + sendTelegram($message); + } + + if ($isOnline) { + $router->last_seen = date('Y-m-d H:i:s'); + $router->status = 'Online'; + } else { + $router->status = 'Offline'; + $adminEmail = $config['mail_from']; + $subject = "Router Offline Alert"; + $message = "Dear Administrator,\nThe router with Name: {$router->name} and IP: {$router->ip_address} appears to be offline.\nThe Router was last seen online on: {$router->last_seen}\nPlease check the router's status and take appropriate action.\n\nBest regards,\nRouter Monitoring System"; + Message::SendEmail($adminEmail, $subject, $message); + sendTelegram($message); + } + + $router->save(); +} + +if ($isCli) { + echo "Cronjob finished\n"; +} else { + echo ""; +} \ No newline at end of file diff --git a/system/updates.json b/system/updates.json index 00e214cc..f9f05bf1 100644 --- a/system/updates.json +++ b/system/updates.json @@ -151,5 +151,9 @@ ], "2024.8.7" : [ "ALTER TABLE `tbl_customers` CHANGE `coordinates` `coordinates` VARCHAR(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT 'Latitude and Longitude coordinates';" + ], + "2024.8.27" : [ + "ALTER TABLE `tbl_routers` ADD `status` ENUM('Online', 'Offline') DEFAULT 'Online', AFTER `coordinates`;", + "ALTER TABLE `tbl_routers` ADD `last_seen` DATETIME AFTER `status`;" ] } \ No newline at end of file diff --git a/ui/ui/routers.tpl b/ui/ui/routers.tpl index 526c4446..3422a5b9 100644 --- a/ui/ui/routers.tpl +++ b/ui/ui/routers.tpl @@ -40,6 +40,8 @@
    + + @@ -47,27 +49,37 @@ {foreach $d as $ds} - - + - - - - - - - + {$ds['name']} + + + + + + + + + + {/foreach}
    Name{Lang::T('Name')} IPType{Lang::T('Type')} Port Server Community {$ds['ip_address']} {$ds['username']} {$ds['description']}{if $ds['enabled'] == 1}Enabled{else}Disabled{/if}{if $ds['enabled'] == 1}{Lang::T('Enabled')}{else}{Lang::T('Disabled')}{/if} {Lang::T('Edit')} @@ -78,4 +78,4 @@ -{include file="sections/footer.tpl"} \ No newline at end of file +{include file="sections/footer.tpl"} From f53e60161abc85a9e22eaae3697508c4f6933a31 Mon Sep 17 00:00:00 2001 From: Ahmad Husein <48185559+ahmadhusein17@users.noreply.github.com> Date: Wed, 21 Aug 2024 15:45:41 +0700 Subject: [PATCH 189/841] Update voucher.tpl Update translation --- ui/ui/voucher.tpl | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/ui/ui/voucher.tpl b/ui/ui/voucher.tpl index 1497424b..6f357b48 100644 --- a/ui/ui/voucher.tpl +++ b/ui/ui/voucher.tpl @@ -9,7 +9,7 @@
    Print + class="ion ion-android-print"> {Lang::T('Print')}
    @@ -20,7 +20,7 @@
    Delete > 3 Months + aria-hidden="true"> {Lang::T('Delete')} > {Lang::T('3 Months')}
    {/if}   @@ -111,8 +111,8 @@ onmouseleave="this.style.backgroundColor = 'black';" onmouseenter="this.style.backgroundColor = 'white';"> {$ds['code']}
    {if $ds['status'] eq '0'} {else} + {if $ds['status'] eq '0'} {else} {/if} {if $ds['user'] eq '0'} - {else}{$ds['user']} @@ -141,4 +141,4 @@ {include file="pagination.tpl"} -{include file="sections/footer.tpl"} \ No newline at end of file +{include file="sections/footer.tpl"} From 0bb1f8ffa0ef64ebeadb2d896b4fd8d31189b8ef Mon Sep 17 00:00:00 2001 From: Ibnu Maksum Date: Wed, 21 Aug 2024 15:23:13 +0700 Subject: [PATCH 190/841] fix show extend_expired --- ui/ui/app-settings.tpl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/ui/app-settings.tpl b/ui/ui/app-settings.tpl index 018cb787..f1d833d5 100644 --- a/ui/ui/app-settings.tpl +++ b/ui/ui/app-settings.tpl @@ -241,8 +241,8 @@

    {Lang::T('Customer can request to extend expirations')}

    From 7172cfbb79c241185c2c70a2cc6aff9d84545bcb Mon Sep 17 00:00:00 2001 From: Ibnu Maksum Date: Wed, 21 Aug 2024 17:05:46 +0700 Subject: [PATCH 191/841] check if pppoe IP or Username has been used by other customer --- system/controllers/autoload.php | 48 +++++++++++++++++++++++++-------- ui/ui/customers-add.tpl | 8 +++--- ui/ui/customers-edit.tpl | 12 ++++----- ui/ui/customers.tpl | 6 +++++ ui/ui/scripts/custom.js | 16 +++++++++++ 5 files changed, 69 insertions(+), 21 deletions(-) diff --git a/system/controllers/autoload.php b/system/controllers/autoload.php index e24af345..c6e9b03c 100644 --- a/system/controllers/autoload.php +++ b/system/controllers/autoload.php @@ -1,4 +1,5 @@ assign('_admin', $admin); switch ($action) { case 'pool': $routers = _get('routers'); - if(empty($routers)){ + if (empty($routers)) { $d = ORM::for_table('tbl_pool')->find_many(); - }else{ + } else { $d = ORM::for_table('tbl_pool')->where('routers', $routers)->find_many(); } $ui->assign('routers', $routers); @@ -34,20 +35,45 @@ switch ($action) { $ui->display('autoload-server.tpl'); break; - + case 'pppoe_ip_used': + if (!empty(_get('ip'))) { + $cs = ORM::for_table('tbl_customers') + ->select("username") + ->where_not_equal('id', _get('id')) + ->where("pppoe_ip", _get('ip')) + ->findArray(); + if (count($cs) > 0) { + $c = array_column($cs, 'username'); + die(Lang::T("IP has been used by") . ' : ' . implode(", ", $c)); + } + } + die(); + case 'pppoe_username_used': + if (!empty(_get('u'))) { + $cs = ORM::for_table('tbl_customers') + ->select("username") + ->where_not_equal('id', _get('id')) + ->where("pppoe_username", _get('u')) + ->findArray(); + if (count($cs) > 0) { + $c = array_column($cs, 'username'); + die(Lang::T("Username has been used by") . ' : ' . implode(", ", $c)); + } + } + die(); case 'plan': $server = _post('server'); $jenis = _post('jenis'); - if(in_array($admin['user_type'], array('SuperAdmin', 'Admin'))){ - if($server=='radius'){ + 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{ + } else { $d = ORM::for_table('tbl_plans')->where('routers', $server)->where('type', $jenis)->find_many(); } - }else{ - if($server=='radius'){ + } else { + if ($server == 'radius') { $d = ORM::for_table('tbl_plans')->where('is_radius', 1)->where('type', $jenis)->where('enabled', '1')->find_many(); - }else{ + } else { $d = ORM::for_table('tbl_plans')->where('routers', $server)->where('type', $jenis)->where('enabled', '1')->find_many(); } } @@ -59,9 +85,9 @@ switch ($action) { $d = ORM::for_table('tbl_user_recharges')->where('customer_id', $routes['2'])->findOne(); if ($d) { if ($d['status'] == 'on') { - die(''.$d['namebp'].''); + die('' . $d['namebp'] . ''); } else { - die(''.$d['namebp'].''); + die('' . $d['namebp'] . ''); } } else { die(''); diff --git a/ui/ui/customers-add.tpl b/ui/ui/customers-add.tpl index 1b0a97b6..1839bcea 100644 --- a/ui/ui/customers-add.tpl +++ b/ui/ui/customers-add.tpl @@ -96,9 +96,9 @@
    PPPOE
    - +
    - + {Lang::T('Not Working for freeradius')}
    @@ -110,9 +110,9 @@
    - +
    - + {Lang::T('Not Working for freeradius')}
    diff --git a/ui/ui/customers-edit.tpl b/ui/ui/customers-edit.tpl index 2941898e..e1ce53f8 100644 --- a/ui/ui/customers-edit.tpl +++ b/ui/ui/customers-edit.tpl @@ -119,11 +119,11 @@
    PPPOE
    - +
    - {Lang::T('Not Working for freeradius')} + onkeyup="checkUsername(this, {$d['id']})" value="{$d['pppoe_username']}"> + {Lang::T('Not Working with Freeradius Mysql')}
    @@ -135,11 +135,11 @@
    - +
    - {Lang::T('Not Working for freeradius')} + onkeyup="checkIP(this, {$d['id']})" value="{$d['pppoe_ip']}"> + {Lang::T('Not Working with Freeradius Mysql')}
    diff --git a/ui/ui/customers.tpl b/ui/ui/customers.tpl index 9eacbce3..f4434ccb 100644 --- a/ui/ui/customers.tpl +++ b/ui/ui/customers.tpl @@ -101,6 +101,7 @@
    {Lang::T('Contact')} {Lang::T('Package')} {Lang::T('Service Type')}PPPOE {Lang::T('Status')} {Lang::T('Created On')} {Lang::T('Manage')} {$ds['service_type']} + {$ds['pppoe_username']} + {if !empty($ds['pppoe_username']) && !empty($ds['pppoe_ip'])}:{/if} + {$ds['pppoe_ip']} + {Lang::T($ds['status'])} {Lang::dateTimeFormat($ds['created_at'])} diff --git a/ui/ui/scripts/custom.js b/ui/ui/scripts/custom.js index 7b33f116..844f5ffc 100644 --- a/ui/ui/scripts/custom.js +++ b/ui/ui/scripts/custom.js @@ -37,6 +37,22 @@ $(document).ready(function () { $("#Hotspot").prop("checked", true).change(); +function checkIP(f, id) { + if (f.value.length > 6) { + $.get('./?_route=autoload/pppoe_ip_used&ip=' + f.value + '&id=' + id, function(data) { + $("#warning_ip").html(data) + }); + } +} + +function checkUsername(f, id) { + if (f.value.length > 1) { + $.get('./?_route=autoload/pppoe_username_used&u=' + f.value + '&id=' + id, function(data) { + $("#warning_username").html(data) + }); + } +} + //auto load pool - pppoe plan var htmlobjek; $(document).ready(function(){ From 55232ac4b3c25533bbab8c3f4583dee684c7c732 Mon Sep 17 00:00:00 2001 From: Ibnu Maksum Date: Wed, 21 Aug 2024 17:09:22 +0700 Subject: [PATCH 192/841] null to '' to delete pppoe_ip --- system/devices/MikrotikPppoe.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/system/devices/MikrotikPppoe.php b/system/devices/MikrotikPppoe.php index 3d2caa23..ef7bf796 100644 --- a/system/devices/MikrotikPppoe.php +++ b/system/devices/MikrotikPppoe.php @@ -52,7 +52,7 @@ class MikrotikPppoe if (!empty($customer['pppoe_ip'])) { $setRequest->setArgument('local-address', $customer['pppoe_ip']); }else{ - $setRequest->setArgument('local-address', null); + $setRequest->setArgument('local-address', ''); } $setRequest->setArgument('profile', $plan['name_plan']); $setRequest->setArgument('comment', $customer['fullname'] . ' | ' . $customer['email'] . ' | ' . implode(', ', User::getBillNames($customer['id']))); From 342fbe25a8cdcdfba914ead516b0ca5a9cbc0f5e Mon Sep 17 00:00:00 2001 From: AGSTR <144728914+agstrxyz@users.noreply.github.com> Date: Wed, 21 Aug 2024 21:31:27 +0700 Subject: [PATCH 193/841] Update Radius.php lokal ip dan profil expired pppoe --- system/devices/Radius.php | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/system/devices/Radius.php b/system/devices/Radius.php index 2544c7c5..634ba2da 100644 --- a/system/devices/Radius.php +++ b/system/devices/Radius.php @@ -88,8 +88,9 @@ class Radius if ($p) { $this->customerAddPlan($customer, $p); } - } + } else { $this->customerDeactivate($customer['username'], true); + } } public function change_username($plan, $from, $to) @@ -257,6 +258,7 @@ class Radius { $this->getTableCustomer()->where_equal('username', $username)->delete_many(); $this->getTableUserPackage()->where_equal('username', $username)->delete_many(); + $this->getTableCustomerAttr()->where_equal('username', $username)->delete_many(); } /** @@ -361,8 +363,16 @@ class Radius } if ($plan['type'] == 'PPPOE') { + if (!empty($customer['pppoe_ip']) && $expired != '') { + $this->upsertCustomerAttr($customer['username'], 'Framed-Pool', $plan['pool'], ':='); + $this->upsertCustomerAttr($customer['username'], 'Framed-IP-Address', $customer['pppoe_ip'], ':='); + $this->upsertCustomerAttr($customer['username'], 'Framed-IP-Netmask', '255.255.255.0', ':='); + }else{ $this->upsertCustomerAttr($customer['username'], 'Framed-Pool', $plan['pool'], ':='); - } + $this->upsertCustomerAttr($customer['username'], 'Framed-IP-Address', '0.0.0.0', ':='); + $this->upsertCustomerAttr($customer['username'], 'Framed-IP-Netmask', '255.255.255.0', ':='); + } + } return true; From be3db525786285905c4123d489e7b11fd59eb4d6 Mon Sep 17 00:00:00 2001 From: Focuslinkstech <45756999+Focuslinkstech@users.noreply.github.com> Date: Wed, 21 Aug 2024 22:09:10 +0100 Subject: [PATCH 194/841] Lets start the journey of our new template from here, lots need to be done --- ui/ui/sections/header.tpl | 117 ++++++++++++++- ui/ui/user-ui/header.tpl | 298 ++++++++++++++++++++++++++++++++++++-- 2 files changed, 403 insertions(+), 12 deletions(-) diff --git a/ui/ui/sections/header.tpl b/ui/ui/sections/header.tpl index a75b6de3..565d498d 100644 --- a/ui/ui/sections/header.tpl +++ b/ui/ui/sections/header.tpl @@ -18,7 +18,118 @@ - From 8c206ba1f8b13233f09f35bad3acd9d45370ae81 Mon Sep 17 00:00:00 2001 From: Focuslinkstech <45756999+Focuslinkstech@users.noreply.github.com> Date: Wed, 21 Aug 2024 22:20:06 +0100 Subject: [PATCH 195/841] fix user footer --- ui/ui/user-ui/header.tpl | 190 +++------------------------------------ 1 file changed, 11 insertions(+), 179 deletions(-) diff --git a/ui/ui/user-ui/header.tpl b/ui/ui/user-ui/header.tpl index d27e9a4d..0e422602 100644 --- a/ui/ui/user-ui/header.tpl +++ b/ui/ui/user-ui/header.tpl @@ -17,6 +17,7 @@ From 34f904ccc4a5374ddbd9f8a62d7f2bcd62526923 Mon Sep 17 00:00:00 2001 From: Focuslinkstech <45756999+Focuslinkstech@users.noreply.github.com> Date: Thu, 22 Aug 2024 02:00:23 +0100 Subject: [PATCH 196/841] Add User Search Bar --- system/controllers/search_user.php | 21 +++++++ ui/ui/sections/footer.tpl | 26 ++++++++ ui/ui/sections/header.tpl | 96 +++++++++++++++++++++++++++++- 3 files changed, 140 insertions(+), 3 deletions(-) create mode 100644 system/controllers/search_user.php diff --git a/system/controllers/search_user.php b/system/controllers/search_user.php new file mode 100644 index 00000000..b3a04062 --- /dev/null +++ b/system/controllers/search_user.php @@ -0,0 +1,21 @@ +where_like('username', "%$query%") + ->find_many(); + + if ($results) { + echo ''; + } else { + echo '

    ' . Lang::T('No users found.') . '

    '; + } +} else { + echo '

    ' . Lang::T('Please enter a search term.') . '

    '; +} diff --git a/ui/ui/sections/footer.tpl b/ui/ui/sections/footer.tpl index 413e9cec..01cb6414 100644 --- a/ui/ui/sections/footer.tpl +++ b/ui/ui/sections/footer.tpl @@ -15,6 +15,32 @@ + + {if isset($xfooter)} {$xfooter} {/if} diff --git a/ui/ui/sections/header.tpl b/ui/ui/sections/header.tpl index 565d498d..8589dd72 100644 --- a/ui/ui/sections/header.tpl +++ b/ui/ui/sections/header.tpl @@ -18,8 +18,10 @@ - {if isset($xheader)} From 0265304069be74bda0f5266aef7663e22a472b96 Mon Sep 17 00:00:00 2001 From: Focuslinkstech <45756999+Focuslinkstech@users.noreply.github.com> Date: Thu, 22 Aug 2024 20:50:00 +0100 Subject: [PATCH 204/841] Add more --- ui/ui/sections/header.tpl | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/ui/ui/sections/header.tpl b/ui/ui/sections/header.tpl index ac6b6e01..c3de8340 100644 --- a/ui/ui/sections/header.tpl +++ b/ui/ui/sections/header.tpl @@ -162,6 +162,17 @@ border-top-left-radius: 3px; } + .content .row [class*=col-] .box { + -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, .1); + -moz-box-shadow: 0 1px 1px rgba(0, 0, 0, .1); + -ms-box-shadow: 0 1px 1px rgba(0, 0, 0, .1); + box-shadow: 0 1px 1px rgba(0, 0, 0, .05); + -webkit-border-radius: 1px !important; + -moz-border-radius: 1px !important; + -ms-border-radius: 1px !important; + border-radius: 25px !important; + } + /* Search Bar Start Here */ .wrap { width: 30%; From cde2706c042867c1204ae47e59c371c3cdf1559a Mon Sep 17 00:00:00 2001 From: Focuslinkstech <45756999+Focuslinkstech@users.noreply.github.com> Date: Thu, 22 Aug 2024 21:26:34 +0100 Subject: [PATCH 205/841] Still on the Journey --- ui/ui/sections/header.tpl | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/ui/ui/sections/header.tpl b/ui/ui/sections/header.tpl index c3de8340..476df2d6 100644 --- a/ui/ui/sections/header.tpl +++ b/ui/ui/sections/header.tpl @@ -173,6 +173,22 @@ border-radius: 25px !important; } + .box.box-solid.box-primary>.box-header { + color: inherit; + background-color: transparent; + border-color: transparent; + } + + .box-footer { + border-top-left-radius: 0; + border-top-right-radius: 0; + border-bottom-right-radius: 25px; + border-bottom-left-radius: 25px; + border-top: 1px solid #f4f4f4; + padding: 10px; + background-color: #f6f6f6; + } + /* Search Bar Start Here */ .wrap { width: 30%; From 9f2f739ba66d805e8bbe5b5db12d73386f7176e3 Mon Sep 17 00:00:00 2001 From: Focuslinkstech <45756999+Focuslinkstech@users.noreply.github.com> Date: Thu, 22 Aug 2024 21:29:09 +0100 Subject: [PATCH 206/841] Fixed --- ui/ui/sections/header.tpl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ui/ui/sections/header.tpl b/ui/ui/sections/header.tpl index 476df2d6..6bf0b85d 100644 --- a/ui/ui/sections/header.tpl +++ b/ui/ui/sections/header.tpl @@ -184,9 +184,9 @@ border-top-right-radius: 0; border-bottom-right-radius: 25px; border-bottom-left-radius: 25px; - border-top: 1px solid #f4f4f4; + border-top: 1px solid transparent; padding: 10px; - background-color: #f6f6f6; + background-color: inherit; } /* Search Bar Start Here */ From 9ca0b3907cbb023c98d667a15de03e645ad63c51 Mon Sep 17 00:00:00 2001 From: Focuslinkstech <45756999+Focuslinkstech@users.noreply.github.com> Date: Thu, 22 Aug 2024 21:30:12 +0100 Subject: [PATCH 207/841] fixed --- ui/ui/sections/header.tpl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ui/ui/sections/header.tpl b/ui/ui/sections/header.tpl index 6bf0b85d..476df2d6 100644 --- a/ui/ui/sections/header.tpl +++ b/ui/ui/sections/header.tpl @@ -184,9 +184,9 @@ border-top-right-radius: 0; border-bottom-right-radius: 25px; border-bottom-left-radius: 25px; - border-top: 1px solid transparent; + border-top: 1px solid #f4f4f4; padding: 10px; - background-color: inherit; + background-color: #f6f6f6; } /* Search Bar Start Here */ From b2d9c13c515d3005c81047b025b3cd194e489a9b Mon Sep 17 00:00:00 2001 From: Focuslinkstech <45756999+Focuslinkstech@users.noreply.github.com> Date: Thu, 22 Aug 2024 21:31:37 +0100 Subject: [PATCH 208/841] Fixed --- ui/ui/sections/header.tpl | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/ui/ui/sections/header.tpl b/ui/ui/sections/header.tpl index 476df2d6..03380ed5 100644 --- a/ui/ui/sections/header.tpl +++ b/ui/ui/sections/header.tpl @@ -184,11 +184,12 @@ border-top-right-radius: 0; border-bottom-right-radius: 25px; border-bottom-left-radius: 25px; - border-top: 1px solid #f4f4f4; + border-top: 1px solid transparent; padding: 10px; - background-color: #f6f6f6; + background-color: inherit; } + /* Search Bar Start Here */ .wrap { width: 30%; From 04bc749eaeebe552a7ded57de371b4d19b994176 Mon Sep 17 00:00:00 2001 From: Focuslinkstech <45756999+Focuslinkstech@users.noreply.github.com> Date: Thu, 22 Aug 2024 22:35:11 +0100 Subject: [PATCH 209/841] add more --- ui/ui/sections/header.tpl | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/ui/ui/sections/header.tpl b/ui/ui/sections/header.tpl index 03380ed5..746c161e 100644 --- a/ui/ui/sections/header.tpl +++ b/ui/ui/sections/header.tpl @@ -189,6 +189,13 @@ background-color: inherit; } + .panel-footer { + padding: 10px 15px; + background-color: inherit; + border-top: 1px solid transparent; + border-bottom-right-radius: 25px; + border-bottom-left-radius: 25px; + } /* Search Bar Start Here */ .wrap { From c188a8a91d6fd1aa84a658a9415518b9872478a7 Mon Sep 17 00:00:00 2001 From: Focuslinkstech <45756999+Focuslinkstech@users.noreply.github.com> Date: Fri, 23 Aug 2024 07:54:11 +0100 Subject: [PATCH 210/841] More template fixes --- ui/ui/sections/header.tpl | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/ui/ui/sections/header.tpl b/ui/ui/sections/header.tpl index 746c161e..e6e2d14b 100644 --- a/ui/ui/sections/header.tpl +++ b/ui/ui/sections/header.tpl @@ -163,10 +163,10 @@ } .content .row [class*=col-] .box { - -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, .1); + -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, .05); + box-shadow: 0px 4px 30px rgba(221, 224, 255, .54); -moz-box-shadow: 0 1px 1px rgba(0, 0, 0, .1); -ms-box-shadow: 0 1px 1px rgba(0, 0, 0, .1); - box-shadow: 0 1px 1px rgba(0, 0, 0, .05); -webkit-border-radius: 1px !important; -moz-border-radius: 1px !important; -ms-border-radius: 1px !important; @@ -197,6 +197,18 @@ border-bottom-left-radius: 25px; } + .box { + position: relative; + border-radius: 25px; + background: inherit; + border-top: 3px solid #d2d6de; + margin-bottom: 20px; + width: 100%; + -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, .05); + box-shadow: 0px 4px 30px rgba(221, 224, 255, .54); + } + + /* Search Bar Start Here */ .wrap { width: 30%; From 71f0fc47a653bfabc7f458d0c4d440aac9f40123 Mon Sep 17 00:00:00 2001 From: Focuslinkstech <45756999+Focuslinkstech@users.noreply.github.com> Date: Fri, 23 Aug 2024 08:19:36 +0100 Subject: [PATCH 211/841] more template fixes --- ui/ui/user-ui/header.tpl | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/ui/ui/user-ui/header.tpl b/ui/ui/user-ui/header.tpl index 2d8f3b06..4be9b0e1 100644 --- a/ui/ui/user-ui/header.tpl +++ b/ui/ui/user-ui/header.tpl @@ -17,7 +17,6 @@ {if isset($xheader)} From 1e8cf726c342613a5d0d148cb313eaf934c96f5e Mon Sep 17 00:00:00 2001 From: Focuslinkstech <45756999+Focuslinkstech@users.noreply.github.com> Date: Fri, 23 Aug 2024 09:03:36 +0100 Subject: [PATCH 212/841] more fix --- ui/ui/sections/header.tpl | 16 ++++++++++++++++ ui/ui/user-ui/header.tpl | 30 ++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+) diff --git a/ui/ui/sections/header.tpl b/ui/ui/sections/header.tpl index e6e2d14b..018c31b8 100644 --- a/ui/ui/sections/header.tpl +++ b/ui/ui/sections/header.tpl @@ -178,6 +178,22 @@ background-color: transparent; border-color: transparent; } + .box.box-solid.box-info>.box-header { + color: inherit; + background-color: transparent; + border-color: transparent; + } + .box.box-solid.box-danger>.box-header { + color: inherit; + background-color: transparent; + border-color: transparent; + } + + .box.box-solid.box-warning>.box-header { + color: inherit; + background-color: transparent; + border-color: transparent; + } .box-footer { border-top-left-radius: 0; diff --git a/ui/ui/user-ui/header.tpl b/ui/ui/user-ui/header.tpl index 4be9b0e1..8cc3a740 100644 --- a/ui/ui/user-ui/header.tpl +++ b/ui/ui/user-ui/header.tpl @@ -214,6 +214,36 @@ background: transparent; background-color: transparent; } + .box.box-solid.box-primary>.box-header { + color: inherit; + background-color: transparent; + border-color: transparent; + } + .box.box-solid.box-info>.box-header { + color: inherit; + background-color: transparent; + border-color: transparent; + } + .box.box-solid.box-danger>.box-header { + color: inherit; + background-color: transparent; + border-color: transparent; + } + + .box.box-solid.box-warning>.box-header { + color: inherit; + background-color: transparent; + border-color: transparent; + } + + .box { + position: relative; + border-radius: 25px; + margin-bottom: 20px; + width: 100%; + -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, .05); + box-shadow: 0px 4px 30px rgba(221, 224, 255, .54); + } /* New Customize Interface End Here */ From d34f6919c74438c6edc858f01ce12dffa24797df Mon Sep 17 00:00:00 2001 From: Focuslinkstech <45756999+Focuslinkstech@users.noreply.github.com> Date: Fri, 23 Aug 2024 09:20:25 +0100 Subject: [PATCH 213/841] more fix --- ui/ui/sections/header.tpl | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/ui/ui/sections/header.tpl b/ui/ui/sections/header.tpl index 018c31b8..31ef27fa 100644 --- a/ui/ui/sections/header.tpl +++ b/ui/ui/sections/header.tpl @@ -195,6 +195,12 @@ border-color: transparent; } + .box.box-solid.box-default>.box-header { + color: inherit; + background-color: transparent; + border-color: transparent; + } + .box-footer { border-top-left-radius: 0; border-top-right-radius: 0; From 1d5341cdfeed7d07b5cc4588ce84a76f1b8a63d8 Mon Sep 17 00:00:00 2001 From: Focuslinkstech <45756999+Focuslinkstech@users.noreply.github.com> Date: Sun, 25 Aug 2024 17:18:22 +0100 Subject: [PATCH 214/841] reduce some border radius in template --- ui/ui/sections/header.tpl | 22 ++++++++++++++-------- ui/ui/user-ui/header.tpl | 11 ++++++----- 2 files changed, 20 insertions(+), 13 deletions(-) diff --git a/ui/ui/sections/header.tpl b/ui/ui/sections/header.tpl index 31ef27fa..da0e0a4c 100644 --- a/ui/ui/sections/header.tpl +++ b/ui/ui/sections/header.tpl @@ -137,8 +137,9 @@ .panel { margin-bottom: 20px; background-color: #fff; - border: 0px solid transparent; - border-radius: 21px; + border: 2px solid; + border-color: rgba(221, 224, 255, .54); + border-radius: 25px; -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, .05); box-shadow: 0px 4px 30px rgba(221, 224, 255, .54); } @@ -170,7 +171,8 @@ -webkit-border-radius: 1px !important; -moz-border-radius: 1px !important; -ms-border-radius: 1px !important; - border-radius: 25px !important; + border-radius: 15px !important; + border-color: rgba(221, 224, 255, .54); } .box.box-solid.box-primary>.box-header { @@ -178,11 +180,13 @@ background-color: transparent; border-color: transparent; } + .box.box-solid.box-info>.box-header { color: inherit; background-color: transparent; border-color: transparent; } + .box.box-solid.box-danger>.box-header { color: inherit; background-color: transparent; @@ -204,8 +208,8 @@ .box-footer { border-top-left-radius: 0; border-top-right-radius: 0; - border-bottom-right-radius: 25px; - border-bottom-left-radius: 25px; + border-bottom-right-radius: 15px; + border-bottom-left-radius: 15px; border-top: 1px solid transparent; padding: 10px; background-color: inherit; @@ -215,13 +219,13 @@ padding: 10px 15px; background-color: inherit; border-top: 1px solid transparent; - border-bottom-right-radius: 25px; - border-bottom-left-radius: 25px; + border-bottom-right-radius: 15px; + border-bottom-left-radius: 15px; } .box { position: relative; - border-radius: 25px; + border-radius: 15px; background: inherit; border-top: 3px solid #d2d6de; margin-bottom: 20px; @@ -301,6 +305,8 @@ overflow-y: auto; } + + /* Search Bar End Here */ /* New Customize Interface End Here */ diff --git a/ui/ui/user-ui/header.tpl b/ui/ui/user-ui/header.tpl index 8cc3a740..c0aead33 100644 --- a/ui/ui/user-ui/header.tpl +++ b/ui/ui/user-ui/header.tpl @@ -178,14 +178,15 @@ } .content .row [class*=col-] .box { - -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, .1); + -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, .05); + box-shadow: 4px 4px 30px rgba(221, 224, 255, .54); -moz-box-shadow: 0 1px 1px rgba(0, 0, 0, .1); -ms-box-shadow: 0 1px 1px rgba(0, 0, 0, .1); - -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, .05); - box-shadow: 0px 4px 30px rgba(221, 224, 255, .54); + -webkit-border-radius: 1px !important; -moz-border-radius: 1px !important; -ms-border-radius: 1px !important; - border-radius: 25px !important; + border-radius: 15px !important; + border-color: rgba(221, 224, 255, .54); } .box.box-solid.box-info>.box-header { @@ -238,7 +239,7 @@ .box { position: relative; - border-radius: 25px; + border-radius: 15px; margin-bottom: 20px; width: 100%; -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, .05); From 9e917536c0a85fbce186434234e849d5ba1b5eef Mon Sep 17 00:00:00 2001 From: Focuslinkstech <45756999+Focuslinkstech@users.noreply.github.com> Date: Sun, 25 Aug 2024 17:23:18 +0100 Subject: [PATCH 215/841] fix border-radius --- ui/ui/sections/header.tpl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ui/ui/sections/header.tpl b/ui/ui/sections/header.tpl index da0e0a4c..764e8d41 100644 --- a/ui/ui/sections/header.tpl +++ b/ui/ui/sections/header.tpl @@ -219,8 +219,8 @@ padding: 10px 15px; background-color: inherit; border-top: 1px solid transparent; - border-bottom-right-radius: 15px; - border-bottom-left-radius: 15px; + border-bottom-right-radius: 25px; + border-bottom-left-radius: 25px; } .box { From 2f85240689ea7d2faadfb8c1fe8e5f219df877b5 Mon Sep 17 00:00:00 2001 From: Focuslinkstech <45756999+Focuslinkstech@users.noreply.github.com> Date: Sun, 25 Aug 2024 17:37:02 +0100 Subject: [PATCH 216/841] add border color --- ui/ui/sections/header.tpl | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/ui/ui/sections/header.tpl b/ui/ui/sections/header.tpl index 764e8d41..68fce6e9 100644 --- a/ui/ui/sections/header.tpl +++ b/ui/ui/sections/header.tpl @@ -171,7 +171,7 @@ -webkit-border-radius: 1px !important; -moz-border-radius: 1px !important; -ms-border-radius: 1px !important; - border-radius: 15px !important; + border-radius: 25px !important; border-color: rgba(221, 224, 255, .54); } @@ -180,13 +180,11 @@ background-color: transparent; border-color: transparent; } - .box.box-solid.box-info>.box-header { color: inherit; background-color: transparent; border-color: transparent; } - .box.box-solid.box-danger>.box-header { color: inherit; background-color: transparent; @@ -208,8 +206,8 @@ .box-footer { border-top-left-radius: 0; border-top-right-radius: 0; - border-bottom-right-radius: 15px; - border-bottom-left-radius: 15px; + border-bottom-right-radius: 25px; + border-bottom-left-radius: 25px; border-top: 1px solid transparent; padding: 10px; background-color: inherit; @@ -225,7 +223,7 @@ .box { position: relative; - border-radius: 15px; + border-radius: 25px; background: inherit; border-top: 3px solid #d2d6de; margin-bottom: 20px; @@ -305,8 +303,6 @@ overflow-y: auto; } - - /* Search Bar End Here */ /* New Customize Interface End Here */ From 178dad8e03a27a86483b657d9e0436fbe2651d99 Mon Sep 17 00:00:00 2001 From: Ahmad Husein <48185559+ahmadhusein17@users.noreply.github.com> Date: Mon, 26 Aug 2024 17:43:54 +0700 Subject: [PATCH 217/841] Update pppoe.tpl Language fixes --- ui/ui/pppoe.tpl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ui/ui/pppoe.tpl b/ui/ui/pppoe.tpl index 435d8ccb..3c17d6b1 100644 --- a/ui/ui/pppoe.tpl +++ b/ui/ui/pppoe.tpl @@ -8,7 +8,7 @@ sync - {Lang::T('PPPOE Plans')} + {Lang::T('PPPOE Package')}
    {Lang::T('Name')} {Lang::T('Type')}{Lang::T('Bandwidth')}Bandwidth {Lang::T('Category')} {Lang::T('Price')} {Lang::T('Validity')} {$ds['device']} {if $ds['plan_expired']}Yes{else}No + href="{$_url}services/edit/{$ds['plan_expired']}">{Lang::T('Yes')}{else}{Lang::T('No')} {/if} {if $ds['prepaid'] == no}{$ds['expired_date']}{/if} {$ds['id']} {Lang::T('IP Address')} {Lang::T('Username')} {Lang::T('Description')}{Lang::T('Online Status')}{Lang::T('Last Seen')} {Lang::T('Status')} {Lang::T('Manage')} ID
    +
    {if $ds['coordinates']} - + {/if} - {$ds['name']}{$ds['ip_address']}{$ds['username']}{$ds['description']}{if $ds['enabled'] == 1}{Lang::T('Enabled')}{else}{Lang::T('Disabled')}{/if} - {Lang::T('Edit')} - - {$ds['id']}
    {$ds['ip_address']}{$ds['username']}{$ds['description']}{if + $ds['status'] == 'Online'}{Lang::T('Online')}{else}{Lang::T('Offline')}{/if} + {$ds['last_seen']}{if $ds['enabled'] == 1}{Lang::T('Enabled')}{else}{Lang::T('Disabled')}{/if} + {Lang::T('Edit')} + + {$ds['id']}
    From edfa98e6b202cc9dff8144a84e76928b5dbad4e4 Mon Sep 17 00:00:00 2001 From: Focuslinkstech <45756999+Focuslinkstech@users.noreply.github.com> Date: Tue, 27 Aug 2024 08:17:28 +0100 Subject: [PATCH 225/841] Add condition to router check, if enable or not --- system/cron.php | 104 +++++++++++++++++++++-------------------- ui/ui/app-settings.tpl | 15 ++++++ 2 files changed, 68 insertions(+), 51 deletions(-) diff --git a/system/cron.php b/system/cron.php index a0862d23..4b8d63ad 100644 --- a/system/cron.php +++ b/system/cron.php @@ -33,7 +33,7 @@ foreach ($d as $ds) { $c = ORM::for_table('tbl_customers')->where('id', $ds['customer_id'])->find_one(); $p = ORM::for_table('tbl_plans')->where('id', $u['plan_id'])->find_one(); $dvc = Package::getDevice($p); - if($_app_stage != 'demo'){ + if ($_app_stage != 'demo') { if (file_exists($dvc)) { require_once $dvc; (new $p['device'])->remove_customer($c, $p); @@ -79,63 +79,65 @@ foreach ($d as $ds) { } } -$routers = ORM::for_table('tbl_routers')->find_many(); -if (!$routers) { - echo "No routers found in the database.\n"; - exit; -} +if ($config['router_check']) { + $routers = ORM::for_table('tbl_routers')->find_many(); + if (!$routers) { + echo "No routers found in the database.\n"; + exit; + } -foreach ($routers as $router) { - [$ip, $port] = explode(':', $router->ip_address); - $isOnline = false; + foreach ($routers as $router) { + [$ip, $port] = explode(':', $router->ip_address); + $isOnline = false; - try { - $timeout = 5; - if (is_callable('fsockopen') && false === stripos(ini_get('disable_functions'), 'fsockopen')) { - $fsock = @fsockopen($ip, $port, $errno, $errstr, $timeout); - if ($fsock) { - fclose($fsock); - $isOnline = true; + try { + $timeout = 5; + if (is_callable('fsockopen') && false === stripos(ini_get('disable_functions'), 'fsockopen')) { + $fsock = @fsockopen($ip, $port, $errno, $errstr, $timeout); + if ($fsock) { + fclose($fsock); + $isOnline = true; + } else { + throw new Exception("Unable to connect to $ip on port $port using fsockopen: $errstr ($errno)"); + } + } elseif (is_callable('stream_socket_client') && false === stripos(ini_get('disable_functions'), 'stream_socket_client')) { + $connection = @stream_socket_client("$ip:$port", $errno, $errstr, $timeout); + if ($connection) { + fclose($connection); + $isOnline = true; + } else { + throw new Exception("Unable to connect to $ip on port $port using stream_socket_client: $errstr ($errno)"); + } } else { - throw new Exception("Unable to connect to $ip on port $port using fsockopen: $errstr ($errno)"); + throw new Exception("Neither fsockopen nor stream_socket_client are enabled on the server."); } - } elseif (is_callable('stream_socket_client') && false === stripos(ini_get('disable_functions'), 'stream_socket_client')) { - $connection = @stream_socket_client("$ip:$port", $errno, $errstr, $timeout); - if ($connection) { - fclose($connection); - $isOnline = true; - } else { - throw new Exception("Unable to connect to $ip on port $port using stream_socket_client: $errstr ($errno)"); - } - } else { - throw new Exception("Neither fsockopen nor stream_socket_client are enabled on the server."); + } catch (Exception $e) { + _log($e->getMessage()); + $adminEmail = $config['mail_from']; + $subject = "Router Monitoring Error Alert"; + $message = "An error occurred during the monitoring of router $ip: " . (string) $e->getMessage(); + Message::SendEmail($adminEmail, $subject, $message); + sendTelegram($message); } - } catch (Exception $e) { - _log($e->getMessage()); - $adminEmail = $config['mail_from']; - $subject = "Router Monitoring Error Alert"; - $message = "An error occurred during the monitoring of router $ip: " . (string) $e->getMessage(); - Message::SendEmail($adminEmail, $subject, $message); - sendTelegram($message); + + if ($isOnline) { + $router->last_seen = date('Y-m-d H:i:s'); + $router->status = 'Online'; + } else { + $router->status = 'Offline'; + $adminEmail = $config['mail_from']; + $subject = "Router Offline Alert"; + $message = "Dear Administrator,\nThe router with Name: {$router->name} and IP: {$router->ip_address} appears to be offline.\nThe Router was last seen online on: {$router->last_seen}\nPlease check the router's status and take appropriate action.\n\nBest regards,\nRouter Monitoring System"; + Message::SendEmail($adminEmail, $subject, $message); + sendTelegram($message); + } + + $router->save(); } - if ($isOnline) { - $router->last_seen = date('Y-m-d H:i:s'); - $router->status = 'Online'; + if ($isCli) { + echo "Cronjob finished\n"; } else { - $router->status = 'Offline'; - $adminEmail = $config['mail_from']; - $subject = "Router Offline Alert"; - $message = "Dear Administrator,\nThe router with Name: {$router->name} and IP: {$router->ip_address} appears to be offline.\nThe Router was last seen online on: {$router->last_seen}\nPlease check the router's status and take appropriate action.\n\nBest regards,\nRouter Monitoring System"; - Message::SendEmail($adminEmail, $subject, $message); - sendTelegram($message); + echo ""; } - - $router->save(); } - -if ($isCli) { - echo "Cronjob finished\n"; -} else { - echo ""; -} \ No newline at end of file diff --git a/ui/ui/app-settings.tpl b/ui/ui/app-settings.tpl index 5e56539f..c1ca96ef 100644 --- a/ui/ui/app-settings.tpl +++ b/ui/ui/app-settings.tpl @@ -621,6 +621,21 @@

    {Lang::T('This is to notify you when new updates is available')}

    +
    + +
    + +
    +

    {Lang::T('If enabled, the system will notify Admin when router goes Offline, If admin have 10 or more router and many customers, it will get overlapping, you can disabled')} +

    +
    From 1bbc7a30f08c221bd35ca7256a3eab722c693373 Mon Sep 17 00:00:00 2001 From: Ahmad Husein <48185559+ahmadhusein17@users.noreply.github.com> Date: Tue, 27 Aug 2024 18:38:39 +0700 Subject: [PATCH 226/841] Update hotspot-edit.tpl --- ui/ui/hotspot-edit.tpl | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/ui/ui/hotspot-edit.tpl b/ui/ui/hotspot-edit.tpl index 96b18e9f..0818009a 100644 --- a/ui/ui/hotspot-edit.tpl +++ b/ui/ui/hotspot-edit.tpl @@ -5,7 +5,7 @@
    -
    {Lang::T('Edit Service Plan')} || {$d['name_plan']}
    +
    {Lang::T('Edit Service Package')} || {$d['name_plan']}
    @@ -34,7 +34,7 @@
    -
    - +
    - +
    {Lang::T('Unlimited')} @@ -152,7 +152,7 @@
    - +
    {$_c['currency_code']} @@ -182,7 +182,7 @@
    - +
    @@ -231,7 +231,7 @@ {Lang::T('Expired Action')} {Lang::T('Optional')}
    - +

    - {Lang::T('When Expired, customer will be move to selected internet plan')}

    + {Lang::T('When Expired, customer will be move to selected internet package')}

    From dcaa7f9cea58a29397fb084393952b99a5641d83 Mon Sep 17 00:00:00 2001 From: Ahmad Husein <48185559+ahmadhusein17@users.noreply.github.com> Date: Tue, 27 Aug 2024 18:41:11 +0700 Subject: [PATCH 227/841] Update hotspot-add.tpl --- ui/ui/hotspot-add.tpl | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/ui/ui/hotspot-add.tpl b/ui/ui/hotspot-add.tpl index 9baeb77f..ee01b1aa 100644 --- a/ui/ui/hotspot-add.tpl +++ b/ui/ui/hotspot-add.tpl @@ -3,14 +3,14 @@
    -
    {Lang::T('Add Service Plan')}
    +
    {Lang::T('Add Service Package')}
    {Lang::T('Active')} @@ -30,10 +30,10 @@
    -
    - +
    - +
    {Lang::T('Unlimited')} @@ -137,7 +137,7 @@
    - +
    {$_c['currency_code']} @@ -165,7 +165,7 @@
    - +
    From 00f65c6aab42fe9ad71ef71e5b656eb2dea8992a Mon Sep 17 00:00:00 2001 From: Ahmad Husein <48185559+ahmadhusein17@users.noreply.github.com> Date: Tue, 27 Aug 2024 18:44:41 +0700 Subject: [PATCH 228/841] Update hotspot.tpl --- ui/ui/hotspot.tpl | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/ui/ui/hotspot.tpl b/ui/ui/hotspot.tpl index 47516488..d083d0b8 100644 --- a/ui/ui/hotspot.tpl +++ b/ui/ui/hotspot.tpl @@ -6,7 +6,7 @@
    {Lang::T('Hotspot Plans')}
    @@ -98,7 +98,7 @@
    + title="{Lang::T('New Service Package')}">
    @@ -108,8 +108,8 @@ - {Lang::T('Internet Plan')} - Limit + {Lang::T('Internet Package')} + {Lang::T('Limit')} {Lang::T('Expired')} @@ -126,7 +126,7 @@ {Lang::T('Data')} {Lang::T('Location')} {Lang::T('Device')} - {Lang::T('Internet Plan')} + {Lang::T('Internet Package')} {Lang::T('Date')} {Lang::T('ID')} {Lang::T('Manage')} @@ -174,8 +174,8 @@
    From 20e212eaa6ad18327efe8728e842013842caf85b Mon Sep 17 00:00:00 2001 From: Ahmad Husein <48185559+ahmadhusein17@users.noreply.github.com> Date: Tue, 27 Aug 2024 18:46:21 +0700 Subject: [PATCH 229/841] Update balance-add.tpl --- ui/ui/balance-add.tpl | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/ui/ui/balance-add.tpl b/ui/ui/balance-add.tpl index 828c1d1f..ea1dfc93 100644 --- a/ui/ui/balance-add.tpl +++ b/ui/ui/balance-add.tpl @@ -3,29 +3,29 @@
    -
    {Lang::T('Add Service Plan')}
    +
    {Lang::T('Add Service Package')}
    - +
    - +
    {$_c['currency_code']} @@ -56,4 +56,4 @@
    -{include file="sections/footer.tpl"} \ No newline at end of file +{include file="sections/footer.tpl"} From d99a51d40e01f5e91197baea512c28a639bdb935 Mon Sep 17 00:00:00 2001 From: Ahmad Husein <48185559+ahmadhusein17@users.noreply.github.com> Date: Wed, 28 Aug 2024 08:57:02 +0700 Subject: [PATCH 230/841] Update plan.tpl --- ui/ui/plan.tpl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ui/ui/plan.tpl b/ui/ui/plan.tpl index 34ae76ea..4cf71280 100644 --- a/ui/ui/plan.tpl +++ b/ui/ui/plan.tpl @@ -17,6 +17,7 @@
    *} {/if}   +{Lang::T('Active Customers')}
    @@ -136,4 +137,4 @@ } -{include file="sections/footer.tpl"} \ No newline at end of file +{include file="sections/footer.tpl"} From ca26f8baa6c7e69168a723aab8fdec233dabb202 Mon Sep 17 00:00:00 2001 From: Focuslinkstech <45756999+Focuslinkstech@users.noreply.github.com> Date: Wed, 28 Aug 2024 07:23:58 +0100 Subject: [PATCH 231/841] We have tried to mitigate the impact of overlapping and also tried to prevent it or reduced it, we still advice admin to be vigilant --- system/cron.php | 78 ++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 64 insertions(+), 14 deletions(-) diff --git a/system/cron.php b/system/cron.php index 4b8d63ad..c7c9b69f 100644 --- a/system/cron.php +++ b/system/cron.php @@ -79,13 +79,41 @@ foreach ($d as $ds) { } } + if ($config['router_check']) { - $routers = ORM::for_table('tbl_routers')->find_many(); - if (!$routers) { - echo "No routers found in the database.\n"; + + $lockFile = '../system/uploads/router_monitor.lock'; + + if (!is_dir('../system/uploads/')) { + echo "Directory '/system/uploads/' does not exist. Exiting...\n"; exit; } + $lock = fopen($lockFile, 'c'); + + if ($lock === false) { + echo "Failed to open lock file. Exiting...\n"; + exit; + } + + if (!flock($lock, LOCK_EX | LOCK_NB)) { + echo "Script is already running. Exiting...\n"; + fclose($lock); + exit; + } + + $routers = ORM::for_table('tbl_routers')->where('enabled', '1')->find_many(); + if (!$routers) { + echo "No active routers found in the database.\n"; + flock($lock, LOCK_UN); + fclose($lock); + unlink($lockFile); + exit; + } + + $offlineRouters = []; + $errors = []; + foreach ($routers as $router) { [$ip, $port] = explode(':', $router->ip_address); $isOnline = false; @@ -113,11 +141,7 @@ if ($config['router_check']) { } } catch (Exception $e) { _log($e->getMessage()); - $adminEmail = $config['mail_from']; - $subject = "Router Monitoring Error Alert"; - $message = "An error occurred during the monitoring of router $ip: " . (string) $e->getMessage(); - Message::SendEmail($adminEmail, $subject, $message); - sendTelegram($message); + $errors[] = "Error with router $ip: " . $e->getMessage(); } if ($isOnline) { @@ -125,19 +149,45 @@ if ($config['router_check']) { $router->status = 'Online'; } else { $router->status = 'Offline'; - $adminEmail = $config['mail_from']; - $subject = "Router Offline Alert"; - $message = "Dear Administrator,\nThe router with Name: {$router->name} and IP: {$router->ip_address} appears to be offline.\nThe Router was last seen online on: {$router->last_seen}\nPlease check the router's status and take appropriate action.\n\nBest regards,\nRouter Monitoring System"; - Message::SendEmail($adminEmail, $subject, $message); - sendTelegram($message); + $offlineRouters[] = $router; } $router->save(); } - if ($isCli) { + if (!empty($offlineRouters)) { + $message = "Dear Administrator,\n"; + $message .= "The following routers are offline:\n"; + foreach ($offlineRouters as $router) { + $message .= "Name: {$router->name}, IP: {$router->ip_address}, Last Seen: {$router->last_seen}\n"; + } + $message .= "\nPlease check the router's status and take appropriate action.\n\nBest regards,\nRouter Monitoring System"; + + $adminEmail = $config['mail_from']; + $subject = "Router Offline Alert"; + Message::SendEmail($adminEmail, $subject, $message); + sendTelegram($message); + } + + if (!empty($errors)) { + $message = "The following errors occurred during router monitoring:\n"; + foreach ($errors as $error) { + $message .= "$error\n"; + } + + $adminEmail = $config['mail_from']; + $subject = "Router Monitoring Error Alert"; + Message::SendEmail($adminEmail, $subject, $message); + sendTelegram($message); + } + + if (defined('PHP_SAPI') && PHP_SAPI === 'cli') { echo "Cronjob finished\n"; } else { echo ""; } + + flock($lock, LOCK_UN); + fclose($lock); + unlink($lockFile); } From d31274b9836d6148a5ece4c8b155194e5a22d06e Mon Sep 17 00:00:00 2001 From: Ibnu Maksum Date: Wed, 28 Aug 2024 13:58:40 +0700 Subject: [PATCH 232/841] Fix Cron Router check, go to cache instead uploads folder. and check if Mikrotik using Default port --- system/cron.php | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/system/cron.php b/system/cron.php index c7c9b69f..e4e6719c 100644 --- a/system/cron.php +++ b/system/cron.php @@ -82,10 +82,10 @@ foreach ($d as $ds) { if ($config['router_check']) { - $lockFile = '../system/uploads/router_monitor.lock'; + $lockFile = $CACHE_PATH . '/router_monitor.lock'; - if (!is_dir('../system/uploads/')) { - echo "Directory '/system/uploads/' does not exist. Exiting...\n"; + if (!is_dir($CACHE_PATH)) { + echo "Directory '$CACHE_PATH' does not exist. Exiting...\n"; exit; } @@ -115,7 +115,13 @@ if ($config['router_check']) { $errors = []; foreach ($routers as $router) { - [$ip, $port] = explode(':', $router->ip_address); + // check if custom port + if (strpos($router->ip_address, ':') === false){ + $ip = $router->ip_address; + $port = 8728; + } else { + [$ip, $port] = explode(':', $router->ip_address); + } $isOnline = false; try { @@ -186,7 +192,7 @@ if ($config['router_check']) { } else { echo ""; } - + flock($lock, LOCK_UN); fclose($lock); unlink($lockFile); From 9b418ed078e32b43d7aa45dd5e547544cce22575 Mon Sep 17 00:00:00 2001 From: Ibnu Maksum Date: Wed, 28 Aug 2024 13:59:09 +0700 Subject: [PATCH 233/841] Add Info to enable Router check, don't show Router status if not enabled --- ui/ui/routers.tpl | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/ui/ui/routers.tpl b/ui/ui/routers.tpl index 3422a5b9..00a08a81 100644 --- a/ui/ui/routers.tpl +++ b/ui/ui/routers.tpl @@ -40,7 +40,9 @@ {Lang::T('IP Address')} {Lang::T('Username')} {Lang::T('Description')} - {Lang::T('Online Status')} + {if $config['router_check']} + {Lang::T('Online Status')} + {/if} {Lang::T('Last Seen')} {Lang::T('Status')} {Lang::T('Manage')} @@ -65,10 +67,12 @@ onmouseleave="this.style.backgroundColor = 'black';" onmouseenter="this.style.backgroundColor = 'white';">{$ds['username']} {$ds['description']} - {if - $ds['status'] == 'Online'}{Lang::T('Online')}{else}{Lang::T('Offline')}{/if} - + {if $config['router_check']} + {if + $ds['status'] == 'Online'}{Lang::T('Online')}{else}{Lang::T('Offline')}{/if} + + {/if} {$ds['last_seen']} {if $ds['enabled'] == 1}{Lang::T('Enabled')}{else}{Lang::T('Disabled')}{/if} @@ -85,9 +89,14 @@
    {include file="pagination.tpl"} +
    +

    {Lang::T('Check if Mikrotik Online?')}

    +

    {Lang::T('To check if Mikrotik is Online or not, go to Settings, set Router Check Enabled')}

    +
    + {include file="sections/footer.tpl"} From 7963c2f3883578ceb053767d18f8ae94d324913b Mon Sep 17 00:00:00 2001 From: Ibnu Maksum Date: Wed, 28 Aug 2024 14:04:42 +0700 Subject: [PATCH 234/841] fix update script to add status in tbl_routers --- system/updates.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/system/updates.json b/system/updates.json index f9f05bf1..bce2f4ef 100644 --- a/system/updates.json +++ b/system/updates.json @@ -152,8 +152,8 @@ "2024.8.7" : [ "ALTER TABLE `tbl_customers` CHANGE `coordinates` `coordinates` VARCHAR(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT 'Latitude and Longitude coordinates';" ], - "2024.8.27" : [ - "ALTER TABLE `tbl_routers` ADD `status` ENUM('Online', 'Offline') DEFAULT 'Online', AFTER `coordinates`;", + "2024.8.28" : [ + "ALTER TABLE `tbl_routers` ADD `status` ENUM('Online', 'Offline') DEFAULT 'Online' AFTER `coordinates`;", "ALTER TABLE `tbl_routers` ADD `last_seen` DATETIME AFTER `status`;" ] } \ No newline at end of file From 11ec4185e74df76416a1734d8dc1e486986d1de3 Mon Sep 17 00:00:00 2001 From: Ibnu Maksum Date: Wed, 28 Aug 2024 14:18:19 +0700 Subject: [PATCH 235/841] Show Offline routers in the dashboard --- system/controllers/dashboard.php | 6 ++ ui/ui/dashboard.tpl | 21 ++++++- ui/ui/routers.tpl | 94 +++++++++++++++++--------------- 3 files changed, 76 insertions(+), 45 deletions(-) diff --git a/system/controllers/dashboard.php b/system/controllers/dashboard.php index 1bb592e9..81b95402 100644 --- a/system/controllers/dashboard.php +++ b/system/controllers/dashboard.php @@ -209,6 +209,12 @@ if (file_exists($cacheMSfile) && time() - filemtime($cacheMSfile) < 43200) { file_put_contents($cacheMSfile, json_encode($monthlySales)); } +if ($config['router_check']) { + $routeroffs = ORM::for_table('tbl_routers')->selects(['id', 'name', 'last_seen'])->where('status', 'Offline')->order_by_desc('name')->find_array(); + print_r($routeroffs); + $ui->assign('routeroffs', $routeroffs); +} + // Assign the monthly sales data to Smarty $ui->assign('start_date', $start_date); $ui->assign('current_date', $current_date); diff --git a/ui/ui/dashboard.tpl b/ui/ui/dashboard.tpl index 7b2abee7..256282d6 100644 --- a/ui/ui/dashboard.tpl +++ b/ui/ui/dashboard.tpl @@ -175,6 +175,25 @@
    + {if $_c['router_check']} +
    +
    {Lang::T('Routers Offline')}
    +
    + + + {foreach $routeroffs as $ros} + + + + + {/foreach} + +
    {$ros['name']}{Lang::timeElapsed($ros['last_seen'])} +
    +
    +
    + {/if} {if $_c['hide_pg'] != 'yes'}
    {Lang::T('Payment Gateway')}: {str_replace(',',', ',$_c['payment_gateway'])} @@ -337,7 +356,7 @@ //lets calculate the inactive users as reported var expired = u_all - u_act; var inactive = c_all - u_all; - if(inactive < 0){ + if (inactive < 0) { inactive = 0; } // Create the chart data diff --git a/ui/ui/routers.tpl b/ui/ui/routers.tpl index 00a08a81..58b63aef 100644 --- a/ui/ui/routers.tpl +++ b/ui/ui/routers.tpl @@ -5,10 +5,10 @@
    {Lang::T('Routers')} -
    - - -
    +
    + + +
    @@ -40,10 +40,10 @@ {Lang::T('IP Address')} {Lang::T('Username')} {Lang::T('Description')} - {if $config['router_check']} + {if $_c['router_check']} {Lang::T('Online Status')} + {Lang::T('Last Seen')} {/if} - {Lang::T('Last Seen')} {Lang::T('Status')} {Lang::T('Manage')} ID @@ -51,52 +51,58 @@ {foreach $d as $ds} - - - {if $ds['coordinates']} - - {/if} - {$ds['name']} - - {$ds['ip_address']} - {$ds['username']} - {$ds['description']} - {if $config['router_check']} - {if - $ds['status'] == 'Online'}{Lang::T('Online')}{else}{Lang::T('Offline')}{/if} + + + {if $ds['coordinates']} + + {/if} + {$ds['name']} - {/if} - {$ds['last_seen']} - {if $ds['enabled'] == 1}{Lang::T('Enabled')}{else}{Lang::T('Disabled')}{/if} - - {Lang::T('Edit')} - - - {$ds['id']} - + {$ds['ip_address']} + {$ds['username']} + {$ds['description']} + {if $_c['router_check']} + + + {if $ds['status'] == 'Online'} + {Lang::T('Online')} + {else} + {Lang::T('Offline')} + {/if} + + + {$ds['last_seen']} + {/if} + {if $ds['enabled'] == 1}{Lang::T('Enabled')}{else}{Lang::T('Disabled')}{/if} + + {Lang::T('Edit')} + + + {$ds['id']} + {/foreach}
    {include file="pagination.tpl"}
    -

    {Lang::T('Check if Mikrotik Online?')}

    -

    {Lang::T('To check if Mikrotik is Online or not, go to Settings, set Router Check Enabled')}

    -
    +

    {Lang::T('Check if Mikrotik Online?')}

    +

    {Lang::T('To check if Mikrotik is Online or not, go to Settings, set Router Check Enabled')}

    +
    -{include file="sections/footer.tpl"} +{include file="sections/footer.tpl"} \ No newline at end of file From ea814dcaf80321762d1de776fe2e10e95eb319b0 Mon Sep 17 00:00:00 2001 From: Ibnu Maksum Date: Wed, 28 Aug 2024 14:24:07 +0700 Subject: [PATCH 236/841] remove Wise in the community page --- CHANGELOG.md | 12 ++++++++++++ ui/ui/community.tpl | 6 ++---- version.json | 2 +- 3 files changed, 15 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ccbdff79..21df89e6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,18 @@ # CHANGELOG +## 2024.8.28 + +- add Router Status Offline/Online by @Focuslinkstech +- Show Router Offline in the Dashbord +- Fix Translation by by @ahmadhusein17 +- Add Payment Info Page, to show to customer before buy +- Voucher Template +- Change Niceedit to summernote +- Customer can change their language by @Focuslinkstech +- Fix Voucher case sensitive +- 3 Tabs Plugin Manager + ## 2024.8.19 - New Page, Payment Info, To Inform Customer, which payment gateway is good diff --git a/ui/ui/community.tpl b/ui/ui/community.tpl index 894c49ee..aeb31dec 100644 --- a/ui/ui/community.tpl +++ b/ui/ui/community.tpl @@ -79,9 +79,9 @@
    @@ -120,8 +120,6 @@
    diff --git a/version.json b/version.json index 49846b41..1ba9562e 100644 --- a/version.json +++ b/version.json @@ -1,3 +1,3 @@ { - "version": "2024.8.22.1" + "version": "2024.8.28" } \ No newline at end of file From bd9989eaf2c8aa27a7314ccaf8c22749d27c9a23 Mon Sep 17 00:00:00 2001 From: Ibnu Maksum Date: Wed, 28 Aug 2024 14:39:19 +0700 Subject: [PATCH 237/841] hide when no router offline --- ui/ui/dashboard.tpl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/ui/dashboard.tpl b/ui/ui/dashboard.tpl index 256282d6..c549d385 100644 --- a/ui/ui/dashboard.tpl +++ b/ui/ui/dashboard.tpl @@ -175,7 +175,7 @@
    - {if $_c['router_check']} + {if $_c['router_check'] && count($routeroffs)> 0}
    {Lang::T('Routers Offline')}
    From afaafd6195d273554a54022d433d4a74b0cdab3d Mon Sep 17 00:00:00 2001 From: Ibnu Maksum Date: Wed, 28 Aug 2024 14:50:26 +0700 Subject: [PATCH 238/841] remove debug --- system/controllers/dashboard.php | 1 - 1 file changed, 1 deletion(-) diff --git a/system/controllers/dashboard.php b/system/controllers/dashboard.php index 81b95402..02173351 100644 --- a/system/controllers/dashboard.php +++ b/system/controllers/dashboard.php @@ -211,7 +211,6 @@ if (file_exists($cacheMSfile) && time() - filemtime($cacheMSfile) < 43200) { if ($config['router_check']) { $routeroffs = ORM::for_table('tbl_routers')->selects(['id', 'name', 'last_seen'])->where('status', 'Offline')->order_by_desc('name')->find_array(); - print_r($routeroffs); $ui->assign('routeroffs', $routeroffs); } From 1d08e8d204279f94eaa41534c473c6d3d77d16e4 Mon Sep 17 00:00:00 2001 From: Ahmad Husein <48185559+ahmadhusein17@users.noreply.github.com> Date: Wed, 28 Aug 2024 21:38:56 +0700 Subject: [PATCH 239/841] Update admin-add.tpl --- ui/ui/admin-add.tpl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ui/ui/admin-add.tpl b/ui/ui/admin-add.tpl index b68ed50a..5ee3e647 100644 --- a/ui/ui/admin-add.tpl +++ b/ui/ui/admin-add.tpl @@ -89,9 +89,9 @@
    @@ -116,4 +116,4 @@ {/literal} -{include file="sections/footer.tpl"} \ No newline at end of file +{include file="sections/footer.tpl"} From 5d79cb65ce7575ef0241a16b1f8eb92b91b549db Mon Sep 17 00:00:00 2001 From: Ahmad Husein <48185559+ahmadhusein17@users.noreply.github.com> Date: Wed, 28 Aug 2024 21:42:45 +0700 Subject: [PATCH 240/841] Update admin-edit.tpl --- ui/ui/admin-edit.tpl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ui/ui/admin-edit.tpl b/ui/ui/admin-edit.tpl index 9f98de58..d040da65 100644 --- a/ui/ui/admin-edit.tpl +++ b/ui/ui/admin-edit.tpl @@ -56,9 +56,9 @@
    @@ -141,4 +141,4 @@ } {/literal} -{include file="sections/footer.tpl"} \ No newline at end of file +{include file="sections/footer.tpl"} From 8d4d88f7023d83af08fae769959b8e4d07941015 Mon Sep 17 00:00:00 2001 From: Ahmad Husein <48185559+ahmadhusein17@users.noreply.github.com> Date: Wed, 28 Aug 2024 21:46:15 +0700 Subject: [PATCH 241/841] Update app-localisation.tpl --- ui/ui/app-localisation.tpl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ui/ui/app-localisation.tpl b/ui/ui/app-localisation.tpl index e16e70f5..936c3abb 100644 --- a/ui/ui/app-localisation.tpl +++ b/ui/ui/app-localisation.tpl @@ -105,7 +105,7 @@

    - +
    @@ -113,7 +113,7 @@ {Lang::T('Change title in user Plan order')}
    - +
    @@ -121,7 +121,7 @@ {Lang::T('Change title in user Plan order')}
    - +
    @@ -141,4 +141,4 @@
    -{include file="sections/footer.tpl"} \ No newline at end of file +{include file="sections/footer.tpl"} From 0189234b560fcedfee4f2c4cad15e3974f16088f Mon Sep 17 00:00:00 2001 From: Ahmad Husein <48185559+ahmadhusein17@users.noreply.github.com> Date: Wed, 28 Aug 2024 22:08:33 +0700 Subject: [PATCH 242/841] Update app-settings.tpl --- ui/ui/app-settings.tpl | 48 +++++++++++++++++++++--------------------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/ui/ui/app-settings.tpl b/ui/ui/app-settings.tpl index c1ca96ef..6979cdcd 100644 --- a/ui/ui/app-settings.tpl +++ b/ui/ui/app-settings.tpl @@ -196,7 +196,7 @@

    - +
    @@ -216,7 +216,7 @@
    - +
    - +

    {Lang::T('User will get notification when package expired')}

    @@ -485,13 +485,13 @@

    @@ -502,13 +502,13 @@

    @@ -546,7 +546,7 @@

    {Lang::T('This Token will act as SuperAdmin/Admin')}

    @@ -655,11 +655,11 @@
    @@ -759,18 +759,18 @@ + {Lang::T('Custome')}

    {Lang::T('Tax Rates in percentage')}

    From 393939fab4c1944c56b21256cd740b6bb8990c85 Mon Sep 17 00:00:00 2001 From: Ahmad Husein <48185559+ahmadhusein17@users.noreply.github.com> Date: Wed, 28 Aug 2024 22:10:51 +0700 Subject: [PATCH 243/841] Update balance-edit.tpl --- ui/ui/balance-edit.tpl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ui/ui/balance-edit.tpl b/ui/ui/balance-edit.tpl index 2603f61c..5c7d53ad 100644 --- a/ui/ui/balance-edit.tpl +++ b/ui/ui/balance-edit.tpl @@ -3,7 +3,7 @@
    -
    {Lang::T('Edit Service Plan')}
    +
    {Lang::T('Edit Service Package')}
    @@ -19,13 +19,13 @@
    - +
    - +
    - +
    {$_c['currency_code']} From f37987a4c6d814043b31861ccd9140f49b24e1ea Mon Sep 17 00:00:00 2001 From: Ahmad Husein <48185559+ahmadhusein17@users.noreply.github.com> Date: Wed, 28 Aug 2024 22:12:19 +0700 Subject: [PATCH 244/841] Update balance.tpl --- ui/ui/balance.tpl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ui/ui/balance.tpl b/ui/ui/balance.tpl index 54570792..8a09dad1 100644 --- a/ui/ui/balance.tpl +++ b/ui/ui/balance.tpl @@ -3,7 +3,7 @@
    -
    {Lang::T('Balance Plans')}
    +
    {Lang::T('Balance Package')}
    - - + + From aaeaa9305a3b32570052ef24ed116b513781594c Mon Sep 17 00:00:00 2001 From: Ahmad Husein <48185559+ahmadhusein17@users.noreply.github.com> Date: Wed, 28 Aug 2024 22:13:24 +0700 Subject: [PATCH 245/841] Update bandwidth-add.tpl --- ui/ui/bandwidth-add.tpl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ui/ui/bandwidth-add.tpl b/ui/ui/bandwidth-add.tpl index fb9516d7..3375b677 100644 --- a/ui/ui/bandwidth-add.tpl +++ b/ui/ui/bandwidth-add.tpl @@ -70,7 +70,7 @@
    + type="submit">{Lang::T('Save')} Or {Lang::T('Cancel')}
    @@ -81,4 +81,4 @@ -{include file="sections/footer.tpl"} \ No newline at end of file +{include file="sections/footer.tpl"} From bac8819c31bac7b4ba3fd788c056202ff51540a3 Mon Sep 17 00:00:00 2001 From: Ahmad Husein <48185559+ahmadhusein17@users.noreply.github.com> Date: Wed, 28 Aug 2024 22:14:06 +0700 Subject: [PATCH 246/841] Update bandwidth-edit.tpl --- ui/ui/bandwidth-edit.tpl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ui/ui/bandwidth-edit.tpl b/ui/ui/bandwidth-edit.tpl index c74469f3..5e1b23c0 100644 --- a/ui/ui/bandwidth-edit.tpl +++ b/ui/ui/bandwidth-edit.tpl @@ -81,7 +81,7 @@
    + type="submit">{Lang::T('Save Change')} Or {Lang::T('Cancel')}
    @@ -92,4 +92,4 @@ -{include file="sections/footer.tpl"} \ No newline at end of file +{include file="sections/footer.tpl"} From 55349b40dd59f4d78934d483bcca70b1e671818e Mon Sep 17 00:00:00 2001 From: Ahmad Husein <48185559+ahmadhusein17@users.noreply.github.com> Date: Wed, 28 Aug 2024 22:15:01 +0700 Subject: [PATCH 247/841] Update bandwidth.tpl --- ui/ui/bandwidth.tpl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ui/ui/bandwidth.tpl b/ui/ui/bandwidth.tpl index e4dcf0c4..0f5aea1a 100644 --- a/ui/ui/bandwidth.tpl +++ b/ui/ui/bandwidth.tpl @@ -57,8 +57,8 @@ {include file="pagination.tpl"}
    -

    {Lang::T('Create Bandwidth Plan for expired Internet Plan')}

    -

    {Lang::T('When customer expired, you can move it to Expired Internet Plan')}

    +

    {Lang::T('Create Bandwidth Package for expired Internet Package')}

    +

    {Lang::T('When customer expired, you can move it to Expired Internet Package')}

    From a167d97e3cb40c397b3d08d07125c9903afd20b2 Mon Sep 17 00:00:00 2001 From: Ahmad Husein <48185559+ahmadhusein17@users.noreply.github.com> Date: Wed, 28 Aug 2024 22:25:25 +0700 Subject: [PATCH 248/841] Update dashboard.tpl --- ui/ui/dashboard.tpl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ui/ui/dashboard.tpl b/ui/ui/dashboard.tpl index c549d385..5a9767b2 100644 --- a/ui/ui/dashboard.tpl +++ b/ui/ui/dashboard.tpl @@ -112,7 +112,7 @@
    {Lang::T('Plan Name')}{Lang::T('Plan Price')}{Lang::T('Package Name')}{Lang::T('Package Price')} {Lang::T('Manage')}
    - + @@ -145,7 +145,7 @@ - + @@ -437,4 +437,4 @@ {/if} -{include file="sections/footer.tpl"} \ No newline at end of file +{include file="sections/footer.tpl"} From 453ea564cfa4469c701c8d908520b735de835daa Mon Sep 17 00:00:00 2001 From: Ahmad Husein <48185559+ahmadhusein17@users.noreply.github.com> Date: Wed, 28 Aug 2024 22:29:12 +0700 Subject: [PATCH 249/841] Update dbstatus.tpl --- ui/ui/dbstatus.tpl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ui/ui/dbstatus.tpl b/ui/ui/dbstatus.tpl index 0ea24212..0ec2642b 100644 --- a/ui/ui/dbstatus.tpl +++ b/ui/ui/dbstatus.tpl @@ -11,7 +11,7 @@ - + @@ -31,7 +31,7 @@
    + {Lang::T('Download Backup')} Database
    @@ -41,14 +41,14 @@
    -
    {Lang::T('Restore Database')}
    +
    {Lang::T('Restore')} Database
    + {Lang::T('Restore')} Database
    From 5bcf278733a831441eb77500e63596ac3c9f809a Mon Sep 17 00:00:00 2001 From: Ahmad Husein <48185559+ahmadhusein17@users.noreply.github.com> Date: Wed, 28 Aug 2024 22:30:08 +0700 Subject: [PATCH 250/841] Update deposit.tpl --- ui/ui/deposit.tpl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ui/ui/deposit.tpl b/ui/ui/deposit.tpl index 1b086fe7..f901ec5b 100644 --- a/ui/ui/deposit.tpl +++ b/ui/ui/deposit.tpl @@ -16,7 +16,7 @@
    - +
    - - + +
    @@ -61,4 +61,4 @@ -{include file="sections/footer.tpl"} \ No newline at end of file +{include file="sections/footer.tpl"} From 2a2e9c3bd4dd45c92f43b698602763978a47485a Mon Sep 17 00:00:00 2001 From: Ahmad Husein <48185559+ahmadhusein17@users.noreply.github.com> Date: Wed, 28 Aug 2024 22:53:55 +0700 Subject: [PATCH 254/841] Update message.tpl --- ui/ui/message.tpl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ui/ui/message.tpl b/ui/ui/message.tpl index bcb16104..569bd695 100644 --- a/ui/ui/message.tpl +++ b/ui/ui/message.tpl @@ -23,9 +23,9 @@
    From 8e96f1457a9574fa2104fa5eb04b033bc1018eda Mon Sep 17 00:00:00 2001 From: Ahmad Husein <48185559+ahmadhusein17@users.noreply.github.com> Date: Wed, 28 Aug 2024 22:55:30 +0700 Subject: [PATCH 255/841] Update page-edit.tpl --- ui/ui/page-edit.tpl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ui/ui/page-edit.tpl b/ui/ui/page-edit.tpl index 9d0153fb..ecc6fabb 100644 --- a/ui/ui/page-edit.tpl +++ b/ui/ui/page-edit.tpl @@ -27,7 +27,7 @@
    {/if} - +

    {Lang::T('Sometimes you need to refresh 3 times until content change')}

    [[company_name]] {Lang::T('Your Company Name at Settings')}.
    - [[price]] {Lang::T('Plan Price')}.
    + [[price]] {Lang::T('Package Price')}.
    [[voucher_code]] {Lang::T('Voucher Code')}.
    - [[plan]] {Lang::T('Voucher Plan')}.
    + [[plan]] {Lang::T('Voucher Package')}.
    [[counter]] {Lang::T('Counter')}.

    From 9436a6e8f117ac19a2af38a9b5d612a69b884f24 Mon Sep 17 00:00:00 2001 From: Ibnu Maksum Date: Thu, 29 Aug 2024 11:23:57 +0700 Subject: [PATCH 256/841] remove active when extend --- system/controllers/home.php | 2 ++ system/controllers/plan.php | 2 ++ 2 files changed, 4 insertions(+) diff --git a/system/controllers/home.php b/system/controllers/home.php index 7c51018a..147476b5 100644 --- a/system/controllers/home.php +++ b/system/controllers/home.php @@ -188,6 +188,8 @@ if (isset($_GET['recharge']) && !empty($_GET['recharge'])) { if ($_app_stage != 'demo') { if (file_exists($dvc)) { require_once $dvc; + global $isChangePlan; + $isChangePlan = true; (new $p['device'])->add_customer($user, $p); } else { new Exception(Lang::T("Devices Not Found")); diff --git a/system/controllers/plan.php b/system/controllers/plan.php index 59505276..dc92ba6f 100644 --- a/system/controllers/plan.php +++ b/system/controllers/plan.php @@ -848,6 +848,8 @@ switch ($action) { if ($_app_stage != 'demo') { if (file_exists($dvc)) { require_once $dvc; + global $isChangePlan; + $isChangePlan = true; (new $p['device'])->add_customer($c, $p); } else { new Exception(Lang::T("Devices Not Found")); From 82d756567e690b62ac1b906209e88ba301c3007c Mon Sep 17 00:00:00 2001 From: Ibnu Maksum Date: Thu, 29 Aug 2024 15:33:49 +0700 Subject: [PATCH 257/841] add Registration code sms verification code to Language, some carrier block text Verification --- system/controllers/accounts.php | 8 ++++---- system/controllers/register.php | 4 ++-- system/lan/indonesia.json | 3 ++- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/system/controllers/accounts.php b/system/controllers/accounts.php index 5a1e4726..abede61e 100644 --- a/system/controllers/accounts.php +++ b/system/controllers/accounts.php @@ -139,12 +139,12 @@ switch ($action) { 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"); + Message::sendSMS($phone, $config['CompanyName'] . "\n\n" . Lang::T("Verification code") . "\n$otp"); } elseif ($config['phone_otp_type'] === 'whatsapp') { - Message::sendWhatsapp($phone, $config['CompanyName'] . "\n Your Verification code is: $otp"); + Message::sendWhatsapp($phone, $config['CompanyName'] . "\n\n" . Lang::T("Verification code") . "\n$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"); + Message::sendSMS($phone, $config['CompanyName'] . "\n\n" . Lang::T("Verification code") . "\n$otp"); + Message::sendWhatsapp($phone, $config['CompanyName'] . "\n\n" . Lang::T("Verification code") . "\n$otp"); } //redirect after sending OTP r2(U . 'accounts/phone-update', 'e', Lang::T('Verification code has been sent to your phone')); diff --git a/system/controllers/register.php b/system/controllers/register.php index b3269748..3ccedf26 100644 --- a/system/controllers/register.php +++ b/system/controllers/register.php @@ -132,9 +132,9 @@ switch ($do) { } 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'] . "\n\n".Lang::T("Registration code")."\n$otp"); $ui->assign('username', $username); - $ui->assign('notify', 'Verification code has been sent to your phone'); + $ui->assign('notify', 'Registration code has been sent to your phone'); $ui->assign('notify_t', 's'); $ui->display('user-ui/register-otp.tpl'); } diff --git a/system/lan/indonesia.json b/system/lan/indonesia.json index 3708dbb6..cb804e6c 100644 --- a/system/lan/indonesia.json +++ b/system/lan/indonesia.json @@ -571,7 +571,8 @@ "Languge_set_to_indonesia": "Language set to indonesia", "Enable": "Aktifkan", "Diable": "Nonaktifkan", - "Balance" "Saldo", + "Verification_code": "Kod3 V3r1fik@s1", + "Registration_code": "Kod3 R3g1str@s1", "TX": "TX", "RX": "RX", "Database": "Database" From e7ec68872be2b893047f801b11f59463d6440b83 Mon Sep 17 00:00:00 2001 From: Ahmad Husein <48185559+ahmadhusein17@users.noreply.github.com> Date: Thu, 29 Aug 2024 18:17:53 +0700 Subject: [PATCH 258/841] Update header.tpl --- ui/ui/user-ui/header.tpl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ui/ui/user-ui/header.tpl b/ui/ui/user-ui/header.tpl index c0aead33..f57da6bc 100644 --- a/ui/ui/user-ui/header.tpl +++ b/ui/ui/user-ui/header.tpl @@ -422,7 +422,7 @@
  • - {Lang::T('Voucher')} + Voucher
  • {/if} @@ -485,4 +485,4 @@ } }); -{/if} \ No newline at end of file +{/if} From 89786c64af6e5517d826ead4b090e2176acf4a87 Mon Sep 17 00:00:00 2001 From: Ahmad Husein <48185559+ahmadhusein17@users.noreply.github.com> Date: Thu, 29 Aug 2024 18:25:29 +0700 Subject: [PATCH 259/841] Update orderBalance.tpl --- ui/ui/user-ui/orderBalance.tpl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/ui/user-ui/orderBalance.tpl b/ui/ui/user-ui/orderBalance.tpl index d68316ae..ce5ecfe2 100644 --- a/ui/ui/user-ui/orderBalance.tpl +++ b/ui/ui/user-ui/orderBalance.tpl @@ -4,7 +4,7 @@
    {if $_c['enable_balance'] == 'yes'}
    -
    {Lang::T('Balance Plans')}
    +
    {Lang::T('Buy Balance Plans')}
    {foreach $plans_balance as $plan}
    From 5a84e10b707b5a48da6e6d4e0307629cdf141564 Mon Sep 17 00:00:00 2001 From: Ahmad Husein <48185559+ahmadhusein17@users.noreply.github.com> Date: Thu, 29 Aug 2024 18:30:55 +0700 Subject: [PATCH 260/841] Update orderHistory.tpl --- ui/ui/user-ui/orderHistory.tpl | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/ui/ui/user-ui/orderHistory.tpl b/ui/ui/user-ui/orderHistory.tpl index 3f60a74c..bee69cf4 100644 --- a/ui/ui/user-ui/orderHistory.tpl +++ b/ui/ui/user-ui/orderHistory.tpl @@ -11,14 +11,14 @@
    - - + + - - - - + + + + @@ -53,4 +53,4 @@ -{include file="user-ui/footer.tpl"} \ No newline at end of file +{include file="user-ui/footer.tpl"} From 9099584d7c6ce0baddd0a4e3435bd044de4d3625 Mon Sep 17 00:00:00 2001 From: Ahmad Husein <48185559+ahmadhusein17@users.noreply.github.com> Date: Thu, 29 Aug 2024 18:46:21 +0700 Subject: [PATCH 261/841] Update orderView.tpl --- ui/ui/user-ui/orderView.tpl | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/ui/ui/user-ui/orderView.tpl b/ui/ui/user-ui/orderView.tpl index 6f62ad76..a8d5ab1a 100644 --- a/ui/ui/user-ui/orderView.tpl +++ b/ui/ui/user-ui/orderView.tpl @@ -5,7 +5,7 @@
    - + {if !in_array($trx['routers'],['balance','radius'])}
    @@ -120,7 +120,7 @@ {/if} {/if}
    - + @@ -134,15 +134,15 @@ {/if} {if $trx['status']==1} - -{include file="user-ui/footer.tpl"} \ No newline at end of file +{include file="user-ui/footer.tpl"} From abd22418ce784bf126a273e12e8986f3f3eca0e0 Mon Sep 17 00:00:00 2001 From: Ahmad Husein <48185559+ahmadhusein17@users.noreply.github.com> Date: Thu, 29 Aug 2024 18:55:21 +0700 Subject: [PATCH 262/841] Update profile.tpl --- ui/ui/user-ui/profile.tpl | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/ui/ui/user-ui/profile.tpl b/ui/ui/user-ui/profile.tpl index e63402b5..311ba8e5 100644 --- a/ui/ui/user-ui/profile.tpl +++ b/ui/ui/user-ui/profile.tpl @@ -4,9 +4,8 @@
    -
    {Lang::T('Edit User')}
    +
    {Lang::T('Data Change')}
    -
    @@ -21,7 +20,7 @@
    - +
    @@ -36,25 +35,25 @@
    {if $_c['allow_phone_otp'] != 'yes'}
    - +
    + + placeholder="{if $_c['country_code_phone']!= ''}{$_c['country_code_phone']}{/if} {Lang::T('Phone number')}">
    {else}
    - +
    + + placeholder="{if $_c['country_code_phone']!= ''}{$_c['country_code_phone']}{/if} {Lang::T('Phone number')}"> {Lang::T('Change')} @@ -63,7 +62,6 @@
    {/if} - {if $_c['allow_email_otp'] != 'yes'}
    @@ -87,7 +85,6 @@
    {/if} -
    -
    -{include file="user-ui/footer.tpl"} \ No newline at end of file +{include file="user-ui/footer.tpl"} From fe930a1012265a0c5468860d837b42051cbe3d0a Mon Sep 17 00:00:00 2001 From: Ahmad Husein <48185559+ahmadhusein17@users.noreply.github.com> Date: Thu, 29 Aug 2024 19:01:28 +0700 Subject: [PATCH 263/841] Update selectGateway.tpl --- ui/ui/user-ui/selectGateway.tpl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ui/ui/user-ui/selectGateway.tpl b/ui/ui/user-ui/selectGateway.tpl index aa61a529..1cf6a490 100644 --- a/ui/ui/user-ui/selectGateway.tpl +++ b/ui/ui/user-ui/selectGateway.tpl @@ -41,7 +41,7 @@ {/if}
  • {Lang::T('Type')} {if $plan['prepaid'] eq - 'yes'}Prepaid{else}Postpaid + 'yes'}{Lang::T('Prepaid')}{else}{Lang::T('Postpaid')} {/if} {$plan['type']}
  • @@ -54,7 +54,7 @@ {if $plan['validity']}
  • - {Lang::T('Plan Validity')} {$plan['validity']} + {Lang::T('Validity Periode')} {$plan['validity']} {$plan['validity_unit']}
  • {/if} From 463ee2711613a423003d7d5d844abf865aa87556 Mon Sep 17 00:00:00 2001 From: Ahmad Husein <48185559+ahmadhusein17@users.noreply.github.com> Date: Thu, 29 Aug 2024 19:03:57 +0700 Subject: [PATCH 264/841] Update sendPlan.tpl --- ui/ui/user-ui/sendPlan.tpl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ui/ui/user-ui/sendPlan.tpl b/ui/ui/user-ui/sendPlan.tpl index 601b35a5..2ae39b02 100644 --- a/ui/ui/user-ui/sendPlan.tpl +++ b/ui/ui/user-ui/sendPlan.tpl @@ -38,7 +38,7 @@ {Lang::moneyFormat($plan['price'])} - + @@ -53,7 +53,7 @@
    @@ -64,4 +64,4 @@ -{include file="user-ui/footer.tpl"} \ No newline at end of file +{include file="user-ui/footer.tpl"} From 6da6041cb88bc8ad84f94c0d0428984fb74e3a94 Mon Sep 17 00:00:00 2001 From: Ahmad Husein <48185559+ahmadhusein17@users.noreply.github.com> Date: Thu, 29 Aug 2024 23:33:43 +0700 Subject: [PATCH 265/841] Update admin-add.tpl --- ui/ui/admin-add.tpl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/ui/admin-add.tpl b/ui/ui/admin-add.tpl index 5ee3e647..edd26814 100644 --- a/ui/ui/admin-add.tpl +++ b/ui/ui/admin-add.tpl @@ -89,7 +89,7 @@
    From 34482ff0d429cac6dbc9057c0ead213d58c88c04 Mon Sep 17 00:00:00 2001 From: Ibnu Maksum Date: Fri, 30 Aug 2024 11:22:18 +0700 Subject: [PATCH 266/841] move register button to right --- system/lan/indonesia.json | 1 - ui/ui/user-ui/register-otp.tpl | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/system/lan/indonesia.json b/system/lan/indonesia.json index cb804e6c..470be464 100644 --- a/system/lan/indonesia.json +++ b/system/lan/indonesia.json @@ -538,7 +538,6 @@ "Zip_Code": "Kode Pos", "Phone": "Telepon", "Customer_Geo_Location_Information": "Informasi Lokasi Geo Pelanggan", - "": "", "Code": "Kode", "Send_Personal_Message": "Kirim Pesan Pribadi", "Send_Via": "Kirim melalui", diff --git a/ui/ui/user-ui/register-otp.tpl b/ui/ui/user-ui/register-otp.tpl index 13b656d8..942417d4 100644 --- a/ui/ui/user-ui/register-otp.tpl +++ b/ui/ui/user-ui/register-otp.tpl @@ -112,10 +112,10 @@
    - + {Lang::T('Cancel')}
    - {Lang::T('Cancel')} +

    From 8e2a40d67050367e0cf261ec93ac098ba1687ec6 Mon Sep 17 00:00:00 2001 From: Ibnu Maksum Date: Fri, 30 Aug 2024 11:44:57 +0700 Subject: [PATCH 267/841] Error page for customer --- system/boot.php | 8 ++--- system/controllers/settings.php | 2 +- ui/ui/error-user.tpl | 51 +++++++++++++++++++++++++++ ui/ui/{router-error.tpl => error.tpl} | 0 4 files changed, 56 insertions(+), 5 deletions(-) create mode 100644 ui/ui/error-user.tpl rename ui/ui/{router-error.tpl => error.tpl} (100%) diff --git a/system/boot.php b/system/boot.php index 374a5b24..6ec57409 100644 --- a/system/boot.php +++ b/system/boot.php @@ -129,11 +129,11 @@ try { $e->getTraceAsString() ); if (!Admin::getID()) { - r2(U . 'home', 'e', $e->getMessage()); + $ui->display('error-user.tpl'); die(); } $ui->assign("error_message", $e->getMessage() . '
    ' . $e->getTraceAsString() . '
    '); $ui->assign("error_title", "PHPNuxBill Crash"); - $ui->display('router-error.tpl'); + $ui->display('error.tpl'); die(); } catch (Exception $e) { Message::sendTelegram( @@ -142,10 +142,10 @@ try { $e->getTraceAsString() ); if (!Admin::getID()) { - r2(U . 'home', 'e', $e->getMessage()); + $ui->display('error-user.tpl'); die(); } $ui->assign("error_message", $e->getMessage() . '
    ' . $e->getTraceAsString() . '
    '); $ui->assign("error_title", "PHPNuxBill Crash"); - $ui->display('router-error.tpl'); + $ui->display('error.tpl'); die(); } diff --git a/system/controllers/settings.php b/system/controllers/settings.php index 2363b257..33e4abe9 100644 --- a/system/controllers/settings.php +++ b/system/controllers/settings.php @@ -151,7 +151,7 @@ switch ($action) { $ui->assign("error_message", "Radius table not found.

    " . $e->getMessage() . "

    Download here or here and import it to database.

    Check config.php for radius connection details"); - $ui->display('router-error.tpl'); + $ui->display('error.tpl'); die(); } } diff --git a/ui/ui/error-user.tpl b/ui/ui/error-user.tpl new file mode 100644 index 00000000..9c2c9be5 --- /dev/null +++ b/ui/ui/error-user.tpl @@ -0,0 +1,51 @@ + + + + + + + {ucwords(Lang::T("Error"))} - {$_c['CompanyName']} + + + + + + + +
    +
    +
    {ucwords(Lang::T("Internal Error"))}
    +
    + {Lang::T("Sorry, the software failed to process the request, if it still happening, please tell")} + {$_c['CompanyName']} +
    + +
    + +
    + + {if $_c['tawkto'] != ''} + + + + {/if} + + + + \ No newline at end of file diff --git a/ui/ui/router-error.tpl b/ui/ui/error.tpl similarity index 100% rename from ui/ui/router-error.tpl rename to ui/ui/error.tpl From ef0d19393f4ca8e9ad6f836bde857ffae64376fe Mon Sep 17 00:00:00 2001 From: Ibnu Maksum Date: Fri, 30 Aug 2024 13:53:13 +0700 Subject: [PATCH 268/841] forgot to check enabled router when showing offline router --- system/controllers/dashboard.php | 2 +- version.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/system/controllers/dashboard.php b/system/controllers/dashboard.php index 02173351..4d1c9849 100644 --- a/system/controllers/dashboard.php +++ b/system/controllers/dashboard.php @@ -210,7 +210,7 @@ if (file_exists($cacheMSfile) && time() - filemtime($cacheMSfile) < 43200) { } if ($config['router_check']) { - $routeroffs = ORM::for_table('tbl_routers')->selects(['id', 'name', 'last_seen'])->where('status', 'Offline')->order_by_desc('name')->find_array(); + $routeroffs = ORM::for_table('tbl_routers')->selects(['id', 'name', 'last_seen'])->where('status', 'Offline')->where('enabled', '1')->order_by_desc('name')->find_array(); $ui->assign('routeroffs', $routeroffs); } diff --git a/version.json b/version.json index 1ba9562e..ddfab6f6 100644 --- a/version.json +++ b/version.json @@ -1,3 +1,3 @@ { - "version": "2024.8.28" + "version": "2024.8.30" } \ No newline at end of file From e1008ae61fd59da465cc4fbb1f0972cf20b4dcb3 Mon Sep 17 00:00:00 2001 From: Ibnu Maksum Date: Fri, 30 Aug 2024 14:02:23 +0700 Subject: [PATCH 269/841] move error customer to folder user-ui --- system/boot.php | 4 ++-- ui/ui/{error-user.tpl => user-ui/error.tpl} | 0 2 files changed, 2 insertions(+), 2 deletions(-) rename ui/ui/{error-user.tpl => user-ui/error.tpl} (100%) diff --git a/system/boot.php b/system/boot.php index 6ec57409..83114a30 100644 --- a/system/boot.php +++ b/system/boot.php @@ -129,7 +129,7 @@ try { $e->getTraceAsString() ); if (!Admin::getID()) { - $ui->display('error-user.tpl'); die(); + $ui->display('user-ui/error.tpl'); die(); } $ui->assign("error_message", $e->getMessage() . '
    ' . $e->getTraceAsString() . '
    '); $ui->assign("error_title", "PHPNuxBill Crash"); @@ -142,7 +142,7 @@ try { $e->getTraceAsString() ); if (!Admin::getID()) { - $ui->display('error-user.tpl'); die(); + $ui->display('user-ui/error.tpl'); die(); } $ui->assign("error_message", $e->getMessage() . '
    ' . $e->getTraceAsString() . '
    '); $ui->assign("error_title", "PHPNuxBill Crash"); diff --git a/ui/ui/error-user.tpl b/ui/ui/user-ui/error.tpl similarity index 100% rename from ui/ui/error-user.tpl rename to ui/ui/user-ui/error.tpl From 9e7698f83d065745ec0d2a362cd985894cac82c5 Mon Sep 17 00:00:00 2001 From: Focuslinkstech <45756999+Focuslinkstech@users.noreply.github.com> Date: Sat, 31 Aug 2024 12:37:20 +0100 Subject: [PATCH 270/841] fix WhatsApp welcome message not sending --- system/controllers/customers.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/system/controllers/customers.php b/system/controllers/customers.php index 10f9ae1d..c38d3461 100644 --- a/system/controllers/customers.php +++ b/system/controllers/customers.php @@ -455,7 +455,7 @@ switch ($action) { 'args' => [$d['phonenumber'], $welcomeMessage] ], 'whatsapp' => [ - 'enabled' => isset($_POST['wa']) && $_POST['wa'] == 'wa', + 'enabled' => isset($_POST['wa']), 'method' => 'sendWhatsapp', 'args' => [$d['phonenumber'], $welcomeMessage] ], From a22e2e1b2c4e3108412cee0f29fa1590293b15c6 Mon Sep 17 00:00:00 2001 From: Focuslinkstech <45756999+Focuslinkstech@users.noreply.github.com> Date: Tue, 3 Sep 2024 17:43:39 +0100 Subject: [PATCH 271/841] Dark Mode Journey Has Started --- ui/ui/sections/footer.tpl | 30 +++ ui/ui/sections/header.tpl | 428 +++++++++++++++++++++++++++++++++++++- 2 files changed, 455 insertions(+), 3 deletions(-) diff --git a/ui/ui/sections/footer.tpl b/ui/ui/sections/footer.tpl index 01cb6414..c30c926f 100644 --- a/ui/ui/sections/footer.tpl +++ b/ui/ui/sections/footer.tpl @@ -41,6 +41,36 @@ }); + + {if isset($xfooter)} {$xfooter} {/if} diff --git a/ui/ui/sections/header.tpl b/ui/ui/sections/header.tpl index 26270036..831bc1b7 100644 --- a/ui/ui/sections/header.tpl +++ b/ui/ui/sections/header.tpl @@ -21,7 +21,6 @@ {if isset($xheader)} {$xheader} @@ -570,6 +987,11 @@ +
  • +
    + 🌞 +
    +
  • {Lang::T('Plan Name')}{Lang::T('Package Name')} unused used
    {Lang::T('Username')} {Lang::T('Created / Expired')}{Lang::T('Internet Plan')}{Lang::T('Internet Package')} {Lang::T('Location')}
    {Lang::T('Table Name')} {Lang::T('Rows')}Select{Lang::T('Choose')}
    {Lang::T('Plan Name')}{Lang::T('Gateway')}{Lang::T('Routers')}{Lang::T('Payment Method')}Routers {Lang::T('Type')} {Lang::T('Plan Price')}{Lang::T('Created On')}{Lang::T('Expires On')}{Lang::T('Date Done')}{Lang::T('Method')}{Lang::T('Created on')}{Lang::T('Expires on')}{Lang::T('Date')}{Lang::T('Status')}
    {Lang::T('Plan Validity')}{Lang::T('Validity Periode')} {$plan['validity']} {$plan['validity_unit']}
    {Lang::T('Validity')}{Lang::T('Validity Periode')} {$plan['validity']} {$plan['validity_unit']}
    - - - - - - - - - - - - - - -
    {Lang::T('Type')}{$plan['type']}
    {Lang::T('Price')}{Lang::moneyFormat($plan['price'])}
    {Lang::T('Validity')}{$plan['validity']} {$plan['validity_unit']}
    -
    -
    -
    - {Lang::T('Buy')} - {if $_c['enable_balance'] == 'yes' && $_user['balance']>=$plan['price']} - {Lang::T('Pay With Balance')} - {/if} -
    - {if $_c['enable_balance'] == 'yes' && $_c['allow_balance_transfer'] == 'yes' && $_user['balance']>=$plan['price']} - {Lang::T('Buy for friend')} - {/if} -
    -
    -
    - {/foreach} + {if $_user['service_type'] == 'PPPoE'} + {if Lang::arrayCount($radius_pppoe)>0} + +
    + {foreach $radius_pppoe as $plan} +
    +
    +
    {$plan['name_plan']}
    +
    +
    + + + + + + + + + + + + + + + +
    {Lang::T('Type')}{$plan['type']}
    {Lang::T('Price')}{Lang::moneyFormat($plan['price'])}
    {Lang::T('Validity')}{$plan['validity']} {$plan['validity_unit']}
    +
    - {/if} - {elseif $_user['service_type'] == 'Hotspot'} - {if Lang::arrayCount($radius_hotspot)>0} - -
    - {foreach $radius_hotspot as $plan} -
    -
    -
    {$plan['name_plan']}
    -
    - - - - - - - - - - - - - - - -
    {Lang::T('Type')}{$plan['type']}
    {Lang::T('Price')}{Lang::moneyFormat($plan['price'])}
    {Lang::T('Validity')}{$plan['validity']} {$plan['validity_unit']}
    -
    -
    -
    - {Lang::T('Buy')} - {if $_c['enable_balance'] == 'yes' && $_user['balance']>=$plan['price']} - {Lang::T('Pay With Balance')} - {/if} -
    - {if $_c['enable_balance'] == 'yes' && $_c['allow_balance_transfer'] == 'yes' && $_user['balance']>=$plan['price']} - {Lang::T('Buy for friend')} - {/if} -
    -
    -
    - {/foreach} +
    +
    + {Lang::T('Buy')} + {if $_c['enable_balance'] == 'yes' && $_user['balance']>=$plan['price']} + {Lang::T('Pay With Balance')} + {/if} +
    + {if $_c['enable_balance'] == 'yes' && $_c['allow_balance_transfer'] == 'yes' && + $_user['balance']>=$plan['price']} + {Lang::T('Buy for friend')} + {/if}
    - {/if} - {elseif $_user['service_type'] == 'Others' || $_user['service_type'] == '' && (Lang::arrayCount($radius_pppoe)>0 || Lang::arrayCount($radius_hotspot)>0)} - - {if Lang::arrayCount($radius_pppoe)>0} -
    - {foreach $radius_pppoe as $plan} -
    -
    -
    {$plan['name_plan']}
    -
    - - - - - - - - - - - - - - - -
    {Lang::T('Type')}{$plan['type']}
    {Lang::T('Price')}{Lang::moneyFormat($plan['price'])}
    {Lang::T('Validity')}{$plan['validity']} {$plan['validity_unit']}
    -
    -
    -
    - {Lang::T('Buy')} - {if $_c['enable_balance'] == 'yes' && $_user['balance']>=$plan['price']} - {Lang::T('Pay With Balance')} - {/if} -
    - {if $_c['enable_balance'] == 'yes' && $_c['allow_balance_transfer'] == 'yes' && $_user['balance']>=$plan['price']} - {Lang::T('Buy for friend')} - {/if} -
    -
    -
    - {/foreach} +
    +
    + {/foreach} +
    + {/if} + {elseif $_user['service_type'] == 'Hotspot'} + {if Lang::arrayCount($radius_hotspot)>0} + +
    + {foreach $radius_hotspot as $plan} +
    +
    +
    {$plan['name_plan']}
    +
    +
    + + + + + + + + + + + + + + + +
    {Lang::T('Type')}{$plan['type']}
    {Lang::T('Price')}{Lang::moneyFormat($plan['price'])}
    {Lang::T('Validity')}{$plan['validity']} {$plan['validity_unit']}
    +
    - {/if} - {if Lang::arrayCount($radius_hotspot)>0} - -
    - {foreach $radius_hotspot as $plan} -
    -
    -
    {$plan['name_plan']}
    -
    - - - - - - - - - - - - - - - -
    {Lang::T('Type')}{$plan['type']}
    {Lang::T('Price')}{Lang::moneyFormat($plan['price'])}
    {Lang::T('Validity')}{$plan['validity']} {$plan['validity_unit']}
    -
    -
    -
    - {Lang::T('Buy')} - {if $_c['enable_balance'] == 'yes' && $_user['balance']>=$plan['price']} - {Lang::T('Pay With Balance')} - {/if} -
    - {if $_c['enable_balance'] == 'yes' && $_c['allow_balance_transfer'] == 'yes' && $_user['balance']>=$plan['price']} - {Lang::T('Buy for friend')} - {/if} -
    -
    -
    - {/foreach} +
    +
    + {Lang::T('Buy')} + {if $_c['enable_balance'] == 'yes' && $_user['balance']>=$plan['price']} + {Lang::T('Pay With Balance')} + {/if} +
    + {if $_c['enable_balance'] == 'yes' && $_c['allow_balance_transfer'] == 'yes' && + $_user['balance']>=$plan['price']} + {Lang::T('Buy for friend')} + {/if}
    - {/if} - {/if} +
    +
    + {/foreach} +
    + {/if} + {elseif $_user['service_type'] == 'Others' || $_user['service_type'] == '' && (Lang::arrayCount($radius_pppoe)>0 + || Lang::arrayCount($radius_hotspot)>0)} + + {if Lang::arrayCount($radius_pppoe)>0} +
    + {foreach $radius_pppoe as $plan} +
    +
    +
    {$plan['name_plan']}
    +
    +
    + + + + + + + + + + + + + + + +
    {Lang::T('Type')}{$plan['type']}
    {Lang::T('Price')}{Lang::moneyFormat($plan['price'])}
    {Lang::T('Validity')}{$plan['validity']} {$plan['validity_unit']}
    +
    +
    +
    +
    + {Lang::T('Buy')} + {if $_c['enable_balance'] == 'yes' && $_user['balance']>=$plan['price']} + {Lang::T('Pay With Balance')} + {/if} +
    + {if $_c['enable_balance'] == 'yes' && $_c['allow_balance_transfer'] == 'yes' && + $_user['balance']>=$plan['price']} + {Lang::T('Buy for friend')} + {/if} +
    +
    +
    + {/foreach} +
    + {/if} + {if Lang::arrayCount($radius_hotspot)>0} + +
    + {foreach $radius_hotspot as $plan} +
    +
    +
    {$plan['name_plan']}
    +
    +
    + + + + + + + + + + + + + + + +
    {Lang::T('Type')}{$plan['type']}
    {Lang::T('Price')}{Lang::moneyFormat($plan['price'])}
    {Lang::T('Validity')}{$plan['validity']} {$plan['validity_unit']}
    +
    +
    +
    +
    + {Lang::T('Buy')} + {if $_c['enable_balance'] == 'yes' && $_user['balance']>=$plan['price']} + {Lang::T('Pay With Balance')} + {/if} +
    + {if $_c['enable_balance'] == 'yes' && $_c['allow_balance_transfer'] == 'yes' && + $_user['balance']>=$plan['price']} + {Lang::T('Buy for friend')} + {/if} +
    +
    +
    + {/foreach} +
    + {/if} + {/if} {/if} {foreach $routers as $router} - {if Validator::isRouterHasPlan($plans_hotspot, $router['name']) || Validator::isRouterHasPlan($plans_pppoe, $router['name'])} -
    -
    {$router['name']}
    - {if $router['description'] != ''} -
    - {$router['description']} -
    - {/if} - {if $_user['service_type'] == 'Hotspot' && Validator::countRouterPlan($plans_hotspot, $router['name'])>0} -
    {if $_c['hotspot_plan']==''}Hotspot Plan{else}{$_c['hotspot_plan']}{/if} -
    -
    - {foreach $plans_hotspot as $plan} - {if $router['name'] eq $plan['routers']} -
    -
    -
    {$plan['name_plan']}
    -
    - - - - - - - - - - - - - - - -
    {Lang::T('Type')}{$plan['type']}
    {Lang::T('Price')}{Lang::moneyFormat($plan['price'])}
    {Lang::T('Validity')}{$plan['validity']} {$plan['validity_unit']}
    -
    -
    -
    - {Lang::T('Buy')} - {if $_c['enable_balance'] == 'yes' && $_user['balance']>=$plan['price']} - {Lang::T('Pay With Balance')} - {/if} -
    - {if $_c['enable_balance'] == 'yes' && $_c['allow_balance_transfer'] == 'yes' && $_user['balance']>=$plan['price']} - {Lang::T('Buy for friend')} - {/if} -
    -
    -
    - {/if} - {/foreach} -
    - {/if} - {if $_user['service_type'] == 'PPPoE' && Validator::countRouterPlan($plans_pppoe,$router['name'])>0} -
    {if $_c['pppoe_plan']==''}PPPOE Plan{else}{$_c['pppoe_plan']}{/if}
    -
    - {foreach $plans_pppoe as $plan} - {if $router['name'] eq $plan['routers']} -
    -
    -
    {$plan['name_plan']}
    -
    - - - - - - - - - - - - - - - -
    {Lang::T('Type')}{$plan['type']}
    {Lang::T('Price')}{Lang::moneyFormat($plan['price'])}
    {Lang::T('Validity')}{$plan['validity']} {$plan['validity_unit']}
    -
    -
    -
    - {Lang::T('Buy')} - {if $_c['enable_balance'] == 'yes' && $_user['balance']>=$plan['price']} - {Lang::T('Pay With Balance')} - {/if} -
    - {if $_c['enable_balance'] == 'yes' && $_c['allow_balance_transfer'] == 'yes' && $_user['balance']>=$plan['price']} - {Lang::T('Buy for friend')} - {/if} -
    -
    -
    - {/if} - {/foreach} -
    - {/if} - {if $_user['service_type'] == 'Others' || $_user['service_type'] == '' && (Validator::countRouterPlan($plans_hotspot, $router['name'])>0 || Validator::countRouterPlan($plans_pppoe, $router['name'])>0)} -
    {if $_c['hotspot_plan']==''}Hotspot Plan{else}{$_c['hotspot_plan']}{/if} -
    -
    - {foreach $plans_hotspot as $plan} - {if $router['name'] eq $plan['routers']} -
    -
    -
    {$plan['name_plan']}
    -
    - - - - - - - - - - - - - - - -
    {Lang::T('Type')}{$plan['type']}
    {Lang::T('Price')}{Lang::moneyFormat($plan['price'])}
    {Lang::T('Validity')}{$plan['validity']} {$plan['validity_unit']}
    -
    -
    -
    - {Lang::T('Buy')} - {if $_c['enable_balance'] == 'yes' && $_user['balance']>=$plan['price']} - {Lang::T('Pay With Balance')} - {/if} -
    - {if $_c['enable_balance'] == 'yes' && $_c['allow_balance_transfer'] == 'yes' && $_user['balance']>=$plan['price']} - {Lang::T('Buy for friend')} - {/if} -
    -
    -
    - {/if} - {/foreach} -
    -
    {if $_c['pppoe_plan']==''}PPPOE Plan{else}{$_c['pppoe_plan']}{/if}
    -
    - {foreach $plans_pppoe as $plan} - {if $router['name'] eq $plan['routers']} -
    -
    -
    {$plan['name_plan']}
    -
    - - - - - - - - - - - - - - - -
    {Lang::T('Type')}{$plan['type']}
    {Lang::T('Price')}{Lang::moneyFormat($plan['price'])}
    {Lang::T('Validity')}{$plan['validity']} {$plan['validity_unit']}
    -
    -
    -
    - {Lang::T('Buy')} - {if $_c['enable_balance'] == 'yes' && $_user['balance']>=$plan['price']} - {Lang::T('Pay With Balance')} - {/if} -
    - {if $_c['enable_balance'] == 'yes' && $_c['allow_balance_transfer'] == 'yes' && $_user['balance']>=$plan['price']} - {Lang::T('Buy for friend')} - {/if} -
    -
    -
    - {/if} - {/foreach} -
    - {/if} -
    + {if Validator::isRouterHasPlan($plans_hotspot, $router['name']) || Validator::isRouterHasPlan($plans_pppoe, + $router['name'])} +
    +
    {$router['name']}
    + {if $router['description'] != ''} +
    + {$router['description']} +
    {/if} + {if $_user['service_type'] == 'Hotspot' && Validator::countRouterPlan($plans_hotspot, $router['name'])>0} +
    {if $_c['hotspot_plan']==''}Hotspot Plan{else}{$_c['hotspot_plan']}{/if} +
    +
    + {foreach $plans_hotspot as $plan} + {if $router['name'] eq $plan['routers']} +
    +
    +
    {$plan['name_plan']}
    +
    +
    + + + + + + + + + + + + + + + +
    {Lang::T('Type')}{$plan['type']}
    {Lang::T('Price')}{Lang::moneyFormat($plan['price'])}
    {Lang::T('Validity')}{$plan['validity']} {$plan['validity_unit']}
    +
    +
    +
    +
    + {Lang::T('Buy')} + {if $_c['enable_balance'] == 'yes' && $_user['balance']>=$plan['price']} + {Lang::T('Pay With Balance')} + {/if} +
    + {if $_c['enable_balance'] == 'yes' && $_c['allow_balance_transfer'] == 'yes' && + $_user['balance']>=$plan['price']} + {Lang::T('Buy for friend')} + {/if} +
    +
    +
    + {/if} + {/foreach} +
    + {/if} + {if $_user['service_type'] == 'PPPoE' && Validator::countRouterPlan($plans_pppoe,$router['name'])>0} +
    {if $_c['pppoe_plan']==''}PPPOE Plan{else}{$_c['pppoe_plan']}{/if}
    +
    + {foreach $plans_pppoe as $plan} + {if $router['name'] eq $plan['routers']} +
    +
    +
    {$plan['name_plan']}
    +
    +
    + + + + + + + + + + + + + + + +
    {Lang::T('Type')}{$plan['type']}
    {Lang::T('Price')}{Lang::moneyFormat($plan['price'])}
    {Lang::T('Validity')}{$plan['validity']} {$plan['validity_unit']}
    +
    +
    +
    +
    + {Lang::T('Buy')} + {if $_c['enable_balance'] == 'yes' && $_user['balance']>=$plan['price']} + {Lang::T('Pay With Balance')} + {/if} +
    + {if $_c['enable_balance'] == 'yes' && $_c['allow_balance_transfer'] == 'yes' && + $_user['balance']>=$plan['price']} + {Lang::T('Buy for friend')} + {/if} +
    +
    +
    + {/if} + {/foreach} +
    + {/if} + {if $_user['service_type'] == 'Others' || $_user['service_type'] == '' && + (Validator::countRouterPlan($plans_hotspot, $router['name'])>0 || Validator::countRouterPlan($plans_pppoe, + $router['name'])>0)} +
    {if $_c['hotspot_plan']==''}Hotspot Plan{else}{$_c['hotspot_plan']}{/if} +
    +
    + {foreach $plans_hotspot as $plan} + {if $router['name'] eq $plan['routers']} +
    +
    +
    {$plan['name_plan']}
    +
    +
    + + + + + + + + + + + + + + + +
    {Lang::T('Type')}{$plan['type']}
    {Lang::T('Price')}{Lang::moneyFormat($plan['price'])}
    {Lang::T('Validity')}{$plan['validity']} {$plan['validity_unit']}
    +
    +
    +
    +
    + {Lang::T('Buy')} + {if $_c['enable_balance'] == 'yes' && $_user['balance']>=$plan['price']} + {Lang::T('Pay With Balance')} + {/if} +
    + {if $_c['enable_balance'] == 'yes' && $_c['allow_balance_transfer'] == 'yes' && + $_user['balance']>=$plan['price']} + {Lang::T('Buy for friend')} + {/if} +
    +
    +
    + {/if} + {/foreach} +
    +
    {if $_c['pppoe_plan']==''}PPPOE Plan{else}{$_c['pppoe_plan']}{/if}
    +
    + {foreach $plans_pppoe as $plan} + {if $router['name'] eq $plan['routers']} +
    +
    +
    {$plan['name_plan']}
    +
    +
    + + + + + + + + + + + + + + + +
    {Lang::T('Type')}{$plan['type']}
    {Lang::T('Price')}{Lang::moneyFormat($plan['price'])}
    {Lang::T('Validity')}{$plan['validity']} {$plan['validity_unit']}
    +
    +
    +
    +
    + {Lang::T('Buy')} + {if $_c['enable_balance'] == 'yes' && $_user['balance']>=$plan['price']} + {Lang::T('Pay With Balance')} + {/if} +
    + {if $_c['enable_balance'] == 'yes' && $_c['allow_balance_transfer'] == 'yes' && + $_user['balance']>=$plan['price']} + {Lang::T('Buy for friend')} + {/if} +
    +
    +
    + {/if} + {/foreach} +
    + {/if} +
    + {/if} {/foreach}
    -{include file="user-ui/footer.tpl"} +{include file="user-ui/footer.tpl"} \ No newline at end of file From d060e210329bdb1f21581a3a21d2331d384f2cc7 Mon Sep 17 00:00:00 2001 From: Focuslinkstech <45756999+Focuslinkstech@users.noreply.github.com> Date: Thu, 5 Sep 2024 10:05:23 +0100 Subject: [PATCH 278/841] Added to Balance list --- ui/ui/user-ui/orderBalance.tpl | 50 ++++++++++++++++++---------------- 1 file changed, 26 insertions(+), 24 deletions(-) diff --git a/ui/ui/user-ui/orderBalance.tpl b/ui/ui/user-ui/orderBalance.tpl index ce5ecfe2..f18a7897 100644 --- a/ui/ui/user-ui/orderBalance.tpl +++ b/ui/ui/user-ui/orderBalance.tpl @@ -3,35 +3,37 @@
    {if $_c['enable_balance'] == 'yes'} -
    -
    {Lang::T('Buy Balance Plans')}
    -
    - {foreach $plans_balance as $plan} -
    -
    -
    {$plan['name_plan']}
    -
    - - - - - - - -
    {Lang::T('Price')}{Lang::moneyFormat($plan['price'])}
    -
    - +
    +
    {Lang::T('Buy Balance Plans')}
    +
    + {foreach $plans_balance as $plan} +
    +
    +
    {$plan['name_plan']}
    +
    +
    + + + + + + + +
    {Lang::T('Price')}{Lang::moneyFormat($plan['price'])}
    - {/foreach} + +
    + {/foreach}
    +
    {/if}
    -{include file="user-ui/footer.tpl"} +{include file="user-ui/footer.tpl"} \ No newline at end of file From af753d3a52478181473d8e81920a2562f06f174d Mon Sep 17 00:00:00 2001 From: Focuslinkstech <45756999+Focuslinkstech@users.noreply.github.com> Date: Thu, 5 Sep 2024 10:07:22 +0100 Subject: [PATCH 279/841] remove excess div --- ui/ui/user-ui/orderBalance.tpl | 1 - 1 file changed, 1 deletion(-) diff --git a/ui/ui/user-ui/orderBalance.tpl b/ui/ui/user-ui/orderBalance.tpl index f18a7897..e541751d 100644 --- a/ui/ui/user-ui/orderBalance.tpl +++ b/ui/ui/user-ui/orderBalance.tpl @@ -35,5 +35,4 @@ {/if}
    -
    {include file="user-ui/footer.tpl"} \ No newline at end of file From aa787af017e3aa9c223bf62918388593235794fe Mon Sep 17 00:00:00 2001 From: Focuslinkstech <45756999+Focuslinkstech@users.noreply.github.com> Date: Thu, 5 Sep 2024 10:36:28 +0100 Subject: [PATCH 280/841] fix bandwidth name not displayed on active packages on customer dashboard --- system/autoload/User.php | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/system/autoload/User.php b/system/autoload/User.php index e8e6e65f..9cf47823 100644 --- a/system/autoload/User.php +++ b/system/autoload/User.php @@ -210,14 +210,15 @@ class User ->select('tbl_user_recharges.id', 'id') ->selects([ 'customer_id', 'username', 'plan_id', 'namebp', 'recharged_on', 'recharged_time', 'expiration', 'time', - 'status', 'method', 'plan_type', 'name_bw', + 'status', 'method', 'plan_type', ['tbl_user_recharges.routers', 'routers'], ['tbl_user_recharges.type', 'type'], 'admin_id', 'prepaid' ]) + ->left_outer_join('tbl_plans', ['tbl_plans.id', '=', 'tbl_user_recharges.plan_id']) + ->left_outer_join('tbl_bandwidth', ['tbl_bandwidth.id', '=', 'tbl_plans.id_bw']) + ->select('tbl_bandwidth.*') ->where('customer_id', $id) - ->left_outer_join('tbl_plans', array('tbl_plans.id', '=', 'tbl_user_recharges.plan_id')) - ->left_outer_join('tbl_bandwidth', array('tbl_bandwidth.id', '=', 'tbl_plans.id_bw')) ->find_many(); return $d; } From 40f452cff8a7a8d19cb4e429a08231a83be2c943 Mon Sep 17 00:00:00 2001 From: Focuslinkstech <45756999+Focuslinkstech@users.noreply.github.com> Date: Thu, 5 Sep 2024 13:46:07 +0100 Subject: [PATCH 281/841] just little bold --- ui/ui/user-ui/header.tpl | 401 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 400 insertions(+), 1 deletion(-) diff --git a/ui/ui/user-ui/header.tpl b/ui/ui/user-ui/header.tpl index f57da6bc..e52c1b69 100644 --- a/ui/ui/user-ui/header.tpl +++ b/ui/ui/user-ui/header.tpl @@ -178,7 +178,7 @@ } .content .row [class*=col-] .box { - -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, .05); + -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, .05); box-shadow: 4px 4px 30px rgba(221, 224, 255, .54); -moz-box-shadow: 0 1px 1px rgba(0, 0, 0, .1); -ms-box-shadow: 0 1px 1px rgba(0, 0, 0, .1); @@ -215,16 +215,19 @@ background: transparent; background-color: transparent; } + .box.box-solid.box-primary>.box-header { color: inherit; background-color: transparent; border-color: transparent; } + .box.box-solid.box-info>.box-header { color: inherit; background-color: transparent; border-color: transparent; } + .box.box-solid.box-danger>.box-header { color: inherit; background-color: transparent; @@ -246,6 +249,21 @@ box-shadow: 0px 4px 30px rgba(221, 224, 255, .54); } + .modern-skin-dark .main-sidebar .sidebar .sidebar-menu li>a { + font-weight: bold; + } + + .content-header>h1 { + font-weight: bold; + } + + .box-header>.fa, + .box-header>.glyphicon, + .box-header>.ion, + .box-header .box-title { + font-weight: bold; + } + /* New Customize Interface End Here */ ::-moz-selection { @@ -306,6 +324,387 @@ margin: 0; padding: 10px; } + + + + + .toggle-container { + position: absolute; + top: 17px; + right: 15px; + cursor: pointer; + } + + .toggle-container .toggle-icon { + font-size: 25px; + color: rgb(100 116 139); + transition: color 0.5s ease; + } + + @media (max-width: 600px) { + .toggle-container { + top: 15px; + right: 200px; + } + + .toggle-container .toggle-icon { + font-size: 20px; + color: rgb(100 116 139); + transition: color 0.5s ease; + } + } + + + /* dark mode styles start here */ + .dark-mode { + background-color: #1a202c; + color: #cbd5e0; + } + + .dark-mode .main-header .logo, + .dark-mode .main-header .navbar, + .dark-mode .main-sidebar, + .dark-mode .main-sidebar .sidebar, + .dark-mode .sidebar-menu li>a { + background-color: #0e1219; + color: #cbd5e0; + } + + .dark-mode .sidebar-menu li:hover, + .dark-mode .sidebar-menu li:focus { + color: #10d435; + } + + .dark-mode .main-sidebar .sidebar .sidebar-menu li.active a { + background-color: #2e298e; + } + + .dark-mode .content, + .dark-mode .content-header, + .dark-mode .content-wrapper, + .dark-mode .right-side { + background-color: #0e1219; + } + + .dark-mode .main-footer { + background-color: #1a202c; + color: #cbd5e0; + } + + .dark-mode .panel, + .dark-mode .box { + background-color: #2d3748; + border-color: #4a5568; + box-shadow: none; + } + + .dark-mode .panel-heading, + .dark-mode .box-header { + background-color: transparent; + color: #cbd5e0; + } + + .dark-mode .box-footer, + .dark-mode .panel-footer { + background-color: #2d3748; + } + + .dark-mode .search-container { + background-color: #2d3748; + color: #cbd5e0; + } + + .dark-mode .searchTerm { + background-color: #4a5568; + color: #cbd5e0; + } + + .dark-mode .cancelButton { + background-color: #e53e3e; + } + + .dark-mode .notification-top-bar { + background-color: #742a2a; + } + + .dark-mode .bs-callout { + background-color: #2d3748; + border-color: #4a5568; + color: #cbd5e0; + } + + .dark-mode .bs-callout h4 { + color: #cbd5e0; + } + + .dark-mode .bg-gray { + background-color: inherit !important; + } + + .dark-mode .breadcrumb { + padding: 8px 15px; + margin-bottom: 20px; + list-style: none; + background-color: rgba(221, 224, 255, .54); + border-radius: 4px; + } + + .dark-mode .pagination>.disabled>span, + .dark-mode .pagination>.disabled>span:hover, + .dark-mode .pagination>.disabled>span:focus, + .dark-mode .pagination>.disabled>a, + .dark-mode .pagination>.disabled>a:hover, + .dark-mode .pagination>.disabled>a:focus { + color: inherit; + background-color: rgba(221, 224, 255, .54); + border-color: rgba(221, 224, 255, .54); + cursor: not-allowed; + } + + .dark-mode .pagination>.active>a, + .dark-mode .pagination>.active>a:hover, + .dark-mode .pagination>.active>a:focus, + .dark-mode .pagination>.active>span, + .dark-mode .pagination>.active>span:hover, + .dark-mode .pagination>.active>span:focus { + z-index: 2; + color: #fff; + background-color: #435ebe; + border-color: rgba(221, 224, 255, .54); + box-shadow: 0 2px 5px rgba(67, 94, 190, .3); + cursor: default; + } + + .dark-mode .pagination>li>a { + background: inherit; + color: inherit; + border: 1px solid; + border-color: rgba(221, 224, 255, .54); + } + + .dark-mode .table { + background-color: inherit; + color: #ddd; + border-color: #444; + } + + .dark-mode .table th, + .dark-mode .table td { + background-color: inherit; + border-color: inherit; + color: #ddd; + } + + .dark-mode .table th { + background-color: inherit; + font-weight: bold; + } + + .dark-mode .table-striped tbody tr:nth-of-type(odd) { + background-color: inherit; + } + + .dark-mode .table-bordered { + border: 1px solid #444; + } + + .dark-mode .table-hover tbody tr:hover { + background-color: #555; + color: #fff; + } + + .dark-mode .table-condensed th, + .dark-mode .table-condensed td { + padding: 8px; + } + + .dark-mode .panel>.table:last-child, + .dark-mode .panel>.table-responsive:last-child>.table:last-child { + border-bottom-right-radius: 21px; + border-bottom-left-radius: 21px; + } + + .dark-mode .panel>.table:last-child>tbody:last-child>tr:last-child, + .dark-mode .panel>.table:last-child>tfoot:last-child>tr:last-child, + .dark-mode .panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child, + .dark-mode .panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child { + border-bottom-right-radius: 21px; + border-bottom-left-radius: 21px; + } + + .dark-mode .panel>.table:last-child>tbody:last-child>tr:last-child td:last-child, + .dark-mode .panel>.table:last-child>tbody:last-child>tr:last-child th:last-child, + .dark-mode .panel>.table:last-child>tfoot:last-child>tr:last-child td:last-child, + .dark-mode .panel>.table:last-child>tfoot:last-child>tr:last-child th:last-child, + .dark-mode .panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:last-child, + .dark-mode .panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:last-child, + .dark-mode .panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:last-child, + .dark-mode .panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:last-child { + border-bottom-right-radius: 21px; + } + + .dark-mode .help-block { + display: block; + margin-top: 5px; + margin-bottom: 10px; + color: inherit; + } + + .dark-mode .text-muted { + color: rgba(221, 224, 255, .54); + } + + .dark-mode .form-control { + display: block; + width: 100%; + padding: 6px 12px; + font-size: 14px; + line-height: 1.428571429; + color: inherit; + background-color: transparent; + background-image: none; + border: 1px solid; + border-color: rgba(221, 224, 255, .54); + border-radius: 4px; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); + -webkit-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s; + -o-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s; + transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s; + } + + .dark-mode .main-footer { + border-top: 1px solid transparent; + } + + .dark-mode .box.box-solid.box-primary>.box-header { + color: #fff; + background-color: inherit; + border-color: rgba(221, 224, 255, .54); + border-top-left-radius: 45px; + border-top-right-radius: 45px; + } + + .dark-mode .box-body { + border-radius: 0px; + padding: 10px; + } + + .dark-mode .box-header { + display: block; + padding: 10px; + position: relative; + border-color: transparent; + border-radius: 0px; + } + + .dark-mode .nav-stacked>li>a { + color: inherit; + } + + .dark-mode .list-group-item { + position: relative; + display: block; + padding: 10px 15px; + margin-bottom: -1px; + background-color: transparent; + border: 1px solid rgba(221, 224, 255, .54); + } + + .dark-mode .panel-footer { + padding: 10px 15px; + border-top: 1px rgba(221, 224, 255, .54); + border-bottom-right-radius: 3px; + border-bottom-left-radius: 3px; + } + + + .dark-mode .content .row [class*=col-] .box { + -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, .05); + box-shadow: 4px 4px 30px rgba(221, 224, 255, .54); + -moz-box-shadow: 0 1px 1px rgba(0, 0, 0, .1); + -ms-box-shadow: 0 1px 1px rgba(0, 0, 0, .1); + -webkit-border-radius: 1px !important; + -moz-border-radius: 1px !important; + -ms-border-radius: 1px !important; + border-radius: 15px !important; + border-color: inherit; + background-color: inherit; + } + + /* Dark Mode - Input Fields */ + .dark-mode input:not(#filterNavigateMenu), + .dark-mode textarea:not(#filterNavigateMenu), + .dark-mode select:not(#filterNavigateMenu), + .dark-mode .select2-selection:not(#filterNavigateMenu) { + color: inherit; + transition: all .5s ease-in-out; + } + + .dark-mode input:focus:not(#filterNavigateMenu), + .dark-mode textarea:focus:not(#filterNavigateMenu), + .dark-mode select:focus:not(#filterNavigateMenu), + .dark-mode .select2-selection:focus:not(#filterNavigateMenu) { + color: #1f201f; + outline: none; + } + + .dark-mode .input-group .form-control { + position: relative; + z-index: 2; + float: left; + width: 100%; + margin-bottom: 0; + color: inherit; + border-color: rgba(221, 224, 255, .54); + background-color: inherit; + } + + .dark-mode .input-group .input-group-addon { + border-top-left-radius: 0; + border-top-right-radius: 0; + border-bottom-right-radius: 0; + color: inherit; + border-bottom-left-radius: 0; + border-color: rgba(221, 224, 255, .54); + background-color: transparent; + } + + .dark-mode .input-group .form-control:last-child, + .dark-mode .input-group-addon:last-child, + .dark-mode .input-group-btn:last-child>.btn, + .dark-mode .input-group-btn:last-child>.btn-group>.btn, + .dark-mode .input-group-btn:last-child>.dropdown-toggle, + .dark-mode .input-group-btn:first-child>.btn:not(:first-child), + .dark-mode .input-group-btn:first-child>.btn-group:not(:first-child)>.btn { + color: inherit; + } + + .dark-mode input:not(#filterNavigateMenu), + textarea:not(#filterNavigateMenu), + optgroup:not(#filterNavigateMenu), + select:not(#filterNavigateMenu), + .dark-mode .select2-selection:not(#filterNavigateMenu) { + -moz-transition: all .5s ease-in-out; + -o-transition: all .5s ease-in-out; + -webkit-transition: all .5s ease-in-out; + transition: all .5s ease-in-out; + } + + .dark-mode .modern-skin-dark .main-sidebar .sidebar .sidebar-menu li>a { + font-weight: bold; + } + + .dark-mode .content-header>h1 { + font-weight: bold; + } + + .dark-mode .box-header>.fa, + .dark-mode .box-header>.glyphicon, + .dark-mode .box-header>.ion, + .dark-mode .box-header .box-title { + font-weight: bold; + } {if isset($xheader)} From 93d53cc6d832e20201f23cddb374bf19f1f6d24d Mon Sep 17 00:00:00 2001 From: Focuslinkstech <45756999+Focuslinkstech@users.noreply.github.com> Date: Thu, 5 Sep 2024 13:59:19 +0100 Subject: [PATCH 282/841] We added bold to sidebar, we want your opinion if it looks good or we should remove it --- ui/ui/sections/header.tpl | 476 +++++++++++++++++++++++++++++++++++++- 1 file changed, 474 insertions(+), 2 deletions(-) diff --git a/ui/ui/sections/header.tpl b/ui/ui/sections/header.tpl index 26270036..843109d9 100644 --- a/ui/ui/sections/header.tpl +++ b/ui/ui/sections/header.tpl @@ -171,7 +171,7 @@ -webkit-border-radius: 1px !important; -moz-border-radius: 1px !important; -ms-border-radius: 1px !important; - border-radius: 25px !important; + border-radius: 15px !important; border-color: rgba(221, 224, 255, .54); } @@ -180,11 +180,13 @@ background-color: transparent; border-color: transparent; } + .box.box-solid.box-info>.box-header { color: inherit; background-color: transparent; border-color: transparent; } + .box.box-solid.box-danger>.box-header { color: inherit; background-color: transparent; @@ -211,6 +213,7 @@ border-top: 1px solid transparent; padding: 10px; background-color: inherit; + border-radius: 15px; } .panel-footer { @@ -232,6 +235,26 @@ box-shadow: 0px 4px 30px rgba(221, 224, 255, .54); } + .panel-success>.panel-heading { + color: #3c763d; + background-color: transparent; + border-color: #d6e9c6; + } + + .content-header>h1 { + font-weight: bold; + } + + .box-header>.fa, + .box-header>.glyphicon, + .box-header>.ion, + .box-header .box-title { + font-weight: bold; + } + + .modern-skin-dark .main-sidebar .sidebar .sidebar-menu li>a { + font-weight: bold; + } /* Search Bar Start Here */ .wrap { @@ -303,6 +326,13 @@ overflow-y: auto; } + .panel-heading { + padding: 10px 15px; + border-bottom: 0px solid transparent; + border-top-right-radius: 21px; + border-top-left-radius: 21px; + } + /* Search Bar End Here */ /* New Customize Interface End Here */ @@ -332,7 +362,6 @@ th:first-child, td:first-child { position: sticky; - left: 0px; background-color: #f9f9f9; } @@ -534,6 +563,449 @@ -ms-transform: translateX(26px); transform: translateX(26px); } + + /* dark mode styles start here */ + + .dark-mode { + background-color: #1a202c; + color: #cbd5e0; + } + + .dark-mode .main-header .logo, + .dark-mode .main-header .navbar, + .dark-mode .main-sidebar, + .dark-mode .main-sidebar .sidebar, + .dark-mode .sidebar-menu li>a { + background-color: #1a202c; + color: #cbd5e0; + } + + .dark-mode .sidebar-menu li:hover, + .dark-mode .sidebar-menu li:focus { + color: #10d435; + } + + .dark-mode .main-sidebar .sidebar .sidebar-menu li.active a { + background-color: #2e298e; + } + + .dark-mode .content, + .dark-mode .content-header, + .dark-mode .content-wrapper, + .dark-mode .right-side { + background-color: #2d3748; + } + + .dark-mode .main-footer { + background-color: #1a202c; + color: #cbd5e0; + } + + .dark-mode .panel, + .dark-mode .box { + background-color: #2d3748; + border-color: #4a5568; + box-shadow: none; + } + + .dark-mode .panel-heading, + .dark-mode .box-header { + background-color: transparent; + color: #cbd5e0; + } + + .dark-mode .box-footer, + .dark-mode .panel-footer { + background-color: #2d3748; + } + + .dark-mode .search-container { + background-color: #2d3748; + color: #cbd5e0; + } + + .dark-mode .searchTerm { + background-color: #4a5568; + color: #cbd5e0; + } + + .dark-mode .cancelButton { + background-color: #e53e3e; + } + + .dark-mode .notification-top-bar { + background-color: #742a2a; + } + + .dark-mode .bs-callout { + background-color: #2d3748; + border-color: #4a5568; + color: #cbd5e0; + } + + .dark-mode .bs-callout h4 { + color: #cbd5e0; + } + + .dark-mode .bg-gray { + background-color: inherit !important; + } + + .toggle-container { + position: absolute; + top: 17px; + right: 15px; + cursor: pointer; + } + + .toggle-container .toggle-icon { + font-size: 25px; + color: rgb(100 116 139); + transition: color 0.5s ease; + } + + @media (max-width: 600px) { + .toggle-container { + top: 15px; + right: 60px; + } + + .toggle-container .toggle-icon { + font-size: 20px; + color: rgb(100 116 139); + transition: color 0.5s ease; + } + } + + .dark-mode .toggle-container .toggle-icon { + color: #ffdd57; + } + + .dark-mode th:first-child, + .dark-mode td:first-child { + background-color: #4a4949; + } + + .dark-mode .panel>.table:last-child>tbody:last-child>tr:last-child td:first-child, + .dark-mode .panel>.table:last-child>tbody:last-child>tr:last-child th:first-child, + .dark-mode .panel>.table:last-child>tfoot:last-child>tr:last-child td:first-child, + .dark-mode .panel>.table:last-child>tfoot:last-child>tr:last-child th:first-child, + .dark-mode .panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:first-child, + .dark-mode .panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:first-child, + .dark-mode .panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:first-child, + .dark-mode .panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:first-child { + background-color: #4a4949; + border-bottom-left-radius: 21px; + } + + .dark-mode .table>thead>tr>td.danger, + .dark-mode .table>thead>tr>th.danger, + .dark-mode .table>thead>tr.danger>td, + .dark-mode .table>thead>tr.danger>th, + .dark-mode .table>tbody>tr>td.danger, + .dark-mode .table>tbody>tr>th.danger, + .dark-mode .table>tbody>tr.danger>td, + .dark-mode .table>tbody>tr.danger>th, + .dark-mode .table>tfoot>tr>td.danger, + .dark-mode .table>tfoot>tr>th.danger, + .dark-mode .table>tfoot>tr.danger>td, + .dark-mode .table>tfoot>tr.danger>th { + background-color: #694760; + } + + .dark-mode .panel-heading { + padding: 10px 15px; + border-bottom: 1px solid transparent; + border-top-right-radius: 21px; + border-top-left-radius: 21px; + } + + .dark-mode .table-bordered>thead>tr>th, + .dark-mode .table-bordered>thead>tr>td, + .dark-mode .table-bordered>tbody>tr>th, + .dark-mode .table-bordered>tbody>tr>td, + .dark-mode .table-bordered>tfoot>tr>th, + .dark-mode .table-bordered>tfoot>tr>td { + border: 1px solid; + border-color: rgba(221, 224, 255, .54); + } + + /* Dark Mode - Input Fields */ + .dark-mode input:not(#filterNavigateMenu), + .dark-mode textarea:not(#filterNavigateMenu), + .dark-mode select:not(#filterNavigateMenu), + .dark-mode .select2-selection:not(#filterNavigateMenu) { + color: inherit; + transition: all .5s ease-in-out; + } + + .dark-mode input:focus:not(#filterNavigateMenu), + .dark-mode textarea:focus:not(#filterNavigateMenu), + .dark-mode select:focus:not(#filterNavigateMenu), + .dark-mode .select2-selection:focus:not(#filterNavigateMenu) { + color: #1f201f; + outline: none; + } + + .dark-mode .nav-stacked>li>a { + color: inherit; + } + + .dark-mode .input-group .form-control { + position: relative; + z-index: 2; + float: left; + width: 100%; + margin-bottom: 0; + color: inherit; + border-color: rgba(221, 224, 255, .54); + background-color: inherit; + } + + .dark-mode .input-group .input-group-addon { + border-top-left-radius: 0; + border-top-right-radius: 0; + border-bottom-right-radius: 0; + color: inherit; + border-bottom-left-radius: 0; + border-color: rgba(221, 224, 255, .54); + background-color: transparent; + } + + .dark-mode .input-group .form-control:last-child, + .dark-mode .input-group-addon:last-child, + .dark-mode .input-group-btn:last-child>.btn, + .dark-mode .input-group-btn:last-child>.btn-group>.btn, + .dark-mode .input-group-btn:last-child>.dropdown-toggle, + .dark-mode .input-group-btn:first-child>.btn:not(:first-child), + .dark-mode .input-group-btn:first-child>.btn-group:not(:first-child)>.btn { + color: inherit; + } + + .dark-mode input:not(#filterNavigateMenu), + textarea:not(#filterNavigateMenu), + optgroup:not(#filterNavigateMenu), + select:not(#filterNavigateMenu), + .dark-mode .select2-selection:not(#filterNavigateMenu) { + -moz-transition: all .5s ease-in-out; + -o-transition: all .5s ease-in-out; + -webkit-transition: all .5s ease-in-out; + transition: all .5s ease-in-out; + } + + .dark-mode .form-control { + display: block; + width: 100%; + padding: 6px 12px; + font-size: 14px; + line-height: 1.428571429; + color: inherit; + background-color: transparent; + background-image: none; + border: 1px solid; + border-color: rgba(221, 224, 255, .54); + border-radius: 4px; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); + -webkit-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s; + -o-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s; + transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s; + } + + .dark-mode .help-block { + display: block; + margin-top: 5px; + margin-bottom: 10px; + color: inherit; + } + + .dark-mode .text-muted { + color: rgba(221, 224, 255, .54); + } + + .dark-mode .breadcrumb { + padding: 8px 15px; + margin-bottom: 20px; + list-style: none; + background-color: rgba(221, 224, 255, .54); + border-radius: 4px; + } + + .dark-mode .pagination>.disabled>span, + .dark-mode .pagination>.disabled>span:hover, + .dark-mode .pagination>.disabled>span:focus, + .dark-mode .pagination>.disabled>a, + .dark-mode .pagination>.disabled>a:hover, + .dark-mode .pagination>.disabled>a:focus { + color: inherit; + background-color: rgba(221, 224, 255, .54); + border-color: rgba(221, 224, 255, .54); + cursor: not-allowed; + } + + .dark-mode .pagination>.active>a, + .dark-mode .pagination>.active>a:hover, + .dark-mode .pagination>.active>a:focus, + .dark-mode .pagination>.active>span, + .dark-mode .pagination>.active>span:hover, + .dark-mode .pagination>.active>span:focus { + z-index: 2; + color: #fff; + background-color: #435ebe; + border-color: rgba(221, 224, 255, .54); + box-shadow: 0 2px 5px rgba(67, 94, 190, .3); + cursor: default; + } + + .dark-mode .pagination>li>a { + background: inherit; + color: inherit; + border: 1px solid; + border-color: rgba(221, 224, 255, .54); + } + + .dark-mode .table { + background-color: #2a2a2a; + color: #ddd; + border-color: #444; + } + + .dark-mode .table th, + .dark-mode .table td { + background-color: #333; + border-color: #444; + color: #ddd; + } + + .dark-mode .table th { + background-color: #444; + font-weight: bold; + } + + .dark-mode .table-striped tbody tr:nth-of-type(odd) { + background-color: #3a3a3a; + } + + .dark-mode .table-bordered { + border: 1px solid #444; + } + + .dark-mode .table-hover tbody tr:hover { + background-color: #555; + color: #fff; + } + + .dark-mode .table-condensed th, + .dark-mode .table-condensed td { + padding: 8px; + } + + .dark-mode .panel>.table:last-child, + .dark-mode .panel>.table-responsive:last-child>.table:last-child { + border-bottom-right-radius: 21px; + border-bottom-left-radius: 21px; + } + + .dark-mode .panel>.table:last-child>tbody:last-child>tr:last-child, + .dark-mode .panel>.table:last-child>tfoot:last-child>tr:last-child, + .dark-mode .panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child, + .dark-mode .panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child { + border-bottom-right-radius: 21px; + border-bottom-left-radius: 21px; + } + + .dark-mode .panel>.table:last-child>tbody:last-child>tr:last-child td:last-child, + .dark-mode .panel>.table:last-child>tbody:last-child>tr:last-child th:last-child, + .dark-mode .panel>.table:last-child>tfoot:last-child>tr:last-child td:last-child, + .dark-mode .panel>.table:last-child>tfoot:last-child>tr:last-child th:last-child, + .dark-mode .panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:last-child, + .dark-mode .panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:last-child, + .dark-mode .panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:last-child, + .dark-mode .panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:last-child { + border-bottom-right-radius: 21px; + } + + /* Dark Mode - Select2 Dropdown start here */ + .dark-mode .select2-container--bootstrap .select2-results__option--highlighted[aria-selected] { + background-color: rgb(96, 89, 89); + color: #ffffff; + } + + .dark-mode .select2-container--bootstrap .select2-results__option { + padding: 6px 12px; + background-color: rgb(96, 89, 89); + color: #f8f9fa; + } + + .dark-mode .select2-results__option[aria-selected] { + cursor: pointer; + background-color: inherit; + color: #ffffff; + } + + .dark-mode .select2-results__option { + padding: 6px 12px; + user-select: none; + -webkit-user-select: none; + background-color: #343a40; + color: #f8f9fa; + } + + .dark-mode .select2-dropdown { + background-color: #343a40; + border-color: #454d55; + } + + .dark-mode .select2-selection--single { + background-color: #495057; + color: #ffffff; + border-color: #454d55; + } + + .dark-mode .select2-selection__rendered { + color: #ffffff; + } + + .dark-mode .select2-selection__arrow b { + border-color: #ffffff transparent transparent transparent; + } + + .dark-mode .select2-container--bootstrap .select2-selection--single .select2-selection__rendered { + color: inherit; + padding: 0; + } + + .dark-mode .main-footer { + border-top: 1px solid transparent; + } + + .dark-mode .list-group-item { + position: relative; + display: block; + padding: 10px 15px; + margin-bottom: -1px; + background-color: transparent; + border: 1px solid rgba(221, 224, 255, .54); + } + + .dark-mode .modern-skin-dark .main-sidebar .sidebar .sidebar-menu li>a { + font-weight: bold; + } + + .dark-mode .content-header>h1 { + font-weight: bold; + } + + .dark-mode .box-header>.fa, + .dark-mode .box-header>.glyphicon, + .dark-mode .box-header>.ion, + .dark-mode .box-header .box-title { + font-weight: bold; + } + + /* Dark Mode - Select2 Dropdown ends here */ + + /* dark mode styles start ends here */ {if isset($xheader)} {$xheader} From 4f74aa0bff1908eac7303e73bd9314724a76b08c Mon Sep 17 00:00:00 2001 From: Focuslinkstech <45756999+Focuslinkstech@users.noreply.github.com> Date: Thu, 5 Sep 2024 14:14:50 +0100 Subject: [PATCH 283/841] Please if you dont like the bold feature kindly report it --- ui/ui/sections/header.tpl | 12 ++++++++++++ ui/ui/user-ui/header.tpl | 12 ++++++++++++ 2 files changed, 24 insertions(+) diff --git a/ui/ui/sections/header.tpl b/ui/ui/sections/header.tpl index 843109d9..d056aabc 100644 --- a/ui/ui/sections/header.tpl +++ b/ui/ui/sections/header.tpl @@ -256,6 +256,10 @@ font-weight: bold; } + .main-header .logo .logo-lg { + font-weight: bold; + } + /* Search Bar Start Here */ .wrap { width: 30%; @@ -1003,6 +1007,14 @@ font-weight: bold; } + .dark-mode .content-header>h2 { + font-weight: bold; + } + + .dark-mode .main-header .logo .logo-lg { + font-weight: bold; + } + /* Dark Mode - Select2 Dropdown ends here */ /* dark mode styles start ends here */ diff --git a/ui/ui/user-ui/header.tpl b/ui/ui/user-ui/header.tpl index e52c1b69..09841709 100644 --- a/ui/ui/user-ui/header.tpl +++ b/ui/ui/user-ui/header.tpl @@ -264,6 +264,10 @@ font-weight: bold; } + .main-header .logo .logo-lg { + font-weight: bold; + } + /* New Customize Interface End Here */ ::-moz-selection { @@ -705,6 +709,14 @@ .dark-mode .box-header .box-title { font-weight: bold; } + + .dark-mode .content-header>h2 { + font-weight: bold; + } + + .dark-mode .main-header .logo .logo-lg { + font-weight: bold; + } {if isset($xheader)} From c255a7be4972fcd47a30cee9593093bdf90dfd61 Mon Sep 17 00:00:00 2001 From: Focuslinkstech <45756999+Focuslinkstech@users.noreply.github.com> Date: Thu, 5 Sep 2024 15:47:28 +0100 Subject: [PATCH 284/841] fix modal in dark mode --- ui/ui/sections/header.tpl | 19 +++++++++++++++++++ ui/ui/user-ui/header.tpl | 20 ++++++++++++++++++++ 2 files changed, 39 insertions(+) diff --git a/ui/ui/sections/header.tpl b/ui/ui/sections/header.tpl index d056aabc..0ea33f58 100644 --- a/ui/ui/sections/header.tpl +++ b/ui/ui/sections/header.tpl @@ -1015,6 +1015,25 @@ font-weight: bold; } + .dark-mode .modal-content { + border-top-left-radius: 0; + border-top-right-radius: 0; + border-bottom-right-radius: 15px; + border-bottom-left-radius: 15px; + -webkit-box-shadow: 0 2px 3px rgba(0, 0, 0, .125); + box-shadow: 0 2px 3px rgba(0, 0, 0, .125); + border: 0; + background: #1a202c; + } + + .dark-mode .modal-header { + padding: 15px; + border-bottom: 1px solid rgba(221, 224, 255, .54); + min-height: 16.428571429px; + background-color: #1a202c; + color: inherit; + } + /* Dark Mode - Select2 Dropdown ends here */ /* dark mode styles start ends here */ diff --git a/ui/ui/user-ui/header.tpl b/ui/ui/user-ui/header.tpl index 09841709..f88820aa 100644 --- a/ui/ui/user-ui/header.tpl +++ b/ui/ui/user-ui/header.tpl @@ -717,6 +717,26 @@ .dark-mode .main-header .logo .logo-lg { font-weight: bold; } + + + .dark-mode .modal-content { + border-top-left-radius: 0; + border-top-right-radius: 0; + border-bottom-right-radius: 15px; + border-bottom-left-radius: 15px; + -webkit-box-shadow: 0 2px 3px rgba(0, 0, 0, .125); + box-shadow: 0 2px 3px rgba(0, 0, 0, .125); + border: 0; + background: #1a202c; + } + + .dark-mode .modal-header { + padding: 15px; + border-bottom: 1px solid rgba(221, 224, 255, .54); + min-height: 16.428571429px; + background-color: #1a202c; + color: inherit; + } {if isset($xheader)} From 299fd90949450257a8632a868f6c939f658963a0 Mon Sep 17 00:00:00 2001 From: Focuslinkstech <45756999+Focuslinkstech@users.noreply.github.com> Date: Thu, 5 Sep 2024 16:13:14 +0100 Subject: [PATCH 285/841] fix dark mode drop-down menu --- ui/ui/sections/header.tpl | 11 +++++++++++ ui/ui/user-ui/header.tpl | 22 ++++++++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/ui/ui/sections/header.tpl b/ui/ui/sections/header.tpl index 0ea33f58..2588a37f 100644 --- a/ui/ui/sections/header.tpl +++ b/ui/ui/sections/header.tpl @@ -1034,6 +1034,17 @@ color: inherit; } + .dark-mode .navbar-nav>.notifications-menu>.dropdown-menu>li.footer>a, + .dark-mode .navbar-nav>.messages-menu>.dropdown-menu>li.footer>a, + .dark-mode .navbar-nav>.tasks-menu>.dropdown-menu>li.footer>a { + background: #1a202c !important; + color: inherit !important; + } + + .dark-mode .navbar-nav>.user-menu>.dropdown-menu>.user-footer { + background-color: #1a202c; + } + /* Dark Mode - Select2 Dropdown ends here */ /* dark mode styles start ends here */ diff --git a/ui/ui/user-ui/header.tpl b/ui/ui/user-ui/header.tpl index f88820aa..37b9e1ee 100644 --- a/ui/ui/user-ui/header.tpl +++ b/ui/ui/user-ui/header.tpl @@ -737,6 +737,28 @@ background-color: #1a202c; color: inherit; } + + + .dark-mode .navbar-nav>.notifications-menu>.dropdown-menu>li .menu>li>a, + .dark-mode .navbar-nav>.messages-menu>.dropdown-menu>li .menu>li>a, + .dark-mode .navbar-nav>.tasks-menu>.dropdown-menu>li .menu>li>a { + display: block; + white-space: nowrap; + border-bottom: 1px solid rgba(221, 224, 255, .54); + background: #1a202c; + color: inherit; + } + + .dark-mode .navbar-nav>.notifications-menu>.dropdown-menu>li.footer>a, + .dark-mode .navbar-nav>.messages-menu>.dropdown-menu>li.footer>a, + .dark-mode .navbar-nav>.tasks-menu>.dropdown-menu>li.footer>a { + background: #1a202c !important; + color: inherit !important; + } + + .dark-mode .navbar-nav>.user-menu>.dropdown-menu>.user-footer { + background-color: #1a202c; + } {if isset($xheader)} From ea0c663278877af2ba1df20e4be9c77257aca1f0 Mon Sep 17 00:00:00 2001 From: Ibnu Maksum Date: Fri, 6 Sep 2024 10:59:26 +0700 Subject: [PATCH 286/841] MikrotikPppoeCustom for PPPOE Custom Username, IP and Password --- .gitignore | 1 + system/devices/MikrotikPppoe.php | 56 +--- system/devices/MikrotikPppoeCustom.php | 407 +++++++++++++++++++++++++ 3 files changed, 414 insertions(+), 50 deletions(-) create mode 100644 system/devices/MikrotikPppoeCustom.php diff --git a/.gitignore b/.gitignore index 99dbdb61..6e2cc32c 100644 --- a/.gitignore +++ b/.gitignore @@ -47,6 +47,7 @@ system/devices/** !system/devices/RadiusRest.php !system/devices/MikrotikPppoe.php !system/devices/MikrotikHotspot.php +!system/devices/MikrotikPppoeCustom.php /.vs docker-compose.yml docs/** diff --git a/system/devices/MikrotikPppoe.php b/system/devices/MikrotikPppoe.php index 4cbff181..6f291c48 100644 --- a/system/devices/MikrotikPppoe.php +++ b/system/devices/MikrotikPppoe.php @@ -39,30 +39,14 @@ class MikrotikPppoe }else{ $setRequest = new RouterOS\Request('/ppp/secret/set'); $setRequest->setArgument('numbers', $cid); - if (!empty($customer['pppoe_password'])) { - $setRequest->setArgument('password', $customer['pppoe_password']); - } else { - $setRequest->setArgument('password', $customer['password']); - } - if (!empty($customer['pppoe_username'])) { - $setRequest->setArgument('name', $customer['pppoe_username']); - } else { - $setRequest->setArgument('name', $customer['username']); - } - if (!empty($customer['pppoe_ip'])) { - $setRequest->setArgument('local-address', $customer['pppoe_ip']); - }else{ - $setRequest->setArgument('local-address', '0.0.0.0'); - } + $setRequest->setArgument('password', $customer['password']); + $setRequest->setArgument('name', $customer['username']); $setRequest->setArgument('profile', $plan['name_plan']); $setRequest->setArgument('comment', $customer['fullname'] . ' | ' . $customer['email'] . ' | ' . implode(', ', User::getBillNames($customer['id']))); $client->sendSync($setRequest); //disconnect then if(isset($isChangePlan) && $isChangePlan){ $this->removePpoeActive($client, $customer['username']); - if (!empty($customer['pppoe_username'])) { - $this->removePpoeActive($client, $customer['pppoe_username']); - } } } } @@ -76,20 +60,11 @@ class MikrotikPppoe if($p){ $this->add_customer($customer, $p); $this->removePpoeActive($client, $customer['username']); - if (!empty($customer['pppoe_username'])) { - $this->removePpoeActive($client, $customer['pppoe_username']); - } return; } } - $this->removePpoeUser($client, $customer['username']); - if (!empty($customer['pppoe_username'])) { - $this->removePpoeUser($client, $customer['pppoe_username']); - } $this->removePpoeActive($client, $customer['username']); - if (!empty($customer['pppoe_username'])) { - $this->removePpoeActive($client, $customer['pppoe_username']); - } + $this->removePpoeUser($client, $customer['username']); } // customer change username @@ -150,15 +125,7 @@ class MikrotikPppoe function getIdByCustomer($customer, $client){ $printRequest = new RouterOS\Request('/ppp/secret/print'); $printRequest->setQuery(RouterOS\Query::where('name', $customer['username'])); - $id = $client->sendSync($printRequest)->getProperty('.id'); - if(empty($id)){ - if (!empty($customer['pppoe_username'])) { - $printRequest = new RouterOS\Request('/ppp/secret/print'); - $printRequest->setQuery(RouterOS\Query::where('name', $customer['pppoe_username'])); - $id = $client->sendSync($printRequest)->getProperty('.id'); - } - } - return $id; + return $client->sendSync($printRequest)->getProperty('.id'); } function update_plan($old_name, $new_plan) @@ -327,19 +294,8 @@ class MikrotikPppoe $setRequest->setArgument('service', 'pppoe'); $setRequest->setArgument('profile', $plan['name_plan']); $setRequest->setArgument('comment', $customer['fullname'] . ' | ' . $customer['email'] . ' | ' . implode(', ', User::getBillNames($customer['id']))); - if (!empty($customer['pppoe_password'])) { - $setRequest->setArgument('password', $customer['pppoe_password']); - } else { - $setRequest->setArgument('password', $customer['password']); - } - if (!empty($customer['pppoe_username'])) { - $setRequest->setArgument('name', $customer['pppoe_username']); - } else { - $setRequest->setArgument('name', $customer['username']); - } - if (!empty($customer['pppoe_ip'])) { - $setRequest->setArgument('local-address', $customer['pppoe_ip']); - } + $setRequest->setArgument('password', $customer['password']); + $setRequest->setArgument('name', $customer['username']); $client->sendSync($setRequest); } diff --git a/system/devices/MikrotikPppoeCustom.php b/system/devices/MikrotikPppoeCustom.php new file mode 100644 index 00000000..83406144 --- /dev/null +++ b/system/devices/MikrotikPppoeCustom.php @@ -0,0 +1,407 @@ + 'Mikrotik PPPOE Custom', + 'description' => 'To handle connection between PHPNuxBill with Mikrotik PPPOE using Custom Username, IP and Password', + 'author' => 'ibnux', + 'url' => [ + 'Github' => 'https://github.com/hotspotbilling/phpnuxbill/', + 'Telegram' => 'https://t.me/phpnuxbill', + 'Donate' => 'https://paypal.me/ibnux' + ] + ]; + } + + function add_customer($customer, $plan) + { + global $isChangePlan; + $mikrotik = $this->info($plan['routers']); + $client = $this->getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']); + $cid = self::getIdByCustomer($customer, $client); + if (empty($cid)) { + //customer not exists, add it + $this->addPpoeUser($client, $plan, $customer); + }else{ + $setRequest = new RouterOS\Request('/ppp/secret/set'); + $setRequest->setArgument('numbers', $cid); + if (!empty($customer['pppoe_password'])) { + $setRequest->setArgument('password', $customer['pppoe_password']); + } else { + $setRequest->setArgument('password', $customer['password']); + } + if (!empty($customer['pppoe_username'])) { + $setRequest->setArgument('name', $customer['pppoe_username']); + } else { + $setRequest->setArgument('name', $customer['username']); + } + if (!empty($customer['pppoe_ip'])) { + $setRequest->setArgument('local-address', $customer['pppoe_ip']); + }else{ + $setRequest->setArgument('local-address', '0.0.0.0'); + } + $setRequest->setArgument('profile', $plan['name_plan']); + $setRequest->setArgument('comment', $customer['fullname'] . ' | ' . $customer['email'] . ' | ' . implode(', ', User::getBillNames($customer['id']))); + $client->sendSync($setRequest); + //disconnect then + if(isset($isChangePlan) && $isChangePlan){ + $this->removePpoeActive($client, $customer['username']); + if (!empty($customer['pppoe_username'])) { + $this->removePpoeActive($client, $customer['pppoe_username']); + } + } + } + } + + function remove_customer($customer, $plan) + { + $mikrotik = $this->info($plan['routers']); + $client = $this->getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']); + if (!empty($plan['plan_expired'])) { + $p = ORM::for_table("tbl_plans")->find_one($plan['plan_expired']); + if($p){ + $this->add_customer($customer, $p); + $this->removePpoeActive($client, $customer['username']); + if (!empty($customer['pppoe_username'])) { + $this->removePpoeActive($client, $customer['pppoe_username']); + } + return; + } + } + $this->removePpoeUser($client, $customer['username']); + if (!empty($customer['pppoe_username'])) { + $this->removePpoeUser($client, $customer['pppoe_username']); + } + $this->removePpoeActive($client, $customer['username']); + if (!empty($customer['pppoe_username'])) { + $this->removePpoeActive($client, $customer['pppoe_username']); + } + } + + // customer change username + public function change_username($plan, $from, $to) + { + $mikrotik = $this->info($plan['routers']); + $client = $this->getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']); + //check if customer exists + $printRequest = new RouterOS\Request('/ppp/secret/print'); + $printRequest->setQuery(RouterOS\Query::where('name', $from)); + $cid = $client->sendSync($printRequest)->getProperty('.id'); + if (!empty($cid)) { + $setRequest = new RouterOS\Request('/ppp/secret/set'); + $setRequest->setArgument('numbers', $cid); + $setRequest->setArgument('name', $to); + $client->sendSync($setRequest); + //disconnect then + $this->removePpoeActive($client, $from); + } + } + + function add_plan($plan) + { + $mikrotik = $this->info($plan['routers']); + $client = $this->getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']); + + //Add Pool + + $bw = ORM::for_table("tbl_bandwidth")->find_one($plan['id_bw']); + if ($bw['rate_down_unit'] == 'Kbps') { + $unitdown = 'K'; + } else { + $unitdown = 'M'; + } + if ($bw['rate_up_unit'] == 'Kbps') { + $unitup = 'K'; + } else { + $unitup = 'M'; + } + $rate = $bw['rate_up'] . $unitup . "/" . $bw['rate_down'] . $unitdown; + if(!empty(trim($bw['burst']))){ + $rate .= ' '.$bw['burst']; + } + $pool = ORM::for_table("tbl_pool")->where("pool_name", $plan['pool'])->find_one(); + $addRequest = new RouterOS\Request('/ppp/profile/add'); + $client->sendSync( + $addRequest + ->setArgument('name', $plan['name_plan']) + ->setArgument('local-address', (!empty($pool['local_ip'])) ? $pool['local_ip']: $pool['pool_name']) + ->setArgument('remote-address', $pool['pool_name']) + ->setArgument('rate-limit', $rate) + ); + } + + /** + * Function to ID by username from Mikrotik + */ + function getIdByCustomer($customer, $client){ + $printRequest = new RouterOS\Request('/ppp/secret/print'); + $printRequest->setQuery(RouterOS\Query::where('name', $customer['username'])); + $id = $client->sendSync($printRequest)->getProperty('.id'); + if(empty($id)){ + if (!empty($customer['pppoe_username'])) { + $printRequest = new RouterOS\Request('/ppp/secret/print'); + $printRequest->setQuery(RouterOS\Query::where('name', $customer['pppoe_username'])); + $id = $client->sendSync($printRequest)->getProperty('.id'); + } + } + return $id; + } + + function update_plan($old_name, $new_plan) + { + $mikrotik = $this->info($new_plan['routers']); + $client = $this->getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']); + + $printRequest = new RouterOS\Request( + '/ppp profile print .proplist=.id', + RouterOS\Query::where('name', $old_name['name_plan']) + ); + $profileID = $client->sendSync($printRequest)->getProperty('.id'); + if (empty($profileID)) { + $this->add_plan($new_plan); + } else { + $bw = ORM::for_table("tbl_bandwidth")->find_one($new_plan['id_bw']); + if ($bw['rate_down_unit'] == 'Kbps') { + $unitdown = 'K'; + } else { + $unitdown = 'M'; + } + if ($bw['rate_up_unit'] == 'Kbps') { + $unitup = 'K'; + } else { + $unitup = 'M'; + } + $rate = $bw['rate_up'] . $unitup . "/" . $bw['rate_down'] . $unitdown; + if(!empty(trim($bw['burst']))){ + $rate .= ' '.$bw['burst']; + } + $pool = ORM::for_table("tbl_pool")->where("pool_name", $new_plan['pool'])->find_one(); + $setRequest = new RouterOS\Request('/ppp/profile/set'); + $client->sendSync( + $setRequest + ->setArgument('numbers', $profileID) + ->setArgument('local-address', (!empty($pool['local_ip'])) ? $pool['local_ip']: $pool['pool_name']) + ->setArgument('remote-address', $pool['pool_name']) + ->setArgument('rate-limit', $rate) + ->setArgument('on-up', $new_plan['on_login']) + ->setArgument('on-down', $new_plan['on_logout']) + ); + } + } + + function remove_plan($plan) + { + $mikrotik = $this->info($plan['routers']); + $client = $this->getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']); + $printRequest = new RouterOS\Request( + '/ppp profile print .proplist=.id', + RouterOS\Query::where('name', $plan['name_plan']) + ); + $profileID = $client->sendSync($printRequest)->getProperty('.id'); + + $removeRequest = new RouterOS\Request('/ppp/profile/remove'); + $client->sendSync( + $removeRequest + ->setArgument('numbers', $profileID) + ); + } + + function add_pool($pool){ + global $_app_stage; + if ($_app_stage == 'demo') { + return null; + } + $mikrotik = $this->info($pool['routers']); + $client = $this->getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']); + $addRequest = new RouterOS\Request('/ip/pool/add'); + $client->sendSync( + $addRequest + ->setArgument('name', $pool['pool_name']) + ->setArgument('ranges', $pool['range_ip']) + ); + } + + function update_pool($old_pool, $new_pool){ + global $_app_stage; + if ($_app_stage == 'demo') { + return null; + } + $mikrotik = $this->info($new_pool['routers']); + $client = $this->getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']); + $printRequest = new RouterOS\Request( + '/ip pool print .proplist=.id', + RouterOS\Query::where('name', $old_pool['pool_name']) + ); + $poolID = $client->sendSync($printRequest)->getProperty('.id'); + if (empty($poolID)) { + $this->add_pool($new_pool); + } else { + $setRequest = new RouterOS\Request('/ip/pool/set'); + $client->sendSync( + $setRequest + ->setArgument('numbers', $poolID) + ->setArgument('name', $new_pool['pool_name']) + ->setArgument('ranges', $new_pool['range_ip']) + ); + } + } + + function remove_pool($pool){ + global $_app_stage; + if ($_app_stage == 'demo') { + return null; + } + $mikrotik = $this->info($pool['routers']); + $client = $this->getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']); + $printRequest = new RouterOS\Request( + '/ip pool print .proplist=.id', + RouterOS\Query::where('name', $pool['pool_name']) + ); + $poolID = $client->sendSync($printRequest)->getProperty('.id'); + $removeRequest = new RouterOS\Request('/ip/pool/remove'); + $client->sendSync( + $removeRequest + ->setArgument('numbers', $poolID) + ); + } + + + function online_customer($customer, $router_name) + { + $mikrotik = $this->info($router_name); + $client = $this->getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']); + $printRequest = new RouterOS\Request( + '/ppp active print', + RouterOS\Query::where('user', $customer['username']) + ); + return $client->sendSync($printRequest)->getProperty('.id'); + } + + function info($name) + { + return ORM::for_table('tbl_routers')->where('name', $name)->find_one(); + } + + function getClient($ip, $user, $pass) + { + global $_app_stage; + if ($_app_stage == 'demo') { + return null; + } + $iport = explode(":", $ip); + return new RouterOS\Client($iport[0], $user, $pass, ($iport[1]) ? $iport[1] : null); + } + + function removePpoeUser($client, $username) + { + global $_app_stage; + if ($_app_stage == 'demo') { + return null; + } + $printRequest = new RouterOS\Request('/ppp/secret/print'); + //$printRequest->setArgument('.proplist', '.id'); + $printRequest->setQuery(RouterOS\Query::where('name', $username)); + $id = $client->sendSync($printRequest)->getProperty('.id'); + $removeRequest = new RouterOS\Request('/ppp/secret/remove'); + $removeRequest->setArgument('numbers', $id); + $client->sendSync($removeRequest); + } + + function addPpoeUser($client, $plan, $customer) + { + $setRequest = new RouterOS\Request('/ppp/secret/add'); + $setRequest->setArgument('service', 'pppoe'); + $setRequest->setArgument('profile', $plan['name_plan']); + $setRequest->setArgument('comment', $customer['fullname'] . ' | ' . $customer['email'] . ' | ' . implode(', ', User::getBillNames($customer['id']))); + if (!empty($customer['pppoe_password'])) { + $setRequest->setArgument('password', $customer['pppoe_password']); + } else { + $setRequest->setArgument('password', $customer['password']); + } + if (!empty($customer['pppoe_username'])) { + $setRequest->setArgument('name', $customer['pppoe_username']); + } else { + $setRequest->setArgument('name', $customer['username']); + } + if (!empty($customer['pppoe_ip'])) { + $setRequest->setArgument('local-address', $customer['pppoe_ip']); + } + $client->sendSync($setRequest); + } + + function removePpoeActive($client, $username) + { + global $_app_stage; + if ($_app_stage == 'demo') { + return null; + } + $onlineRequest = new RouterOS\Request('/ppp/active/print'); + $onlineRequest->setArgument('.proplist', '.id'); + $onlineRequest->setQuery(RouterOS\Query::where('name', $username)); + $id = $client->sendSync($onlineRequest)->getProperty('.id'); + + $removeRequest = new RouterOS\Request('/ppp/active/remove'); + $removeRequest->setArgument('numbers', $id); + $client->sendSync($removeRequest); + } + + 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'); + } + + function addIpToAddressList($client, $ip, $listName, $comment = '') + { + global $_app_stage; + if ($_app_stage == 'demo') { + return null; + } + $addRequest = new RouterOS\Request('/ip/firewall/address-list/add'); + $client->sendSync( + $addRequest + ->setArgument('address', $ip) + ->setArgument('comment', $comment) + ->setArgument('list', $listName) + ); + } + + function removeIpFromAddressList($client, $ip) + { + global $_app_stage; + if ($_app_stage == 'demo') { + return null; + } + $printRequest = new RouterOS\Request( + '/ip firewall address-list print .proplist=.id', + RouterOS\Query::where('address', $ip) + ); + $id = $client->sendSync($printRequest)->getProperty('.id'); + $removeRequest = new RouterOS\Request('/ip/firewall/address-list/remove'); + $client->sendSync( + $removeRequest + ->setArgument('numbers', $id) + ); + } +} From b517ef2b73cfa8b8797d43dbab6849e2ecfc28a7 Mon Sep 17 00:00:00 2001 From: Ibnu Maksum Date: Fri, 6 Sep 2024 11:00:09 +0700 Subject: [PATCH 287/841] fix ignore list --- .gitignore | 2 +- version.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index 6e2cc32c..2b53984b 100644 --- a/.gitignore +++ b/.gitignore @@ -46,8 +46,8 @@ system/devices/** !system/devices/Radius.php !system/devices/RadiusRest.php !system/devices/MikrotikPppoe.php -!system/devices/MikrotikHotspot.php !system/devices/MikrotikPppoeCustom.php +!system/devices/MikrotikHotspot.php /.vs docker-compose.yml docs/** diff --git a/version.json b/version.json index ddfab6f6..1bd146b2 100644 --- a/version.json +++ b/version.json @@ -1,3 +1,3 @@ { - "version": "2024.8.30" + "version": "2024.9.6" } \ No newline at end of file From 9e63d7ce20e9da98c7a957f8092347204e78572f Mon Sep 17 00:00:00 2001 From: Focuslinkstech <45756999+Focuslinkstech@users.noreply.github.com> Date: Fri, 6 Sep 2024 11:36:30 +0100 Subject: [PATCH 288/841] add margin to the table list --- ui/ui/reports.tpl | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/ui/ui/reports.tpl b/ui/ui/reports.tpl index 21a39b9f..7303afb1 100644 --- a/ui/ui/reports.tpl +++ b/ui/ui/reports.tpl @@ -80,8 +80,9 @@
    -
    -
    +
    +
    +
    @@ -126,6 +127,7 @@
    +
    -
    -
       +
    +
       +
    @@ -126,6 +127,7 @@
    +
    -
    -
    -
    +
    +
    @@ -127,7 +126,6 @@
    -
    {if $abills && count($abills)>0}
    From 22615eb2788f4c27f225f643e769b19a2e281ffa Mon Sep 17 00:00:00 2001 From: Focuslinkstech <45756999+Focuslinkstech@users.noreply.github.com> Date: Sat, 7 Sep 2024 12:25:21 +0100 Subject: [PATCH 293/841] fix pending transaction in customer dashboard --- ui/ui/user-ui/dashboard.tpl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ui/ui/user-ui/dashboard.tpl b/ui/ui/user-ui/dashboard.tpl index 8b53f904..361e6487 100644 --- a/ui/ui/user-ui/dashboard.tpl +++ b/ui/ui/user-ui/dashboard.tpl @@ -29,7 +29,7 @@ {$unpaid['routers']} - +  
    -
    +
      
    {/if}
    @@ -111,7 +111,7 @@ {/if} -    +   
    {if $abills && count($abills)>0}
    From d0e66d86515c9bdb539fe0e78ab63ef6f9c5010a Mon Sep 17 00:00:00 2001 From: Focuslinkstech <45756999+Focuslinkstech@users.noreply.github.com> Date: Sun, 8 Sep 2024 09:50:54 +0100 Subject: [PATCH 294/841] more css style added --- ui/ui/sections/header.tpl | 72 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) diff --git a/ui/ui/sections/header.tpl b/ui/ui/sections/header.tpl index 37411fc3..e19b8073 100644 --- a/ui/ui/sections/header.tpl +++ b/ui/ui/sections/header.tpl @@ -717,6 +717,38 @@ background-color: #694760; } + .dark-mode .table>thead>tr>td.warning, + .dark-mode .table>thead>tr>th.warning, + .dark-mode .table>thead>tr.warning>td, + .dark-mode .table>thead>tr.warning>th, + .dark-mode .table>tbody>tr>td.warning, + .dark-mode .table>tbody>tr>th.warning, + .dark-mode .table>tbody>tr.warning>td, + .dark-mode .table>tbody>tr.warning>th, + .dark-mode .table>tfoot>tr>td.warning, + .dark-mode .table>tfoot>tr>th.warning, + .dark-mode .table>tfoot>tr.warning>td, + .dark-mode .table>tfoot>tr.danger>th { + background-color: #787c63; + color: #ffffff; + } + + .dark-mode .table>thead>tr>td.success, + .dark-mode .table>thead>tr>th.success, + .dark-mode .table>thead>tr.success>td, + .dark-mode .table>thead>tr.success>th, + .dark-mode .table>tbody>tr>td.success, + .dark-mode .table>tbody>tr>th.success, + .dark-mode .table>tbody>tr.success>td, + .dark-mode .table>tbody>tr.success>th, + .dark-mode .table>tfoot>tr>td.success, + .dark-mode .table>tfoot>tr>th.success, + .dark-mode .table>tfoot>tr.success>td, + .dark-mode .table>tfoot>tr.success>th { + background-color: #7dcba7; + color: #ffffff; + } + .dark-mode .panel-heading { padding: 10px 15px; border-bottom: 1px solid transparent; @@ -1045,6 +1077,46 @@ background-color: #1a202c; } + .dark-mode .nav-tabs-custom>.tab-content { + background-color: #1a202c; + padding: 10px; + border-bottom-right-radius: 15px; + border-bottom-left-radius: 15px; + } + + .dark-mode .nav-tabs-custom { + margin-bottom: 20px; + background: #1a202c; + box-shadow: 0 1px 1px rgba(0, 0, 0, .1); + border-radius: 15px; + } + + .dark-mode .nav-tabs-custom>.nav-tabs>li:first-of-type.active>a { + border-left-color: transparent; + } + + .dark-mode .nav-tabs-custom>.nav-tabs>li.active>a { + border-top-color: transparent; + border-left-color: rgba(221, 224, 255, .54); + border-right-color: rgba(221, 224, 255, .54); + color: inherit; + background-color: #1a202c; + } + + .dark-mode pre { + display: block; + padding: 9.5px; + margin: 0 0 10px; + font-size: 13px; + line-height: 1.428571429; + word-break: break-all; + word-wrap: break-word; + color: inherit; + background-color: inherit; + border: 1px solid #ccc; + border-radius: 4px; + } + /* Dark Mode - Select2 Dropdown ends here */ /* dark mode styles start ends here */ From 84bc680f40b1281b6e0ddb2a65e0e3672c556466 Mon Sep 17 00:00:00 2001 From: gerandonk Date: Mon, 9 Sep 2024 07:19:48 +0700 Subject: [PATCH 295/841] Change Local-Ip PPPoE to Remote-IP Change Local-Ip PPPoE to Remote-IP in customer page and ignor attribute if empty --- system/devices/MikrotikPppoe.php | 58 +++++++++++++++++++++++++++----- ui/ui/customers-add.tpl | 2 +- ui/ui/customers-edit.tpl | 2 +- ui/ui/customers-view.tpl | 2 +- 4 files changed, 53 insertions(+), 11 deletions(-) diff --git a/system/devices/MikrotikPppoe.php b/system/devices/MikrotikPppoe.php index 6f291c48..f9d46dd0 100644 --- a/system/devices/MikrotikPppoe.php +++ b/system/devices/MikrotikPppoe.php @@ -10,14 +10,14 @@ use PEAR2\Net\RouterOS; -class MikrotikPppoe +class MikrotikPppoeCustom { // show Description function description() { return [ 'title' => 'Mikrotik PPPOE', - 'description' => 'To handle connection between PHPNuxBill with Mikrotik PPPOE', + 'description' => 'To handle connection between PHPNuxBill with Mikrotik PPPOE using Custom Username, IP and Password', 'author' => 'ibnux', 'url' => [ 'Github' => 'https://github.com/hotspotbilling/phpnuxbill/', @@ -39,14 +39,28 @@ class MikrotikPppoe }else{ $setRequest = new RouterOS\Request('/ppp/secret/set'); $setRequest->setArgument('numbers', $cid); - $setRequest->setArgument('password', $customer['password']); - $setRequest->setArgument('name', $customer['username']); + if (!empty($customer['pppoe_password'])) { + $setRequest->setArgument('password', $customer['pppoe_password']); + } else { + $setRequest->setArgument('password', $customer['password']); + } + if (!empty($customer['pppoe_username'])) { + $setRequest->setArgument('name', $customer['pppoe_username']); + } else { + $setRequest->setArgument('name', $customer['username']); + } + if (!empty($customer['pppoe_ip'])) { + $setRequest->setArgument('remote-address', $customer['pppoe_ip']); + } $setRequest->setArgument('profile', $plan['name_plan']); $setRequest->setArgument('comment', $customer['fullname'] . ' | ' . $customer['email'] . ' | ' . implode(', ', User::getBillNames($customer['id']))); $client->sendSync($setRequest); //disconnect then if(isset($isChangePlan) && $isChangePlan){ $this->removePpoeActive($client, $customer['username']); + if (!empty($customer['pppoe_username'])) { + $this->removePpoeActive($client, $customer['pppoe_username']); + } } } } @@ -60,11 +74,20 @@ class MikrotikPppoe if($p){ $this->add_customer($customer, $p); $this->removePpoeActive($client, $customer['username']); + if (!empty($customer['pppoe_username'])) { + $this->removePpoeActive($client, $customer['pppoe_username']); + } return; } } - $this->removePpoeActive($client, $customer['username']); $this->removePpoeUser($client, $customer['username']); + if (!empty($customer['pppoe_username'])) { + $this->removePpoeUser($client, $customer['pppoe_username']); + } + $this->removePpoeActive($client, $customer['username']); + if (!empty($customer['pppoe_username'])) { + $this->removePpoeActive($client, $customer['pppoe_username']); + } } // customer change username @@ -125,7 +148,15 @@ class MikrotikPppoe function getIdByCustomer($customer, $client){ $printRequest = new RouterOS\Request('/ppp/secret/print'); $printRequest->setQuery(RouterOS\Query::where('name', $customer['username'])); - return $client->sendSync($printRequest)->getProperty('.id'); + $id = $client->sendSync($printRequest)->getProperty('.id'); + if(empty($id)){ + if (!empty($customer['pppoe_username'])) { + $printRequest = new RouterOS\Request('/ppp/secret/print'); + $printRequest->setQuery(RouterOS\Query::where('name', $customer['pppoe_username'])); + $id = $client->sendSync($printRequest)->getProperty('.id'); + } + } + return $id; } function update_plan($old_name, $new_plan) @@ -294,8 +325,19 @@ class MikrotikPppoe $setRequest->setArgument('service', 'pppoe'); $setRequest->setArgument('profile', $plan['name_plan']); $setRequest->setArgument('comment', $customer['fullname'] . ' | ' . $customer['email'] . ' | ' . implode(', ', User::getBillNames($customer['id']))); - $setRequest->setArgument('password', $customer['password']); - $setRequest->setArgument('name', $customer['username']); + if (!empty($customer['pppoe_password'])) { + $setRequest->setArgument('password', $customer['pppoe_password']); + } else { + $setRequest->setArgument('password', $customer['password']); + } + if (!empty($customer['pppoe_username'])) { + $setRequest->setArgument('name', $customer['pppoe_username']); + } else { + $setRequest->setArgument('name', $customer['username']); + } + if (!empty($customer['pppoe_ip'])) { + $setRequest->setArgument('remote-address', $customer['pppoe_ip']); + } $client->sendSync($setRequest); } diff --git a/ui/ui/customers-add.tpl b/ui/ui/customers-add.tpl index 1839bcea..4a849946 100644 --- a/ui/ui/customers-add.tpl +++ b/ui/ui/customers-add.tpl @@ -110,7 +110,7 @@
    - +
    {Lang::T('Not Working for freeradius')} diff --git a/ui/ui/customers-edit.tpl b/ui/ui/customers-edit.tpl index e1ce53f8..e0f670c2 100644 --- a/ui/ui/customers-edit.tpl +++ b/ui/ui/customers-edit.tpl @@ -135,7 +135,7 @@
    - +
    diff --git a/ui/ui/customers-view.tpl b/ui/ui/customers-view.tpl index 6d7de98c..7dd0ca0e 100644 --- a/ui/ui/customers-view.tpl +++ b/ui/ui/customers-view.tpl @@ -56,7 +56,7 @@ {/if} {if $d['pppoe_ip'] != ''}
  • - PPPOE Local IP {$d['pppoe_ip']} + PPPOE Remote IP {$d['pppoe_ip']}
  • {/if} From f736868819ef5794f1f2797cbe77336f29b9320b Mon Sep 17 00:00:00 2001 From: Ibnu Maksum Date: Mon, 9 Sep 2024 09:44:28 +0700 Subject: [PATCH 296/841] update remote-address instead local-address --- system/devices/MikrotikPppoe.php | 56 +++- system/devices/MikrotikPppoeCustom.php | 407 ------------------------- 2 files changed, 50 insertions(+), 413 deletions(-) delete mode 100644 system/devices/MikrotikPppoeCustom.php diff --git a/system/devices/MikrotikPppoe.php b/system/devices/MikrotikPppoe.php index 6f291c48..71ac800a 100644 --- a/system/devices/MikrotikPppoe.php +++ b/system/devices/MikrotikPppoe.php @@ -39,14 +39,30 @@ class MikrotikPppoe }else{ $setRequest = new RouterOS\Request('/ppp/secret/set'); $setRequest->setArgument('numbers', $cid); - $setRequest->setArgument('password', $customer['password']); - $setRequest->setArgument('name', $customer['username']); + if (!empty($customer['pppoe_password'])) { + $setRequest->setArgument('password', $customer['pppoe_password']); + } else { + $setRequest->setArgument('password', $customer['password']); + } + if (!empty($customer['pppoe_username'])) { + $setRequest->setArgument('name', $customer['pppoe_username']); + } else { + $setRequest->setArgument('name', $customer['username']); + } + if (!empty($customer['pppoe_ip'])) { + $setRequest->setArgument('remote-address', $customer['pppoe_ip']); + }else{ + $setRequest->setArgument('remote-address', '0.0.0.0'); + } $setRequest->setArgument('profile', $plan['name_plan']); $setRequest->setArgument('comment', $customer['fullname'] . ' | ' . $customer['email'] . ' | ' . implode(', ', User::getBillNames($customer['id']))); $client->sendSync($setRequest); //disconnect then if(isset($isChangePlan) && $isChangePlan){ $this->removePpoeActive($client, $customer['username']); + if (!empty($customer['pppoe_username'])) { + $this->removePpoeActive($client, $customer['pppoe_username']); + } } } } @@ -60,11 +76,20 @@ class MikrotikPppoe if($p){ $this->add_customer($customer, $p); $this->removePpoeActive($client, $customer['username']); + if (!empty($customer['pppoe_username'])) { + $this->removePpoeActive($client, $customer['pppoe_username']); + } return; } } - $this->removePpoeActive($client, $customer['username']); $this->removePpoeUser($client, $customer['username']); + if (!empty($customer['pppoe_username'])) { + $this->removePpoeUser($client, $customer['pppoe_username']); + } + $this->removePpoeActive($client, $customer['username']); + if (!empty($customer['pppoe_username'])) { + $this->removePpoeActive($client, $customer['pppoe_username']); + } } // customer change username @@ -125,7 +150,15 @@ class MikrotikPppoe function getIdByCustomer($customer, $client){ $printRequest = new RouterOS\Request('/ppp/secret/print'); $printRequest->setQuery(RouterOS\Query::where('name', $customer['username'])); - return $client->sendSync($printRequest)->getProperty('.id'); + $id = $client->sendSync($printRequest)->getProperty('.id'); + if(empty($id)){ + if (!empty($customer['pppoe_username'])) { + $printRequest = new RouterOS\Request('/ppp/secret/print'); + $printRequest->setQuery(RouterOS\Query::where('name', $customer['pppoe_username'])); + $id = $client->sendSync($printRequest)->getProperty('.id'); + } + } + return $id; } function update_plan($old_name, $new_plan) @@ -294,8 +327,19 @@ class MikrotikPppoe $setRequest->setArgument('service', 'pppoe'); $setRequest->setArgument('profile', $plan['name_plan']); $setRequest->setArgument('comment', $customer['fullname'] . ' | ' . $customer['email'] . ' | ' . implode(', ', User::getBillNames($customer['id']))); - $setRequest->setArgument('password', $customer['password']); - $setRequest->setArgument('name', $customer['username']); + if (!empty($customer['pppoe_password'])) { + $setRequest->setArgument('password', $customer['pppoe_password']); + } else { + $setRequest->setArgument('password', $customer['password']); + } + if (!empty($customer['pppoe_username'])) { + $setRequest->setArgument('name', $customer['pppoe_username']); + } else { + $setRequest->setArgument('name', $customer['username']); + } + if (!empty($customer['pppoe_ip'])) { + $setRequest->setArgument('remote-address', $customer['pppoe_ip']); + } $client->sendSync($setRequest); } diff --git a/system/devices/MikrotikPppoeCustom.php b/system/devices/MikrotikPppoeCustom.php deleted file mode 100644 index 83406144..00000000 --- a/system/devices/MikrotikPppoeCustom.php +++ /dev/null @@ -1,407 +0,0 @@ - 'Mikrotik PPPOE Custom', - 'description' => 'To handle connection between PHPNuxBill with Mikrotik PPPOE using Custom Username, IP and Password', - 'author' => 'ibnux', - 'url' => [ - 'Github' => 'https://github.com/hotspotbilling/phpnuxbill/', - 'Telegram' => 'https://t.me/phpnuxbill', - 'Donate' => 'https://paypal.me/ibnux' - ] - ]; - } - - function add_customer($customer, $plan) - { - global $isChangePlan; - $mikrotik = $this->info($plan['routers']); - $client = $this->getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']); - $cid = self::getIdByCustomer($customer, $client); - if (empty($cid)) { - //customer not exists, add it - $this->addPpoeUser($client, $plan, $customer); - }else{ - $setRequest = new RouterOS\Request('/ppp/secret/set'); - $setRequest->setArgument('numbers', $cid); - if (!empty($customer['pppoe_password'])) { - $setRequest->setArgument('password', $customer['pppoe_password']); - } else { - $setRequest->setArgument('password', $customer['password']); - } - if (!empty($customer['pppoe_username'])) { - $setRequest->setArgument('name', $customer['pppoe_username']); - } else { - $setRequest->setArgument('name', $customer['username']); - } - if (!empty($customer['pppoe_ip'])) { - $setRequest->setArgument('local-address', $customer['pppoe_ip']); - }else{ - $setRequest->setArgument('local-address', '0.0.0.0'); - } - $setRequest->setArgument('profile', $plan['name_plan']); - $setRequest->setArgument('comment', $customer['fullname'] . ' | ' . $customer['email'] . ' | ' . implode(', ', User::getBillNames($customer['id']))); - $client->sendSync($setRequest); - //disconnect then - if(isset($isChangePlan) && $isChangePlan){ - $this->removePpoeActive($client, $customer['username']); - if (!empty($customer['pppoe_username'])) { - $this->removePpoeActive($client, $customer['pppoe_username']); - } - } - } - } - - function remove_customer($customer, $plan) - { - $mikrotik = $this->info($plan['routers']); - $client = $this->getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']); - if (!empty($plan['plan_expired'])) { - $p = ORM::for_table("tbl_plans")->find_one($plan['plan_expired']); - if($p){ - $this->add_customer($customer, $p); - $this->removePpoeActive($client, $customer['username']); - if (!empty($customer['pppoe_username'])) { - $this->removePpoeActive($client, $customer['pppoe_username']); - } - return; - } - } - $this->removePpoeUser($client, $customer['username']); - if (!empty($customer['pppoe_username'])) { - $this->removePpoeUser($client, $customer['pppoe_username']); - } - $this->removePpoeActive($client, $customer['username']); - if (!empty($customer['pppoe_username'])) { - $this->removePpoeActive($client, $customer['pppoe_username']); - } - } - - // customer change username - public function change_username($plan, $from, $to) - { - $mikrotik = $this->info($plan['routers']); - $client = $this->getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']); - //check if customer exists - $printRequest = new RouterOS\Request('/ppp/secret/print'); - $printRequest->setQuery(RouterOS\Query::where('name', $from)); - $cid = $client->sendSync($printRequest)->getProperty('.id'); - if (!empty($cid)) { - $setRequest = new RouterOS\Request('/ppp/secret/set'); - $setRequest->setArgument('numbers', $cid); - $setRequest->setArgument('name', $to); - $client->sendSync($setRequest); - //disconnect then - $this->removePpoeActive($client, $from); - } - } - - function add_plan($plan) - { - $mikrotik = $this->info($plan['routers']); - $client = $this->getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']); - - //Add Pool - - $bw = ORM::for_table("tbl_bandwidth")->find_one($plan['id_bw']); - if ($bw['rate_down_unit'] == 'Kbps') { - $unitdown = 'K'; - } else { - $unitdown = 'M'; - } - if ($bw['rate_up_unit'] == 'Kbps') { - $unitup = 'K'; - } else { - $unitup = 'M'; - } - $rate = $bw['rate_up'] . $unitup . "/" . $bw['rate_down'] . $unitdown; - if(!empty(trim($bw['burst']))){ - $rate .= ' '.$bw['burst']; - } - $pool = ORM::for_table("tbl_pool")->where("pool_name", $plan['pool'])->find_one(); - $addRequest = new RouterOS\Request('/ppp/profile/add'); - $client->sendSync( - $addRequest - ->setArgument('name', $plan['name_plan']) - ->setArgument('local-address', (!empty($pool['local_ip'])) ? $pool['local_ip']: $pool['pool_name']) - ->setArgument('remote-address', $pool['pool_name']) - ->setArgument('rate-limit', $rate) - ); - } - - /** - * Function to ID by username from Mikrotik - */ - function getIdByCustomer($customer, $client){ - $printRequest = new RouterOS\Request('/ppp/secret/print'); - $printRequest->setQuery(RouterOS\Query::where('name', $customer['username'])); - $id = $client->sendSync($printRequest)->getProperty('.id'); - if(empty($id)){ - if (!empty($customer['pppoe_username'])) { - $printRequest = new RouterOS\Request('/ppp/secret/print'); - $printRequest->setQuery(RouterOS\Query::where('name', $customer['pppoe_username'])); - $id = $client->sendSync($printRequest)->getProperty('.id'); - } - } - return $id; - } - - function update_plan($old_name, $new_plan) - { - $mikrotik = $this->info($new_plan['routers']); - $client = $this->getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']); - - $printRequest = new RouterOS\Request( - '/ppp profile print .proplist=.id', - RouterOS\Query::where('name', $old_name['name_plan']) - ); - $profileID = $client->sendSync($printRequest)->getProperty('.id'); - if (empty($profileID)) { - $this->add_plan($new_plan); - } else { - $bw = ORM::for_table("tbl_bandwidth")->find_one($new_plan['id_bw']); - if ($bw['rate_down_unit'] == 'Kbps') { - $unitdown = 'K'; - } else { - $unitdown = 'M'; - } - if ($bw['rate_up_unit'] == 'Kbps') { - $unitup = 'K'; - } else { - $unitup = 'M'; - } - $rate = $bw['rate_up'] . $unitup . "/" . $bw['rate_down'] . $unitdown; - if(!empty(trim($bw['burst']))){ - $rate .= ' '.$bw['burst']; - } - $pool = ORM::for_table("tbl_pool")->where("pool_name", $new_plan['pool'])->find_one(); - $setRequest = new RouterOS\Request('/ppp/profile/set'); - $client->sendSync( - $setRequest - ->setArgument('numbers', $profileID) - ->setArgument('local-address', (!empty($pool['local_ip'])) ? $pool['local_ip']: $pool['pool_name']) - ->setArgument('remote-address', $pool['pool_name']) - ->setArgument('rate-limit', $rate) - ->setArgument('on-up', $new_plan['on_login']) - ->setArgument('on-down', $new_plan['on_logout']) - ); - } - } - - function remove_plan($plan) - { - $mikrotik = $this->info($plan['routers']); - $client = $this->getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']); - $printRequest = new RouterOS\Request( - '/ppp profile print .proplist=.id', - RouterOS\Query::where('name', $plan['name_plan']) - ); - $profileID = $client->sendSync($printRequest)->getProperty('.id'); - - $removeRequest = new RouterOS\Request('/ppp/profile/remove'); - $client->sendSync( - $removeRequest - ->setArgument('numbers', $profileID) - ); - } - - function add_pool($pool){ - global $_app_stage; - if ($_app_stage == 'demo') { - return null; - } - $mikrotik = $this->info($pool['routers']); - $client = $this->getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']); - $addRequest = new RouterOS\Request('/ip/pool/add'); - $client->sendSync( - $addRequest - ->setArgument('name', $pool['pool_name']) - ->setArgument('ranges', $pool['range_ip']) - ); - } - - function update_pool($old_pool, $new_pool){ - global $_app_stage; - if ($_app_stage == 'demo') { - return null; - } - $mikrotik = $this->info($new_pool['routers']); - $client = $this->getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']); - $printRequest = new RouterOS\Request( - '/ip pool print .proplist=.id', - RouterOS\Query::where('name', $old_pool['pool_name']) - ); - $poolID = $client->sendSync($printRequest)->getProperty('.id'); - if (empty($poolID)) { - $this->add_pool($new_pool); - } else { - $setRequest = new RouterOS\Request('/ip/pool/set'); - $client->sendSync( - $setRequest - ->setArgument('numbers', $poolID) - ->setArgument('name', $new_pool['pool_name']) - ->setArgument('ranges', $new_pool['range_ip']) - ); - } - } - - function remove_pool($pool){ - global $_app_stage; - if ($_app_stage == 'demo') { - return null; - } - $mikrotik = $this->info($pool['routers']); - $client = $this->getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']); - $printRequest = new RouterOS\Request( - '/ip pool print .proplist=.id', - RouterOS\Query::where('name', $pool['pool_name']) - ); - $poolID = $client->sendSync($printRequest)->getProperty('.id'); - $removeRequest = new RouterOS\Request('/ip/pool/remove'); - $client->sendSync( - $removeRequest - ->setArgument('numbers', $poolID) - ); - } - - - function online_customer($customer, $router_name) - { - $mikrotik = $this->info($router_name); - $client = $this->getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']); - $printRequest = new RouterOS\Request( - '/ppp active print', - RouterOS\Query::where('user', $customer['username']) - ); - return $client->sendSync($printRequest)->getProperty('.id'); - } - - function info($name) - { - return ORM::for_table('tbl_routers')->where('name', $name)->find_one(); - } - - function getClient($ip, $user, $pass) - { - global $_app_stage; - if ($_app_stage == 'demo') { - return null; - } - $iport = explode(":", $ip); - return new RouterOS\Client($iport[0], $user, $pass, ($iport[1]) ? $iport[1] : null); - } - - function removePpoeUser($client, $username) - { - global $_app_stage; - if ($_app_stage == 'demo') { - return null; - } - $printRequest = new RouterOS\Request('/ppp/secret/print'); - //$printRequest->setArgument('.proplist', '.id'); - $printRequest->setQuery(RouterOS\Query::where('name', $username)); - $id = $client->sendSync($printRequest)->getProperty('.id'); - $removeRequest = new RouterOS\Request('/ppp/secret/remove'); - $removeRequest->setArgument('numbers', $id); - $client->sendSync($removeRequest); - } - - function addPpoeUser($client, $plan, $customer) - { - $setRequest = new RouterOS\Request('/ppp/secret/add'); - $setRequest->setArgument('service', 'pppoe'); - $setRequest->setArgument('profile', $plan['name_plan']); - $setRequest->setArgument('comment', $customer['fullname'] . ' | ' . $customer['email'] . ' | ' . implode(', ', User::getBillNames($customer['id']))); - if (!empty($customer['pppoe_password'])) { - $setRequest->setArgument('password', $customer['pppoe_password']); - } else { - $setRequest->setArgument('password', $customer['password']); - } - if (!empty($customer['pppoe_username'])) { - $setRequest->setArgument('name', $customer['pppoe_username']); - } else { - $setRequest->setArgument('name', $customer['username']); - } - if (!empty($customer['pppoe_ip'])) { - $setRequest->setArgument('local-address', $customer['pppoe_ip']); - } - $client->sendSync($setRequest); - } - - function removePpoeActive($client, $username) - { - global $_app_stage; - if ($_app_stage == 'demo') { - return null; - } - $onlineRequest = new RouterOS\Request('/ppp/active/print'); - $onlineRequest->setArgument('.proplist', '.id'); - $onlineRequest->setQuery(RouterOS\Query::where('name', $username)); - $id = $client->sendSync($onlineRequest)->getProperty('.id'); - - $removeRequest = new RouterOS\Request('/ppp/active/remove'); - $removeRequest->setArgument('numbers', $id); - $client->sendSync($removeRequest); - } - - 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'); - } - - function addIpToAddressList($client, $ip, $listName, $comment = '') - { - global $_app_stage; - if ($_app_stage == 'demo') { - return null; - } - $addRequest = new RouterOS\Request('/ip/firewall/address-list/add'); - $client->sendSync( - $addRequest - ->setArgument('address', $ip) - ->setArgument('comment', $comment) - ->setArgument('list', $listName) - ); - } - - function removeIpFromAddressList($client, $ip) - { - global $_app_stage; - if ($_app_stage == 'demo') { - return null; - } - $printRequest = new RouterOS\Request( - '/ip firewall address-list print .proplist=.id', - RouterOS\Query::where('address', $ip) - ); - $id = $client->sendSync($printRequest)->getProperty('.id'); - $removeRequest = new RouterOS\Request('/ip/firewall/address-list/remove'); - $client->sendSync( - $removeRequest - ->setArgument('numbers', $id) - ); - } -} From 0d2b140bcfc9761e9d813ed403cdd4991f24556b Mon Sep 17 00:00:00 2001 From: Ibnu Maksum Date: Mon, 9 Sep 2024 10:23:51 +0700 Subject: [PATCH 297/841] Fix Balance sent/received --- system/autoload/Message.php | 16 ++++++++++++++-- system/controllers/home.php | 5 +++-- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/system/autoload/Message.php b/system/autoload/Message.php index a7fbae9b..988c98e0 100644 --- a/system/autoload/Message.php +++ b/system/autoload/Message.php @@ -201,10 +201,10 @@ class Message return "$via: $msg"; } - public static function sendBalanceNotification($cust, $balance, $balance_now, $message, $via) + public static function sendBalanceNotification($cust, $target, $balance, $balance_now, $message, $via) { global $config; - $msg = str_replace('[[name]]', $cust['fullname'] . ' (' . $cust['username'] . ')', $message); + $msg = str_replace('[[name]]', $target['fullname'] . ' (' . $target['username'] . ')', $message); $msg = str_replace('[[current_balance]]', Lang::moneyFormat($balance_now), $msg); $msg = str_replace('[[balance]]', Lang::moneyFormat($balance), $msg); $phone = $cust['phonenumber']; @@ -219,6 +219,7 @@ class Message } else if ($via == 'wa') { Message::sendWhatsapp($phone, $msg); } + self::addToInbox($cust['id'], Lang::T('Balance Notification'), $msg); } return "$via: $msg"; } @@ -258,4 +259,15 @@ class Message Message::sendWhatsapp($cust['phonenumber'], $textInvoice); } } + + + public static function addToInbox($to_customer_id, $subject, $body, $from = 'System'){ + $v = ORM::for_table('tbl_customers_inbox')->create(); + $v->from = $from; + $v->customer_id = $to_customer_id; + $v->subject = $subject; + $v->date_created = date('Y-m-d H:i:s'); + $v->body = nl2br($body); + $v->save(); + } } diff --git a/system/controllers/home.php b/system/controllers/home.php index 147476b5..a71d340e 100644 --- a/system/controllers/home.php +++ b/system/controllers/home.php @@ -71,8 +71,9 @@ if (_post('send') == 'balance') { $d->pg_url_payment = 'balance'; $d->status = 2; $d->save(); - Message::sendBalanceNotification($user, $balance, ($user['balance'] - $balance), Lang::getNotifText('balance_send'), $config['user_notification_payment']); - Message::sendBalanceNotification($target, $balance, ($target['balance'] + $balance), Lang::getNotifText('balance_received'), $config['user_notification_payment']); + // + Message::sendBalanceNotification($user, $target, $balance, ($user['balance'] - $balance), Lang::getNotifText('balance_send'), $config['user_notification_payment']); + Message::sendBalanceNotification($target, $user, $balance, ($target['balance'] + $balance), Lang::getNotifText('balance_received'), $config['user_notification_payment']); Message::sendTelegram("#u$user[username] send balance to #u$target[username] \n" . Lang::moneyFormat($balance)); r2(U . 'home', 's', Lang::T('Sending balance success')); } From 45bb3f04eebea7783f7db93e065c99facedeb182 Mon Sep 17 00:00:00 2001 From: Ibnu Maksum Date: Mon, 9 Sep 2024 10:26:28 +0700 Subject: [PATCH 298/841] add back button on inbox --- ui/ui/user-ui/inbox.tpl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ui/ui/user-ui/inbox.tpl b/ui/ui/user-ui/inbox.tpl index 89210942..954e2896 100644 --- a/ui/ui/user-ui/inbox.tpl +++ b/ui/ui/user-ui/inbox.tpl @@ -29,10 +29,11 @@ {Lang::T("Next")} {/if}
    + {Lang::T("Back")} {Lang::T("Delete")} - {Lang::T("Share")} + {Lang::T("Share")}
    From 3aead7a98ab7a53fd8f93d99215e0dea58152ea1 Mon Sep 17 00:00:00 2001 From: Ibnu Maksum Date: Mon, 9 Sep 2024 13:23:26 +0700 Subject: [PATCH 299/841] Fix toggle dark mode --- ui/ui/user-ui/header.tpl | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/ui/ui/user-ui/header.tpl b/ui/ui/user-ui/header.tpl index a2be9f04..4298c03a 100644 --- a/ui/ui/user-ui/header.tpl +++ b/ui/ui/user-ui/header.tpl @@ -333,9 +333,6 @@ .toggle-container { - position: absolute; - top: 17px; - right: 15px; cursor: pointer; } @@ -346,10 +343,6 @@ } @media (max-width: 600px) { - .toggle-container { - top: 15px; - right: 200px; - } .toggle-container .toggle-icon { font-size: 20px; @@ -781,13 +774,13 @@
  • - +
  • - - - - - - - - - - - - - - - - - - - - - - - - - - - - - {foreach $d as $ds} +
    +
    {Lang::T('Internet Package')}{Lang::T('Limit')} - {Lang::T('Expired')}
    {Lang::T('Name')}{Lang::T('Type')}Bandwidth{Lang::T('Category')}{Lang::T('Price')}{Lang::T('Validity')}{Lang::T('Time')}{Lang::T('Data')}{Lang::T('Location')}{Lang::T('Device')}{Lang::T('Internet Package')}{Lang::T('Date')}{Lang::T('ID')}{Lang::T('Manage')}
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + {foreach $d as $ds} + }class="warning" title="Postpaid" {/if}> @@ -146,11 +148,11 @@ @@ -163,13 +165,14 @@ {Lang::T('Edit')} + onclick="return confirm('{Lang::T('Delete')}?')" + class="btn btn-danger btn-xs"> - {/foreach} - -
    {Lang::T('Internet Package')} + {Lang::T('Limit')} + {Lang::T('Expired')}
    {Lang::T('Name')}{Lang::T('Type')}Bandwidth{Lang::T('Category')}{Lang::T('Price')}{Lang::T('Validity')}{Lang::T('Time')}{Lang::T('Data')}{Lang::T('Location')}{Lang::T('Device')}{Lang::T('Internet Package')}{Lang::T('Date')}{Lang::T('ID')}{Lang::T('Manage')}
    {$ds['name_plan']} {if $ds['prepaid'] == no}Postpaid{else}Prepaid{/if} {$ds['plan_type']} {$ds['name_bw']}{$ds['data_limit']} {$ds['data_unit']} {if $ds['is_radius']} - RADIUS + RADIUS {else} - {if $ds['routers']!=''} - {$ds['routers']} - {/if} + {if $ds['routers']!=''} + {$ds['routers']} + {/if} {/if} {$ds['device']}
    + {/foreach} + + +
    -{include file="sections/footer.tpl"} +{include file="sections/footer.tpl"} \ No newline at end of file diff --git a/ui/ui/plan.tpl b/ui/ui/plan.tpl index 4cf71280..3cca5861 100644 --- a/ui/ui/plan.tpl +++ b/ui/ui/plan.tpl @@ -5,19 +5,19 @@
    {if in_array($_admin['user_type'],['SuperAdmin','Admin'])} -
    - sync -
    - {*
    - CSV -
    *} +
    + sync +
    + {*
    + CSV +
    *} {/if}   -{Lang::T('Active Customers')} + {Lang::T('Active Customers')}
    @@ -70,33 +70,34 @@
    - - - - - - - - - - - - - - - {foreach $d as $ds} - +
      +
    {Lang::T('Username')}{Lang::T('Plan Name')}{Lang::T('Type')}{Lang::T('Created On')}{Lang::T('Expires On')}{Lang::T('Method')}{Lang::T('Location')}{Lang::T('Manage')}
    + + + + + + + + + + + + + + {foreach $d as $ds} + {if $ds['type'] == 'Hotspot'} - + {else} - + {/if} @@ -107,19 +108,20 @@ {Lang::T('Edit')} {if in_array($_admin['user_type'],['SuperAdmin','Admin'])} - + {/if} {if $ds['status']=='off' && $_c['extend_expired']} - {Lang::T('Extend')} + {Lang::T('Extend')} {/if} - {/foreach} - -
    {Lang::T('Username')}{Lang::T('Plan Name')}{Lang::T('Type')}{Lang::T('Created On')}{Lang::T('Expires On')}{Lang::T('Method')}{Lang::T('Location')}{Lang::T('Manage')}
    {if $ds['customer_id'] == '0'} - {$ds['username']} + {$ds['username']} {else} - {$ds['username']} + {$ds['username']} {/if} {$ds['namebp']}{$ds['namebp']}{$ds['namebp']}{$ds['namebp']}{$ds['type']} {Lang::dateAndTimeFormat($ds['recharged_on'],$ds['recharged_time'])}
    + {/foreach} + + +
    {include file="pagination.tpl"}
    @@ -131,10 +133,10 @@ var res = prompt("Extend for many days?", "3"); if (res) { if (confirm("Extend for " + res + " days?")) { - window.location.href = "{$_url}plan/extend/"+idP+"/"+res+"&stoken={App::getToken()}"; + window.location.href = "{$_url}plan/extend/" + idP + "/" + res + "&stoken={App::getToken()}"; } } } -{include file="sections/footer.tpl"} +{include file="sections/footer.tpl"} \ No newline at end of file diff --git a/ui/ui/pppoe.tpl b/ui/ui/pppoe.tpl index 3c17d6b1..9dfc8711 100644 --- a/ui/ui/pppoe.tpl +++ b/ui/ui/pppoe.tpl @@ -35,8 +35,8 @@
    @@ -44,9 +44,9 @@
    @@ -54,8 +54,8 @@
    @@ -63,8 +63,8 @@
    @@ -72,7 +72,7 @@ @@ -81,7 +81,7 @@
    @@ -104,36 +104,38 @@
    - - - - - - - - - - - - - - - - - - - - - - - - - - {foreach $d as $ds} - +
    +
    {Lang::T('Internet Plan')} - {Lang::T('Expired')}
    {Lang::T('Name')}{Lang::T('Type')}{Lang::T('Bandwidth')}{Lang::T('Price')}{Lang::T('Validity')}{Lang::T('IP Pool')}{Lang::T('Internet Plan')}{Lang::T('Date')}{Lang::T('Location')}{Lang::T('Device')}{Lang::T('Manage')}ID
    + + + + + + + + + + + + + + + + + + + + + + + + + {foreach $d as $ds} + - + @@ -144,11 +146,11 @@ @@ -161,9 +163,10 @@ - {/foreach} - -
    {Lang::T('Internet Plan')} + {Lang::T('Expired')}
    {Lang::T('Name')}{Lang::T('Type')}{Lang::T('Bandwidth')}{Lang::T('Price')}{Lang::T('Validity')}{Lang::T('IP Pool')}{Lang::T('Internet Plan')}{Lang::T('Date')}{Lang::T('Location')}{Lang::T('Device')}{Lang::T('Manage')}ID
    {$ds['name_plan']}{$ds['plan_type']} {if $ds['prepaid'] != 'yes'}{Lang::T('Postpaid')}{else}{Lang::T('Prepaid')}{/if}{$ds['plan_type']} {if $ds['prepaid'] != + 'yes'}{Lang::T('Postpaid')}{else}{Lang::T('Prepaid')}{/if} {$ds['name_bw']} {Lang::moneyFormat($ds['price'])} {$ds['validity']} {$ds['validity_unit']}{if $ds['prepaid'] == no}{$ds['expired_date']}{/if} {if $ds['is_radius']} - RADIUS + RADIUS {else} - {if $ds['routers']!=''} - {$ds['routers']} - {/if} + {if $ds['routers']!=''} + {$ds['routers']} + {/if} {/if} {$ds['device']} {$ds['id']}
    + {/foreach} + + +
    -{include file="sections/footer.tpl"} +{include file="sections/footer.tpl"} \ No newline at end of file diff --git a/ui/ui/voucher.tpl b/ui/ui/voucher.tpl index 6f357b48..abf652f0 100644 --- a/ui/ui/voucher.tpl +++ b/ui/ui/voucher.tpl @@ -17,11 +17,12 @@
    {if in_array($_admin['user_type'],['SuperAdmin','Admin'])} - + {/if}  
    @@ -41,8 +42,8 @@
    @@ -50,7 +51,7 @@
    @@ -65,7 +66,7 @@
    @@ -76,8 +77,8 @@ class="fa fa-search">
    - +
    @@ -85,24 +86,25 @@
    - - - - - - - - - - - - - - - - - {foreach $d as $ds} - +
      +
    ID{Lang::T('Type')}{Lang::T('Routers')}{Lang::T('Plan Name')}{Lang::T('Code Voucher')}{Lang::T('Status Voucher')}{Lang::T('Customer')}{Lang::T('Used Date')}{Lang::T('Generated By')}{Lang::T('Manage')}
    + + + + + + + + + + + + + + + + {foreach $d as $ds} + @@ -112,33 +114,35 @@ onmouseenter="this.style.backgroundColor = 'white';"> {$ds['code']} - {/foreach} - -
    ID{Lang::T('Type')}{Lang::T('Routers')}{Lang::T('Plan Name')}{Lang::T('Code Voucher')}{Lang::T('Status Voucher')}{Lang::T('Customer')}{Lang::T('Used Date')}{Lang::T('Generated By')}{Lang::T('Manage')}
    {$ds['id']} {$ds['type']} {$ds['routers']} {if $ds['status'] eq '0'} {else} + {else} {/if} {if $ds['user'] eq '0'} - {else}{$ds['user']} {/if} {if $ds['used_date']}{Lang::dateTimeFormat($ds['used_date'])}{/if} {if $ds['generated_by']} - {$admins[$ds['generated_by']]} + {$admins[$ds['generated_by']]} {else} - {/if} {if $ds['status'] neq '1'} -   {Lang::T('View')}   +   {Lang::T('View')}   {/if} {if in_array($_admin['user_type'],['SuperAdmin','Admin'])} - + {/if}
    + {/foreach} + + +
    {include file="pagination.tpl"} -{include file="sections/footer.tpl"} +{include file="sections/footer.tpl"} \ No newline at end of file From 723e99ebedc231e502707621ec169cd1da57aa57 Mon Sep 17 00:00:00 2001 From: Focuslinkstech <45756999+Focuslinkstech@users.noreply.github.com> Date: Wed, 11 Sep 2024 14:19:13 +0100 Subject: [PATCH 304/841] fix panel headers in css, add cron job monitor to check if cron is running, has run, or not setup --- system/controllers/dashboard.php | 6 +++ system/cron.php | 69 ++++++++++++++++++-------------- ui/ui/dashboard.tpl | 17 ++++++++ ui/ui/sections/header.tpl | 30 ++++++++++++-- 4 files changed, 87 insertions(+), 35 deletions(-) diff --git a/system/controllers/dashboard.php b/system/controllers/dashboard.php index 4d1c9849..9f1185b0 100644 --- a/system/controllers/dashboard.php +++ b/system/controllers/dashboard.php @@ -214,6 +214,12 @@ if ($config['router_check']) { $ui->assign('routeroffs', $routeroffs); } +$timestampFile = "$UPLOAD_PATH/cron_last_run.txt"; +if (file_exists($timestampFile)) { + $lastRunTime = file_get_contents($timestampFile); + $ui->assign('run_date', date('Y-m-d h:i:s A', $lastRunTime)); +} + // Assign the monthly sales data to Smarty $ui->assign('start_date', $start_date); $ui->assign('current_date', $current_date); diff --git a/system/cron.php b/system/cron.php index e4e6719c..81d9f423 100644 --- a/system/cron.php +++ b/system/cron.php @@ -1,6 +1,27 @@ where('enabled', '1')->find_many(); if (!$routers) { echo "No active routers found in the database.\n"; @@ -186,14 +187,20 @@ if ($config['router_check']) { Message::SendEmail($adminEmail, $subject, $message); sendTelegram($message); } - - if (defined('PHP_SAPI') && PHP_SAPI === 'cli') { - echo "Cronjob finished\n"; - } else { - echo ""; - } - - flock($lock, LOCK_UN); - fclose($lock); - unlink($lockFile); + echo "Router monitoring finished\n"; } + + +if (defined('PHP_SAPI') && PHP_SAPI === 'cli') { + echo "Cronjob finished\n"; +} else { + echo ""; +} + +flock($lock, LOCK_UN); +fclose($lock); +unlink($lockFile); + +$timestampFile = "$UPLOAD_PATH/cron_last_run.txt"; +file_put_contents($timestampFile, time()); + diff --git a/ui/ui/dashboard.tpl b/ui/ui/dashboard.tpl index eb6788da..7a998ba8 100644 --- a/ui/ui/dashboard.tpl +++ b/ui/ui/dashboard.tpl @@ -194,6 +194,23 @@ {/if} + {if $run_date} + {if $current_time - $run_time > 3600} +
    +
      {Lang::T('Cron has not run for over 1 hour. Please + check your setup.')}
    +
    + {else} +
    +
    {Lang::T('Cron Job last ran on')}: {$run_date}
    +
    + {/if} + {else} +
    +
      {Lang::T('Cron appear not been setup, please check + your cron setup.')}
    +
    + {/if} {if $_c['hide_pg'] != 'yes'}
    {Lang::T('Payment Gateway')}: {str_replace(',',', ',$_c['payment_gateway'])} diff --git a/ui/ui/sections/header.tpl b/ui/ui/sections/header.tpl index bba3dbce..34b7f1e9 100644 --- a/ui/ui/sections/header.tpl +++ b/ui/ui/sections/header.tpl @@ -148,12 +148,26 @@ color: inherit; background-color: transparent; border-color: transparent; + border-bottom-right-radius: 21px; + border-bottom-left-radius: 21px; } - .panel-primary>.panel-heading { - color: inherit; - background-color: transparent; - border-color: transparent; + .panel-success>.panel-heading { + border-bottom-right-radius: 21px; + border-bottom-left-radius: 21px; + } + + .panel-warning>.panel-heading { + border-bottom-right-radius: 21px; + border-bottom-left-radius: 21px; + } + + .panel-danger>.panel-heading { + color: #a94442; + background-color: #f2dede; + border-color: #ebccd1; + border-bottom-right-radius: 21px; + border-bottom-left-radius: 21px; } .panel-heading { @@ -656,6 +670,9 @@ } .toggle-container { + position: absolute; + top: 17px; + right: 15px; cursor: pointer; } @@ -666,6 +683,11 @@ } @media (max-width: 600px) { + .toggle-container { + top: 15px; + right: 60px; + } + .toggle-container .toggle-icon { font-size: 20px; color: rgb(100 116 139); From 05b681df47fb12f84725091f3831b0199a96a545 Mon Sep 17 00:00:00 2001 From: Focuslinkstech <45756999+Focuslinkstech@users.noreply.github.com> Date: Wed, 11 Sep 2024 14:38:54 +0100 Subject: [PATCH 305/841] change current_time to current_date --- ui/ui/dashboard.tpl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/ui/dashboard.tpl b/ui/ui/dashboard.tpl index 7a998ba8..78955672 100644 --- a/ui/ui/dashboard.tpl +++ b/ui/ui/dashboard.tpl @@ -195,7 +195,7 @@
    {/if} {if $run_date} - {if $current_time - $run_time > 3600} + {if $current_date - $run_time > 3600}
      {Lang::T('Cron has not run for over 1 hour. Please check your setup.')}
    From fe532a62386a5b588d65cb8fdd1b5d9097153fac Mon Sep 17 00:00:00 2001 From: Focuslinkstech <45756999+Focuslinkstech@users.noreply.github.com> Date: Wed, 11 Sep 2024 16:52:34 +0100 Subject: [PATCH 306/841] change the time calculation logic --- ui/ui/dashboard.tpl | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/ui/ui/dashboard.tpl b/ui/ui/dashboard.tpl index 78955672..f0432982 100644 --- a/ui/ui/dashboard.tpl +++ b/ui/ui/dashboard.tpl @@ -195,7 +195,9 @@
    {/if} {if $run_date} - {if $current_date - $run_time > 3600} + {assign var="current_time" value=$smarty.now} + {assign var="run_time" value=strtotime($run_date)} + {if $current_time - $run_time > 3600}
      {Lang::T('Cron has not run for over 1 hour. Please check your setup.')}
    From 68de3a71b930f55c0713197c745263e088601b0b Mon Sep 17 00:00:00 2001 From: Focuslinkstech <45756999+Focuslinkstech@users.noreply.github.com> Date: Thu, 12 Sep 2024 11:39:45 +0100 Subject: [PATCH 307/841] if admin session time error, it logout admin out whether admin are online or not, once time reach it logout you out --- system/autoload/Admin.php | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/system/autoload/Admin.php b/system/autoload/Admin.php index 66052cda..18d016c6 100644 --- a/system/autoload/Admin.php +++ b/system/autoload/Admin.php @@ -13,25 +13,27 @@ class Admin { global $db_pass, $config; $enable_session_timeout = $config['enable_session_timeout']; - if ($enable_session_timeout) { - $timeout = 60; - if ($config['session_timeout_duration']) { - $timeout = intval($config['session_timeout_duration']); + $session_timeout_duration = $config['session_timeout_duration'] ? intval($config['session_timeout_duration'] * 60) : intval(60 * 60); // Convert minutes to seconds + + // Check if the session is active and valid + if (isset($_SESSION['aid']) && isset($_SESSION['aid_expiration'])) { + if ($_SESSION['aid_expiration'] > time()) { + if ($enable_session_timeout) { + $_SESSION['aid_expiration'] = time() + $session_timeout_duration; + } + return $_SESSION['aid']; + } + // Session expired, log out the user + elseif ($enable_session_timeout && $_SESSION['aid_expiration'] <= time()) { + self::removeCookie(); + session_destroy(); + _alert(Lang::T('Session has expired. Please log in again.'), 'danger', "admin"); + return 0; } - $session_timeout_duration = $timeout * 60; // Convert minutes to seconds } - if (isset($_SESSION['aid']) && isset($_SESSION['aid_expiration']) && $_SESSION['aid_expiration'] > time()) { - return $_SESSION['aid']; - } elseif ($enable_session_timeout && isset($_SESSION['aid']) && isset($_SESSION['aid_expiration']) && $_SESSION['aid_expiration'] <= time()) { - self::removeCookie(); - session_destroy(); - _alert(Lang::T('Session has expired. Please log in again.'), 'danger', "admin"); - return 0; - } - // Check if cookie is set and valid + // Check if the cookie is set and valid elseif (isset($_COOKIE['aid'])) { - // id.time.sha1 $tmp = explode('.', $_COOKIE['aid']); if (sha1($tmp[0] . '.' . $tmp[1] . '.' . $db_pass) == $tmp[2]) { if (time() - $tmp[1] < 86400 * 7) { From 095e8937a29c6279b86e6ea5fcf5c0b94c0e1943 Mon Sep 17 00:00:00 2001 From: agamsatria Date: Fri, 13 Sep 2024 00:43:46 +0700 Subject: [PATCH 308/841] Paket vpn tunnel remot --- system/controllers/home.php | 10 +- system/controllers/order.php | 7 + system/controllers/pool.php | 126 +++++++++++ system/controllers/services.php | 374 ++++++++++++++++++++++++++++++++ system/controllers/settings.php | 10 + system/updates.json | 6 + ui/ui/app-localisation.tpl | 8 + ui/ui/customers-add.tpl | 1 + ui/ui/customers-edit.tpl | 1 + ui/ui/plan.tpl | 10 +- ui/ui/port-add.tpl | 51 +++++ ui/ui/port-edit.tpl | 49 +++++ ui/ui/port.tpl | 76 +++++++ ui/ui/recharge.tpl | 1 + ui/ui/scripts/custom.js | 23 +- ui/ui/sections/header.tpl | 4 + ui/ui/user-ui/dashboard.tpl | 25 ++- ui/ui/user-ui/orderPlan.tpl | 104 +++++++++ ui/ui/vpn-add.tpl | 188 ++++++++++++++++ ui/ui/vpn-edit.tpl | 255 ++++++++++++++++++++++ ui/ui/vpn.tpl | 179 +++++++++++++++ 21 files changed, 1502 insertions(+), 6 deletions(-) create mode 100644 ui/ui/port-add.tpl create mode 100644 ui/ui/port-edit.tpl create mode 100644 ui/ui/port.tpl create mode 100644 ui/ui/vpn-add.tpl create mode 100644 ui/ui/vpn-edit.tpl create mode 100644 ui/ui/vpn.tpl diff --git a/system/controllers/home.php b/system/controllers/home.php index a71d340e..20e1d1b6 100644 --- a/system/controllers/home.php +++ b/system/controllers/home.php @@ -317,7 +317,15 @@ if (!empty($_SESSION['nux-mac']) && !empty($_SESSION['nux-ip'] && !empty($_SESSI } } } - + +$tcf = ORM::for_table('tbl_customers_fields') + ->where('customer_id', $user['id']) + ->find_many(); +$vpn = ORM::for_table('tbl_port_pool') + ->find_one(); +$ui->assign('cf', $tcf); +$ui->assign('vpn', $vpn); + $ui->assign('unpaid', ORM::for_table('tbl_payment_gateway') ->where('username', $user['username']) ->where('status', 1) diff --git a/system/controllers/order.php b/system/controllers/order.php index 0d4b2a3c..988db104 100644 --- a/system/controllers/order.php +++ b/system/controllers/order.php @@ -113,12 +113,19 @@ switch ($action) { ->where('type', 'Hotspot') ->where('prepaid', 'yes') ->find_many(); + $plans_vpn = ORM::for_table('tbl_plans') + ->where('plan_type', $account_type) + ->where('enabled', '1')->where('is_radius', 0) + ->where('type', 'VPN') + ->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); + $ui->assign('plans_vpn', $plans_vpn); run_hook('customer_view_order_plan'); #HOOK $ui->display('user-ui/orderPlan.tpl'); break; diff --git a/system/controllers/pool.php b/system/controllers/pool.php index 5528e751..ba599f22 100644 --- a/system/controllers/pool.php +++ b/system/controllers/pool.php @@ -147,6 +147,132 @@ switch ($action) { } else { r2(U . 'pool/edit/' . $id, 'e', $msg); } + + case 'port': + $ui->assign('xfooter', ''); + + $name = _post('name'); + if ($name != '') { + $query = ORM::for_table('tbl_port_pool')->where_like('pool_name', '%' . $name . '%')->order_by_desc('id'); + $d = Paginator::findMany($query, ['name' => $name]); + } else { + $query = ORM::for_table('tbl_port_pool')->order_by_desc('id'); + $d = Paginator::findMany($query); + } + + $ui->assign('d', $d); + run_hook('view_port'); #HOOK + $ui->display('port.tpl'); + break; + + case 'add-port': + $r = ORM::for_table('tbl_routers')->find_many(); + $ui->assign('r', $r); + run_hook('view_add_port'); #HOOK + $ui->display('port-add.tpl'); + break; + + case 'edit-port': + $id = $routes['2']; + $d = ORM::for_table('tbl_port_pool')->find_one($id); + if ($d) { + $ui->assign('d', $d); + run_hook('view_edit_port'); #HOOK + $ui->display('port-edit.tpl'); + } else { + r2(U . 'pool/port', 'e', Lang::T('Account Not Found')); + } + break; + + case 'delete-port': + $id = $routes['2']; + run_hook('delete_port'); #HOOK + $d = ORM::for_table('tbl_port_pool')->find_one($id); + if ($d) { + $d->delete(); + + r2(U . 'pool/port', 's', Lang::T('Data Deleted Successfully')); + } + break; + + case 'sync': + $pools = ORM::for_table('tbl_port_pool')->find_many(); + $log = ''; + foreach ($pools as $pool) { + if ($pool['routers'] != 'radius') { + (new MikrotikPppoe())->update_pool($pool, $pool); + $log .= 'DONE: ' . $pool['port_name'] . ': ' . $pool['range_port'] . '
    '; + } + } + r2(U . 'pool/list', 's', $log); + break; + case 'add-port-post': + $name = _post('name'); + $port_range = _post('port_range'); + $public_ip = _post('public_ip'); + $routers = _post('routers'); + run_hook('add_pool'); #HOOK + $msg = ''; + if (Validator::Length($name, 30, 2) == false) { + $msg .= 'Name should be between 3 to 30 characters' . '
    '; + } + if ($port_range == '' or $routers == '') { + $msg .= Lang::T('All field is required') . '
    '; + } + + $d = ORM::for_table('tbl_port_pool')->where('routers', $routers)->find_one(); + if ($d) { + $msg .= Lang::T('Routers already have ports, each router can only have 1 port range!') . '
    '; + } + if ($msg == '') { + $b = ORM::for_table('tbl_port_pool')->create(); + $b->public_ip = $public_ip; + $b->port_name = $name; + $b->range_port = $port_range; + $b->routers = $routers; + $b->save(); + r2(U . 'pool/port', 's', Lang::T('Data Created Successfully')); + } else { + r2(U . 'pool/add-port', 'e', $msg); + } + break; + + + case 'edit-port-post': + $name = _post('name'); + $public_ip = _post('public_ip'); + $range_port = _post('range_port'); + $routers = _post('routers'); + run_hook('edit_port'); #HOOK + $msg = ''; + $msg = ''; + if (Validator::Length($name, 30, 2) == false) { + $msg .= 'Name should be between 3 to 30 characters' . '
    '; + } + if ($range_port == '' or $routers == '') { + $msg .= Lang::T('All field is required') . '
    '; + } + + $id = _post('id'); + $d = ORM::for_table('tbl_port_pool')->find_one($id); + $old = ORM::for_table('tbl_port_pool')->find_one($id); + if (!$d) { + $msg .= Lang::T('Data Not Found') . '
    '; + } + + if ($msg == '') { + $d->port_name = $name; + $d->public_ip = $public_ip; + $d->range_port = $range_port; + $d->routers = $routers; + $d->save(); + + + + r2(U . 'pool/port', 's', Lang::T('Data Updated Successfully')); + } else { + r2(U . 'pool/edit-port/' . $id, 'e', $msg); + } break; default: diff --git a/system/controllers/services.php b/system/controllers/services.php index aaa69635..9bc32e5e 100644 --- a/system/controllers/services.php +++ b/system/controllers/services.php @@ -901,6 +901,380 @@ switch ($action) { r2(U . 'services/balance-add', 'e', $msg); } break; + case 'vpn': + $ui->assign('_title', Lang::T('VPN Plans')); + $ui->assign('xfooter', ''); + + $name = _post('name'); + $name = _req('name'); + $type1 = _req('type1'); + $type2 = _req('type2'); + $type3 = _req('type3'); + $bandwidth = _req('bandwidth'); + $valid = _req('valid'); + $device = _req('device'); + $status = _req('status'); + $router = _req('router'); + $ui->assign('type1', $type1); + $ui->assign('type2', $type2); + $ui->assign('type3', $type3); + $ui->assign('bandwidth', $bandwidth); + $ui->assign('valid', $valid); + $ui->assign('device', $device); + $ui->assign('status', $status); + $ui->assign('router', $router); + + $append_url = "&type1=" . urlencode($type1) + . "&type2=" . urlencode($type2) + . "&type3=" . urlencode($type3) + . "&bandwidth=" . urlencode($bandwidth) + . "&valid=" . urlencode($valid) + . "&device=" . urlencode($device) + . "&status=" . urlencode($status) + . "&router=" . urlencode($router); + + $bws = ORM::for_table('tbl_plans')->distinct()->select("id_bw")->where('tbl_plans.type', 'VPN')->findArray(); + $ids = array_column($bws, 'id_bw'); + if(count($ids)){ + $ui->assign('bws', ORM::for_table('tbl_bandwidth')->select("id")->select('name_bw')->where_id_in($ids)->findArray()); + }else{ + $ui->assign('bws', []); + } + $ui->assign('type2s', ORM::for_table('tbl_plans')->getEnum("plan_type")); + $ui->assign('type3s', ORM::for_table('tbl_plans')->getEnum("typebp")); + $ui->assign('valids', ORM::for_table('tbl_plans')->getEnum("validity_unit")); + $ui->assign('routers', array_column(ORM::for_table('tbl_plans')->distinct()->select("routers")->whereNotEqual('routers', '')->findArray(), 'routers')); + $devices = []; + $files = scandir($DEVICE_PATH); + foreach ($files as $file) { + $ext = pathinfo($file, PATHINFO_EXTENSION); + if ($ext == 'php') { + $devices[] = pathinfo($file, PATHINFO_FILENAME); + } + } + $ui->assign('devices', $devices); + $query = ORM::for_table('tbl_bandwidth') + ->left_outer_join('tbl_plans', array('tbl_bandwidth.id', '=', 'tbl_plans.id_bw')) + ->where('tbl_plans.type', 'VPN'); + if (!empty($type1)) { + $query->where('tbl_plans.prepaid', $type1); + } + if (!empty($type2)) { + $query->where('tbl_plans.plan_type', $type2); + } + if (!empty($type3)) { + $query->where('tbl_plans.typebp', $type3); + } + if (!empty($bandwidth)) { + $query->where('tbl_plans.id_bw', $bandwidth); + } + if (!empty($valid)) { + $query->where('tbl_plans.validity_unit', $valid); + } + if (!empty($router)) { + if ($router == 'radius') { + $query->where('tbl_plans.is_radius', '1'); + } else { + $query->where('tbl_plans.routers', $router); + } + } + if (!empty($device)) { + $query->where('tbl_plans.device', $device); + } + if (in_array($status, ['0', '1'])) { + $query->where('tbl_plans.enabled', $status); + } + if ($name != '') { + $query->where_like('tbl_plans.name_plan', '%' . $name . '%'); + } + $d = Paginator::findMany($query, ['name' => $name], 20, $append_url); + + $ui->assign('d', $d); + run_hook('view_list_vpn'); #HOOK + $ui->display('vpn.tpl'); + break; + + case 'vpn-add': + $ui->assign('_title', Lang::T('VPN Plans')); + $d = ORM::for_table('tbl_bandwidth')->find_many(); + $ui->assign('d', $d); + $r = ORM::for_table('tbl_routers')->find_many(); + $ui->assign('r', $r); + $devices = []; + $files = scandir($DEVICE_PATH); + foreach ($files as $file) { + $ext = pathinfo($file, PATHINFO_EXTENSION); + if ($ext == 'php') { + $devices[] = pathinfo($file, PATHINFO_FILENAME); + } + } + $ui->assign('devices', $devices); + run_hook('view_add_vpn'); #HOOK + $ui->display('vpn-add.tpl'); + break; + + case 'vpn-edit': + $ui->assign('_title', Lang::T('VPN Plans')); + $id = $routes['2']; + $d = ORM::for_table('tbl_plans')->find_one($id); + if ($d) { + if (empty($d['device'])) { + if ($d['is_radius']) { + $d->device = 'Radius'; + } else { + $d->device = 'MikrotikVpn'; + } + $d->save(); + } + $ui->assign('d', $d); + $p = ORM::for_table('tbl_pool')->where('routers', ($d['is_radius']) ? 'radius' : $d['routers'])->find_many(); + $ui->assign('p', $p); + $b = ORM::for_table('tbl_bandwidth')->find_many(); + $ui->assign('b', $b); + $r = []; + if ($d['is_radius']) { + $r = ORM::for_table('tbl_routers')->find_many(); + } + $ui->assign('r', $r); + $devices = []; + $files = scandir($DEVICE_PATH); + foreach ($files as $file) { + $ext = pathinfo($file, PATHINFO_EXTENSION); + if ($ext == 'php') { + $devices[] = pathinfo($file, PATHINFO_FILENAME); + } + } + $ui->assign('devices', $devices); + //select expired plan + if ($d['is_radius']) { + $exps = ORM::for_table('tbl_plans')->selects('id', 'name_plan')->where('type', 'VPN')->where("is_radius", 1)->findArray(); + } else { + $exps = ORM::for_table('tbl_plans')->selects('id', 'name_plan')->where('type', 'VPN')->where("routers", $d['routers'])->findArray(); + } + $ui->assign('exps', $exps); + run_hook('view_edit_vpn'); #HOOK + $ui->display('vpn-edit.tpl'); + } else { + r2(U . 'services/vpn', 'e', Lang::T('Account Not Found')); + } + break; + + case 'vpn-delete': + $id = $routes['2']; + + $d = ORM::for_table('tbl_plans')->find_one($id); + if ($d) { + run_hook('delete_vpn'); #HOOK + + $dvc = Package::getDevice($d); + if ($_app_stage != 'demo') { + if (file_exists($dvc)) { + require_once $dvc; + (new $d['device'])->remove_plan($d); + } else { + new Exception(Lang::T("Devices Not Found")); + } + } + $d->delete(); + + r2(U . 'services/vpn', 's', Lang::T('Data Deleted Successfully')); + } + break; + + case 'vpn-add-post': + $name = _post('name_plan'); + $plan_type = _post('plan_type'); + $radius = _post('radius'); + $id_bw = _post('id_bw'); + $price = _post('price'); + $validity = _post('validity'); + $validity_unit = _post('validity_unit'); + $routers = _post('routers'); + $device = _post('device'); + $pool = _post('pool_name'); + $enabled = _post('enabled'); + $prepaid = _post('prepaid'); + $expired_date = _post('expired_date'); + + + $msg = ''; + if (Validator::UnsignedNumber($validity) == false) { + $msg .= 'The validity must be a number' . '
    '; + } + if (Validator::UnsignedNumber($price) == false) { + $msg .= 'The price must be a number' . '
    '; + } + if ($name == '' or $id_bw == '' or $price == '' or $validity == '' or $pool == '') { + $msg .= Lang::T('All field is required') . '
    '; + } + if (empty($radius)) { + if ($routers == '') { + $msg .= Lang::T('All field is required') . '
    '; + } + } + + $d = ORM::for_table('tbl_plans')->where('name_plan', $name)->find_one(); + if ($d) { + $msg .= Lang::T('Name Plan Already Exist') . '
    '; + } + run_hook('add_vpn'); #HOOK + if ($msg == '') { + $b = ORM::for_table('tbl_bandwidth')->where('id', $id_bw)->find_one(); + if ($b['rate_down_unit'] == 'Kbps') { + $unitdown = 'K'; + $raddown = '000'; + } else { + $unitdown = 'M'; + $raddown = '000000'; + } + if ($b['rate_up_unit'] == 'Kbps') { + $unitup = 'K'; + $radup = '000'; + } else { + $unitup = 'M'; + $radup = '000000'; + } + $rate = $b['rate_up'] . $unitup . "/" . $b['rate_down'] . $unitdown; + $radiusRate = $b['rate_up'] . $radup . '/' . $b['rate_down'] . $raddown . '/' . $b['burst']; + $rate = trim($rate . " " . $b['burst']); + $d = ORM::for_table('tbl_plans')->create(); + $d->type = 'VPN'; + $d->name_plan = $name; + $d->id_bw = $id_bw; + $d->price = $price; + $d->plan_type = $plan_type; + $d->validity = $validity; + $d->validity_unit = $validity_unit; + $d->pool = $pool; + if (!empty($radius)) { + $d->is_radius = 1; + $d->routers = ''; + } else { + $d->is_radius = 0; + $d->routers = $routers; + } + if ($prepaid == 'no') { + if ($expired_date > 28 && $expired_date < 1) { + $expired_date = 20; + } + $d->expired_date = $expired_date; + } else { + $d->expired_date = 0; + } + $d->enabled = $enabled; + $d->prepaid = $prepaid; + $d->device = $device; + $d->save(); + + $dvc = Package::getDevice($d); + if ($_app_stage != 'demo') { + if (file_exists($dvc)) { + require_once $dvc; + (new $d['device'])->add_plan($d); + } else { + new Exception(Lang::T("Devices Not Found")); + } + } + r2(U . 'services/vpn', 's', Lang::T('Data Created Successfully')); + } else { + r2(U . 'services/vpn-add', 'e', $msg); + } + break; + + case 'edit-vpn-post': + $id = _post('id'); + $plan_type = _post('plan_type'); + $name = _post('name_plan'); + $id_bw = _post('id_bw'); + $price = _post('price'); + $validity = _post('validity'); + $validity_unit = _post('validity_unit'); + $routers = _post('routers'); + $device = _post('device'); + $pool = _post('pool_name'); + $plan_expired = _post('plan_expired'); + $enabled = _post('enabled'); + $prepaid = _post('prepaid'); + $expired_date = _post('expired_date'); + $on_login = _post('on_login'); + $on_logout = _post('on_logout'); + + $msg = ''; + if (Validator::UnsignedNumber($validity) == false) { + $msg .= 'The validity must be a number' . '
    '; + } + if (Validator::UnsignedNumber($price) == false) { + $msg .= 'The price must be a number' . '
    '; + } + if ($name == '' or $id_bw == '' or $price == '' or $validity == '' or $pool == '') { + $msg .= Lang::T('All field is required') . '
    '; + } + + $d = ORM::for_table('tbl_plans')->where('id', $id)->find_one(); + $old = ORM::for_table('tbl_plans')->where('id', $id)->find_one(); + if ($d) { + } else { + $msg .= Lang::T('Data Not Found') . '
    '; + } + run_hook('edit_vpn'); #HOOK + if ($msg == '') { + $b = ORM::for_table('tbl_bandwidth')->where('id', $id_bw)->find_one(); + if ($b['rate_down_unit'] == 'Kbps') { + $unitdown = 'K'; + $raddown = '000'; + } else { + $unitdown = 'M'; + $raddown = '000000'; + } + if ($b['rate_up_unit'] == 'Kbps') { + $unitup = 'K'; + $radup = '000'; + } else { + $unitup = 'M'; + $radup = '000000'; + } + $rate = $b['rate_up'] . $unitup . "/" . $b['rate_down'] . $unitdown; + $radiusRate = $b['rate_up'] . $radup . '/' . $b['rate_down'] . $raddown . '/' . $b['burst']; + $rate = trim($rate . " " . $b['burst']); + + $d->name_plan = $name; + $d->id_bw = $id_bw; + $d->price = $price; + $d->plan_type = $plan_type; + $d->validity = $validity; + $d->validity_unit = $validity_unit; + $d->routers = $routers; + $d->pool = $pool; + $d->plan_expired = $plan_expired; + $d->enabled = $enabled; + $d->prepaid = $prepaid; + $d->device = $device; + $d->on_login = $on_login; + $d->on_logout = $on_logout; + if ($prepaid == 'no') { + if ($expired_date > 28 && $expired_date < 1) { + $expired_date = 20; + } + $d->expired_date = $expired_date; + } else { + $d->expired_date = 0; + } + $d->save(); + + $dvc = Package::getDevice($d); + if ($_app_stage != 'demo') { + if (file_exists($dvc)) { + require_once $dvc; + (new $d['device'])->update_plan($old, $d); + } else { + new Exception(Lang::T("Devices Not Found")); + } + } + r2(U . 'services/vpn', 's', Lang::T('Data Updated Successfully')); + } else { + r2(U . 'services/vpn-edit/' . $id, 'e', $msg); + } + break; default: $ui->display('a404.tpl'); } diff --git a/system/controllers/settings.php b/system/controllers/settings.php index 33e4abe9..96cb497b 100644 --- a/system/controllers/settings.php +++ b/system/controllers/settings.php @@ -295,6 +295,16 @@ switch ($action) { $d->value = _post('pppoe_plan'); $d->save(); } + $d = ORM::for_table('tbl_appconfig')->where('setting', 'vpn_plan')->find_one(); + if ($d) { + $d->value = _post('vpn_plan'); + $d->save(); + } else { + $d = ORM::for_table('tbl_appconfig')->create(); + $d->setting = 'vpn_plan'; + $d->value = _post('vpn_plan'); + $d->save(); + } $currency_code = $_POST['currency_code']; $d = ORM::for_table('tbl_appconfig')->where('setting', 'currency_code')->find_one(); diff --git a/system/updates.json b/system/updates.json index bce2f4ef..8d66fc0c 100644 --- a/system/updates.json +++ b/system/updates.json @@ -155,5 +155,11 @@ "2024.8.28" : [ "ALTER TABLE `tbl_routers` ADD `status` ENUM('Online', 'Offline') DEFAULT 'Online' AFTER `coordinates`;", "ALTER TABLE `tbl_routers` ADD `last_seen` DATETIME AFTER `status`;" + ], + "2024.9.13" : [ + "ALTER TABLE `tbl_plans` CHANGE `type` `type` ENUM('Hotspot','PPPOE','VPN','Balance') CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL;", + "ALTER TABLE `tbl_customers` CHANGE `service_type` `service_type` ENUM('Hotspot','PPPoE','VPN','Others') CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT 'Others' COMMENT 'For selecting user type';", + "ALTER TABLE `tbl_transactions` CHANGE `type` `type` ENUM('Hotspot','PPPOE','VPN','Balance') CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL;", + "CREATE TABLE IF NOT EXISTS `tbl_port_pool` ( `id` int(10) NOT NULL AUTO_INCREMENT , `public_ip` varchar(40) NOT NULL, `port_name` varchar(40) NOT NULL, `range_port` varchar(40) NOT NULL, `routers` varchar(40) NOT NULL, PRIMARY KEY (`id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;" ] } \ No newline at end of file diff --git a/ui/ui/app-localisation.tpl b/ui/ui/app-localisation.tpl index 936c3abb..571d5588 100644 --- a/ui/ui/app-localisation.tpl +++ b/ui/ui/app-localisation.tpl @@ -128,6 +128,14 @@
    {Lang::T('Change title in user Plan order')}
    +
    + +
    + +
    + {Lang::T('Change title in user Plan order')} +
    diff --git a/ui/ui/customers-edit.tpl b/ui/ui/customers-edit.tpl index e1ce53f8..0ed074b4 100644 --- a/ui/ui/customers-edit.tpl +++ b/ui/ui/customers-edit.tpl @@ -75,6 +75,7 @@ +
    diff --git a/ui/ui/plan.tpl b/ui/ui/plan.tpl index 3cca5861..32111f4a 100644 --- a/ui/ui/plan.tpl +++ b/ui/ui/plan.tpl @@ -95,9 +95,13 @@ {/if} {if $ds['type'] == 'Hotspot'} - {$ds['namebp']} - {else} - {$ds['namebp']} + {$ds['namebp']} + {/if} + {if $ds['type'] == 'PPPOE'} + {$ds['namebp']} + {/if} + {if $ds['type'] == 'VPN'} + {$ds['namebp']} {/if} {$ds['type']} {Lang::dateAndTimeFormat($ds['recharged_on'],$ds['recharged_time'])} diff --git a/ui/ui/port-add.tpl b/ui/ui/port-add.tpl new file mode 100644 index 00000000..b689a896 --- /dev/null +++ b/ui/ui/port-add.tpl @@ -0,0 +1,51 @@ +{include file="sections/header.tpl"} + +
    +
    +
    +
    {Lang::T('Add Port Pool')}
    +
    + +
    +
    + +
    + +
    +
    +
    + +
    + +
    +
    +
    + +
    + +
    +
    +
    + +
    + +
    +
    +
    +
    + + Or {Lang::T('Cancel')} +
    +
    +
    + +
    +
    +
    +
    + +{include file="sections/footer.tpl"} diff --git a/ui/ui/port-edit.tpl b/ui/ui/port-edit.tpl new file mode 100644 index 00000000..46413314 --- /dev/null +++ b/ui/ui/port-edit.tpl @@ -0,0 +1,49 @@ +{include file="sections/header.tpl"} + +
    +
    +
    +
    {Lang::T('Edit Port')}
    +
    + +
    + +
    + +
    + +
    +
    +
    + +
    + +
    +
    +
    + +
    + +
    +
    +
    + +
    + +
    +
    + +
    +
    + + Or {Lang::T('Cancel')} +
    +
    +
    + +
    +
    +
    +
    + +{include file="sections/footer.tpl"} diff --git a/ui/ui/port.tpl b/ui/ui/port.tpl new file mode 100644 index 00000000..77fd2661 --- /dev/null +++ b/ui/ui/port.tpl @@ -0,0 +1,76 @@ +{include file="sections/header.tpl"} + +
    +
    +
    +
    +
    + sync +
    + {Lang::T('Port Pool')} - VPN Tunnels +
    +
    +
    +
    + +
    +   +
    +
    + + + + + + + + + + + + + {foreach $d as $ds} + + + + + + + + + {/foreach} + +
    {Lang::T('Port Name')}{Lang::T('Public IP')}{Lang::T('Range Port')}{Lang::T('Routers')}{Lang::T('Manage')}ID
    {$ds['port_name']}{$ds['public_ip']}{$ds['range_port']}{$ds['routers']} + {Lang::T('Edit')} + + {$ds['id']}
    +
    + {include file="pagination.tpl"} +
    +

    {Lang::T('Create expired Internet Plan')}

    +

    {Lang::T('When customer expired, you can move it to Expired Internet Plan')}

    +
    +
    +
    +
    +
    + +{include file="sections/footer.tpl"} diff --git a/ui/ui/recharge.tpl b/ui/ui/recharge.tpl index b896ab50..96370d58 100644 --- a/ui/ui/recharge.tpl +++ b/ui/ui/recharge.tpl @@ -22,6 +22,7 @@
    +
    diff --git a/ui/ui/scripts/custom.js b/ui/ui/scripts/custom.js index 844f5ffc..87734583 100644 --- a/ui/ui/scripts/custom.js +++ b/ui/ui/scripts/custom.js @@ -96,7 +96,7 @@ $(function() { }); }; - }else{ + } else if ($('#POE').is(':checked')) { $.ajax({ type: "POST", dataType: "html", @@ -117,6 +117,27 @@ $(function() { } }); }); + } else { + $.ajax({ + type: "POST", + dataType: "html", + url: "index.php?_route=autoload/server", + success: function(msg){ + $("#server").html(msg); + } + }); + $("#server").change(function(){ + var server = $("#server").val(); + $.ajax({ + type: "POST", + dataType: "html", + url: "index.php?_route=autoload/plan", + data: "jenis=VPN&server="+server, + success: function(msg){ + $("#plan").html(msg); + } + }); + }); } }); }); diff --git a/ui/ui/sections/header.tpl b/ui/ui/sections/header.tpl index 34b7f1e9..bb5f8525 100644 --- a/ui/ui/sections/header.tpl +++ b/ui/ui/sections/header.tpl @@ -1283,6 +1283,8 @@ href="{$_url}services/hotspot">Hotspot
  • PPPOE
  • +
  • VPN
  • Bandwidth
  • {if $_c['enable_balance'] == 'yes'} @@ -1341,6 +1343,8 @@ href="{$_url}routers">Routers
  • IP Pool
  • +
  • Port Pool
  • {Lang::T('Routers Maps')}
  • {$_MENU_NETWORK} diff --git a/ui/ui/user-ui/dashboard.tpl b/ui/ui/user-ui/dashboard.tpl index 361e6487..65e24c39 100644 --- a/ui/ui/user-ui/dashboard.tpl +++ b/ui/ui/user-ui/dashboard.tpl @@ -88,6 +88,8 @@ Hotspot {elseif $_user.service_type == 'PPPoE'} PPPoE + {elseif $_user.service_type == 'VPN'} + VPN {elseif $_user.service_type == 'Others' || $_user.service_type == null} Others {/if} @@ -165,8 +167,10 @@
    {if $_bill['type'] == 'Hotspot'} {if $_c['hotspot_plan']==''}Hotspot Plan{else}{$_c['hotspot_plan']}{/if} - {else} + {else if $_bill['type'] == 'PPPOE'} {if $_c['pppoe_plan']==''}PPPOE Plan{else}{$_c['pppoe_plan']}{/if} + {else if $_bill['type'] == 'VPN'} + {if $_c['pppoe_plan']==''}VPN Plan{else}{$_c['vpn_plan']}{/if} {/if}
    @@ -215,6 +219,25 @@ {$_bill['plan_type']} + {if $_bill['type'] == 'VPN' && $_bill['routers'] == $vpn['routers']} + + {Lang::T('Public IP')} + {$vpn['public_ip']} / {$vpn['port_name']} + + + {Lang::T('Private IP')} + {$_user['pppoe_ip']} + + {foreach $cf as $tcf} + + {if $tcf['field_name'] == 'Winbox' or $tcf['field_name'] == 'Api' or $tcf['field_name'] == 'Web'} + {$tcf['field_name']} - Port + {$tcf['field_value']} + + {/if} + {/foreach} + {/if} + {if $nux_ip neq ''} {Lang::T('Current IP')} diff --git a/ui/ui/user-ui/orderPlan.tpl b/ui/ui/user-ui/orderPlan.tpl index f79ed4dd..9db514ff 100644 --- a/ui/ui/user-ui/orderPlan.tpl +++ b/ui/ui/user-ui/orderPlan.tpl @@ -226,6 +226,7 @@ {/if} {foreach $routers as $router} {if Validator::isRouterHasPlan($plans_hotspot, $router['name']) || Validator::isRouterHasPlan($plans_pppoe, + $router['name']) || Validator::isRouterHasPlan($plans_vpn, $router['name'])}
    {$router['name']}
    @@ -338,9 +339,62 @@ {/if} {/foreach}
    + {/if} + {if $_user['service_type'] == 'VPN' && Validator::countRouterPlan($plans_vpn,$router['name'])>0} +
    {if $_c['vpn_plan']==''}VPN Plan{else}{$_c['vpn_plan']}{/if}
    +
    + {foreach $plans_vpn as $plan} + {if $router['name'] eq $plan['routers']} +
    +
    +
    {$plan['name_plan']}
    +
    +
    + + + + + + + + + + + + + + + +
    {Lang::T('Type')}{$plan['type']}
    {Lang::T('Price')}{Lang::moneyFormat($plan['price'])}
    {Lang::T('Validity')}{$plan['validity']} {$plan['validity_unit']}
    +
    +
    +
    +
    + {Lang::T('Buy')} + {if $_c['enable_balance'] == 'yes' && $_user['balance']>=$plan['price']} + {Lang::T('Pay With Balance')} + {/if} +
    + {if $_c['enable_balance'] == 'yes' && $_c['allow_balance_transfer'] == 'yes' && + $_user['balance']>=$plan['price']} + {Lang::T('Buy for friend')} + {/if} +
    +
    +
    + {/if} + {/foreach} +
    {/if} {if $_user['service_type'] == 'Others' || $_user['service_type'] == '' && (Validator::countRouterPlan($plans_hotspot, $router['name'])>0 || Validator::countRouterPlan($plans_pppoe, + $router['name'])>0 || Validator::countRouterPlan($plans_vpn, $router['name'])>0)}
    {if $_c['hotspot_plan']==''}Hotspot Plan{else}{$_c['hotspot_plan']}{/if}
    @@ -443,6 +497,56 @@ {/if} {/foreach} +
    {if $_c['vpn_plan']==''}VPN Plan{else}{$_c['vpn_plan']}{/if}
    +
    + {foreach $plans_vpn as $plan} + {if $router['name'] eq $plan['routers']} +
    +
    +
    {$plan['name_plan']}
    +
    +
    + + + + + + + + + + + + + + + +
    {Lang::T('Type')}{$plan['type']}
    {Lang::T('Price')}{Lang::moneyFormat($plan['price'])}
    {Lang::T('Validity')}{$plan['validity']} {$plan['validity_unit']}
    +
    +
    +
    +
    + {Lang::T('Buy')} + {if $_c['enable_balance'] == 'yes' && $_user['balance']>=$plan['price']} + {Lang::T('Pay With Balance')} + {/if} +
    + {if $_c['enable_balance'] == 'yes' && $_c['allow_balance_transfer'] == 'yes' && + $_user['balance']>=$plan['price']} + {Lang::T('Buy for friend')} + {/if} +
    +
    +
    + {/if} + {/foreach} +
    {/if} {/if} diff --git a/ui/ui/vpn-add.tpl b/ui/ui/vpn-add.tpl new file mode 100644 index 00000000..ae26a8ac --- /dev/null +++ b/ui/ui/vpn-add.tpl @@ -0,0 +1,188 @@ +{include file="sections/header.tpl"} + +
    +
    +
    +
    {Lang::T('Add Service Plan')}
    +
    +
    +
    + +
    + {Lang::T('Enable')} + {Lang::T('Disable')} +
    +
    +
    + +
    + {Lang::T('Prepaid')} + {Lang::T('Postpaid')} +
    +
    +
    + +
    + {Lang::T('Personal')} + {Lang::T('Business')} +
    +
    +
    + +
    + +
    +
    +
    + +
    + +
    +
    +
    + +
    + +
    +
    +
    + +
    +
    + {$_c['currency_code']} + +
    +
    + {if $_c['enable_tax'] == 'yes'} + {if $_c['tax_rate'] == 'custom'} +

    {number_format($_c['custom_tax_rate'], 2)} % {Lang::T('Tax Rates + will be added')}

    + {else} +

    {number_format($_c['tax_rate'] * 100, 2)} % {Lang::T('Tax Rates + will be added')}

    + {/if} + {/if} +
    +
    + +
    + +
    +
    + +
    +

    {Lang::T('1 Period = 1 Month, Expires the 20th of each month')} +

    +
    + +
    + +
    + +

    {Lang::T('Cannot be change after saved')}

    +
    +
    +
    + +
    + +
    +
    +
    +
    + + Or {Lang::T('Cancel')} +
    +
    +
    +
    +
    +
    +
    + +{if $_c['radius_enable']} + {literal} + + {/literal} +{/if} +{include file="sections/footer.tpl"} diff --git a/ui/ui/vpn-edit.tpl b/ui/ui/vpn-edit.tpl new file mode 100644 index 00000000..53428605 --- /dev/null +++ b/ui/ui/vpn-edit.tpl @@ -0,0 +1,255 @@ +{include file="sections/header.tpl"} + +
    +
    +
    +
    +
    {Lang::T('Edit Service Plan')} || {$d['name_plan']}
    +
    + +
    + +
    + {Lang::T('Enable')} + {Lang::T('Disable')} +
    +
    +
    + +
    + + {Lang::T('Prepaid')} + {Lang::T('Postpaid')} +
    +
    +
    + +
    + + {Lang::T('Personal')} + {Lang::T('Business')} +
    +
    + {if $_c['radius_enable'] and $d['is_radius']} +
    + +
    + +
    +
    + {/if} +
    + +
    + +
    +
    +
    + +
    + +
    +
    +
    + +
    + +
    +
    +
    + +
    +
    + {$_c['currency_code']} + +
    +
    + {if $_c['enable_tax'] == 'yes'} + {if $_c['tax_rate'] == 'custom'} +

    {number_format($_c['custom_tax_rate'], 2)} % {Lang::T('Tax Rates + will be added')}

    + {else} +

    {number_format($_c['tax_rate'] * 100, 2)} % {Lang::T('Tax Rates + will be added')}

    + {/if} + {/if} + +
    +
    + +
    + +
    +
    + +

    {Lang::T('1 Period = 1 Month, Expires the 20th of each month')}

    +
    + +
    +
    + +
    + +
    +
    +
    + +
    + +
    +
    +
    + +
    + +
    +
    + {Lang::T('Expired Action')} {Lang::T('Optional')} +
    + +
    + +

    + {Lang::T('When Expired, customer will be move to selected internet plan')}

    +
    +
    +
    +
    +
    + {if !$d['is_radius']} +
    +
    +
    {Lang::T('on-login / on-up')}
    +
    + +
    +
    +
    +
    {Lang::T('on-logout / on-down')}
    +
    + +
    +
    +
    + {/if} +
    +
    +
    + + Or {Lang::T('Cancel')} +
    +
    +
    + + + + + + + + + + + + + + +{include file="sections/footer.tpl"} diff --git a/ui/ui/vpn.tpl b/ui/ui/vpn.tpl new file mode 100644 index 00000000..6047e446 --- /dev/null +++ b/ui/ui/vpn.tpl @@ -0,0 +1,179 @@ +{include file="sections/header.tpl"} + +
    +
    +
    +
    +
    + sync +
    {Lang::T('VPN Package')} +
    + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + {foreach $d as $ds} + + + + + + + + + + + + + + + {/foreach} + +
    {Lang::T('Internet Plan')} + {Lang::T('Expired')}
    {Lang::T('Name')}{Lang::T('Type')}{Lang::T('Bandwidth')}{Lang::T('Price')}{Lang::T('Validity')}{Lang::T('IP Pool')}{Lang::T('Internet Plan')}{Lang::T('Date')}{Lang::T('Location')}{Lang::T('Device')}{Lang::T('Manage')}ID
    {$ds['name_plan']}{$ds['plan_type']} {if $ds['prepaid'] != 'yes'}{Lang::T('Postpaid')}{else}{Lang::T('Prepaid')}{/if}{$ds['name_bw']}{Lang::moneyFormat($ds['price'])}{$ds['validity']} {$ds['validity_unit']}{$ds['pool']}{if $ds['plan_expired']}{Lang::T('Yes')}{else}{Lang::T('No')} + {/if}{if $ds['prepaid'] == no}{$ds['expired_date']}{/if} + {if $ds['is_radius']} + RADIUS + {else} + {if $ds['routers']!=''} + {$ds['routers']} + {/if} + {/if} + {$ds['device']} + {Lang::T('Edit')} + + {$ds['id']}
    +
    + +
    +
    +
    + +{include file="sections/footer.tpl"} From f5d9649f97e512751dbcb1eec8c1c40925c31fde Mon Sep 17 00:00:00 2001 From: AGSTR <144728914+agstrxyz@users.noreply.github.com> Date: Fri, 13 Sep 2024 00:46:40 +0700 Subject: [PATCH 309/841] Add files via upload --- system/devices/MikrotikVpn.php | 504 +++++++++++++++++++++++++++++++++ 1 file changed, 504 insertions(+) create mode 100644 system/devices/MikrotikVpn.php diff --git a/system/devices/MikrotikVpn.php b/system/devices/MikrotikVpn.php new file mode 100644 index 00000000..6edeed2c --- /dev/null +++ b/system/devices/MikrotikVpn.php @@ -0,0 +1,504 @@ + 'Mikrotik Vpn', + 'description' => 'To handle connection between PHPNuxBill with Mikrotik VPN', + 'author' => 'agstr', + 'url' => [ + 'Github' => 'https://github.com/agstrxyz', + 'Telegram' => 'https://t.me/agstrxyz', + 'Youtube' => 'https://www.youtube.com/@agstrxyz', + 'Donate' => 'https://paypal.me/ibnux' + ] + ]; + } + + function add_customer($customer, $plan) + { + global $isChangePlan; + $mikrotik = $this->info($plan['routers']); + $client = $this->getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']); + $cid = self::getIdByCustomer($customer, $client); + if (empty($cid)) { + $this->addVpnUser($client, $plan, $customer); + }else{ + $setRequest = new RouterOS\Request('/ppp/secret/set'); + $setRequest->setArgument('numbers', $cid); + if (!empty($customer['pppoe_password'])) { + $setRequest->setArgument('password', $customer['pppoe_password']); + } else { + $setRequest->setArgument('password', $customer['password']); + } + if (!empty($customer['pppoe_username'])) { + $setRequest->setArgument('name', $customer['pppoe_username']); + } else { + $setRequest->setArgument('name', $customer['username']); + } + if (!empty($customer['pppoe_ip'])) { + $setRequest->setArgument('remote-address', $customer['pppoe_ip']); + }else{ + $setRequest->setArgument('remote-address', '0.0.0.0'); + } + $setRequest->setArgument('profile', $plan['name_plan']); + $setRequest->setArgument('comment', $customer['fullname'] . ' | ' . $customer['email'] . ' | ' . implode(', ', User::getBillNames($customer['id']))); + $client->sendSync($setRequest); + if(isset($isChangePlan) && $isChangePlan){ + $this->removeVpnActive($client, $customer['username']); + if (!empty($customer['pppoe_username'])) { + $this->removeVpnActive($client, $customer['pppoe_username']); + } + } + } + } + + function remove_customer($customer, $plan) + { + $mikrotik = $this->info($plan['routers']); + $client = $this->getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']); + if (!empty($plan['plan_expired'])) { + $p = ORM::for_table("tbl_plans")->find_one($plan['plan_expired']); + if($p){ + $this->add_customer($customer, $p); + $this->removeVpnActive($client, $customer['username']); + if (!empty($customer['pppoe_username'])) { + $this->removeVpnActive($client, $customer['pppoe_username']); + } + return; + } + } + $this->removeVpnUser($client, $customer['username'], $customer['id']); + if (!empty($customer['pppoe_username'])) { + $this->removeVpnUser($client, $customer['pppoe_username'], $customer['id']); + } + $this->removeVpnActive($client, $customer['username']); + if (!empty($customer['pppoe_username'])) { + $this->removeVpnActive($client, $customer['pppoe_username']); + } + } + + public function change_username($plan, $from, $to) + { + $mikrotik = $this->info($plan['routers']); + $client = $this->getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']); + $printRequest = new RouterOS\Request('/ppp/secret/print'); + $printRequest->setQuery(RouterOS\Query::where('name', $from)); + $cid = $client->sendSync($printRequest)->getProperty('.id'); + if (!empty($cid)) { + $setRequest = new RouterOS\Request('/ppp/secret/set'); + $setRequest->setArgument('numbers', $cid); + $setRequest->setArgument('name', $to); + $client->sendSync($setRequest); + $this->removeVpnActive($client, $from); + } + } + + function add_plan($plan) + { + $mikrotik = $this->info($plan['routers']); + $client = $this->getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']); + + + $bw = ORM::for_table("tbl_bandwidth")->find_one($plan['id_bw']); + if ($bw['rate_down_unit'] == 'Kbps') { + $unitdown = 'K'; + } else { + $unitdown = 'M'; + } + if ($bw['rate_up_unit'] == 'Kbps') { + $unitup = 'K'; + } else { + $unitup = 'M'; + } + $rate = $bw['rate_up'] . $unitup . "/" . $bw['rate_down'] . $unitdown; + if(!empty(trim($bw['burst']))){ + $rate .= ' '.$bw['burst']; + } + $pool = ORM::for_table("tbl_pool")->where("pool_name", $plan['pool'])->find_one(); + $addRequest = new RouterOS\Request('/ppp/profile/add'); + $client->sendSync( + $addRequest + ->setArgument('name', $plan['name_plan']) + ->setArgument('local-address', (!empty($pool['local_ip'])) ? $pool['local_ip']: $pool['pool_name']) + ->setArgument('remote-address', $pool['pool_name']) + ->setArgument('rate-limit', $rate) + ); + } + + + function getIdByCustomer($customer, $client){ + $printRequest = new RouterOS\Request('/ppp/secret/print'); + $printRequest->setQuery(RouterOS\Query::where('name', $customer['username'])); + $id = $client->sendSync($printRequest)->getProperty('.id'); + if(empty($id)){ + if (!empty($customer['pppoe_username'])) { + $printRequest = new RouterOS\Request('/ppp/secret/print'); + $printRequest->setQuery(RouterOS\Query::where('name', $customer['pppoe_username'])); + $id = $client->sendSync($printRequest)->getProperty('.id'); + } + } + return $id; + } + + function update_plan($old_name, $new_plan) + { + $mikrotik = $this->info($new_plan['routers']); + $client = $this->getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']); + + $printRequest = new RouterOS\Request( + '/ppp profile print .proplist=.id', + RouterOS\Query::where('name', $old_name['name_plan']) + ); + $profileID = $client->sendSync($printRequest)->getProperty('.id'); + if (empty($profileID)) { + $this->add_plan($new_plan); + } else { + $bw = ORM::for_table("tbl_bandwidth")->find_one($new_plan['id_bw']); + if ($bw['rate_down_unit'] == 'Kbps') { + $unitdown = 'K'; + } else { + $unitdown = 'M'; + } + if ($bw['rate_up_unit'] == 'Kbps') { + $unitup = 'K'; + } else { + $unitup = 'M'; + } + $rate = $bw['rate_up'] . $unitup . "/" . $bw['rate_down'] . $unitdown; + if(!empty(trim($bw['burst']))){ + $rate .= ' '.$bw['burst']; + } + $pool = ORM::for_table("tbl_pool")->where("pool_name", $new_plan['pool'])->find_one(); + $setRequest = new RouterOS\Request('/ppp/profile/set'); + $client->sendSync( + $setRequest + ->setArgument('numbers', $profileID) + ->setArgument('local-address', (!empty($pool['local_ip'])) ? $pool['local_ip']: $pool['pool_name']) + ->setArgument('remote-address', $pool['pool_name']) + ->setArgument('rate-limit', $rate) + ->setArgument('on-up', $new_plan['on_login']) + ->setArgument('on-down', $new_plan['on_logout']) + ); + } + } + + function remove_plan($plan) + { + $mikrotik = $this->info($plan['routers']); + $client = $this->getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']); + $printRequest = new RouterOS\Request( + '/ppp profile print .proplist=.id', + RouterOS\Query::where('name', $plan['name_plan']) + ); + $profileID = $client->sendSync($printRequest)->getProperty('.id'); + + $removeRequest = new RouterOS\Request('/ppp/profile/remove'); + $client->sendSync( + $removeRequest + ->setArgument('numbers', $profileID) + ); + } + + function add_pool($pool){ + global $_app_stage; + if ($_app_stage == 'demo') { + return null; + } + $mikrotik = $this->info($pool['routers']); + $client = $this->getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']); + $addRequest = new RouterOS\Request('/ip/pool/add'); + $client->sendSync( + $addRequest + ->setArgument('name', $pool['pool_name']) + ->setArgument('ranges', $pool['range_ip']) + ); + } + + function update_pool($old_pool, $new_pool){ + global $_app_stage; + if ($_app_stage == 'demo') { + return null; + } + $mikrotik = $this->info($new_pool['routers']); + $client = $this->getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']); + $printRequest = new RouterOS\Request( + '/ip pool print .proplist=.id', + RouterOS\Query::where('name', $old_pool['pool_name']) + ); + $poolID = $client->sendSync($printRequest)->getProperty('.id'); + if (empty($poolID)) { + $this->add_pool($new_pool); + } else { + $setRequest = new RouterOS\Request('/ip/pool/set'); + $client->sendSync( + $setRequest + ->setArgument('numbers', $poolID) + ->setArgument('name', $new_pool['pool_name']) + ->setArgument('ranges', $new_pool['range_ip']) + ); + } + } + + function remove_pool($pool){ + global $_app_stage; + if ($_app_stage == 'demo') { + return null; + } + $mikrotik = $this->info($pool['routers']); + $client = $this->getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']); + $printRequest = new RouterOS\Request( + '/ip pool print .proplist=.id', + RouterOS\Query::where('name', $pool['pool_name']) + ); + $poolID = $client->sendSync($printRequest)->getProperty('.id'); + $removeRequest = new RouterOS\Request('/ip/pool/remove'); + $client->sendSync( + $removeRequest + ->setArgument('numbers', $poolID) + ); + } + + + function online_customer($customer, $router_name) + { + $mikrotik = $this->info($router_name); + $client = $this->getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']); + $printRequest = new RouterOS\Request( + '/ppp active print', + RouterOS\Query::where('user', $customer['username']) + ); + return $client->sendSync($printRequest)->getProperty('.id'); + } + + function info($name) + { + return ORM::for_table('tbl_routers')->where('name', $name)->find_one(); + } + + function getClient($ip, $user, $pass) + { + global $_app_stage; + if ($_app_stage == 'demo') { + return null; + } + $iport = explode(":", $ip); + return new RouterOS\Client($iport[0], $user, $pass, ($iport[1]) ? $iport[1] : null); + } + + function removeVpnUser($client, $username, $cstid) + { + global $_app_stage; + if ($_app_stage == 'demo') { + return null; + } + $printRequest = new RouterOS\Request('/ppp/secret/print'); + //$printRequest->setArgument('.proplist', '.id'); + $printRequest->setQuery(RouterOS\Query::where('name', $username)); + $id = $client->sendSync($printRequest)->getProperty('.id'); + $removeRequest = new RouterOS\Request('/ppp/secret/remove'); + $removeRequest->setArgument('numbers', $id); + $client->sendSync($removeRequest); + $this->rmNat($client, $cstid); + } + + function addVpnUser($client, $plan, $customer) + { + $setRequest = new RouterOS\Request('/ppp/secret/add'); + $setRequest->setArgument('service', 'any'); + $setRequest->setArgument('profile', $plan['name_plan']); + $setRequest->setArgument('comment', $customer['fullname'] . ' | ' . $customer['email'] . ' | ' . implode(', ', User::getBillNames($customer['id']))); + if (!empty($customer['pppoe_password'])) { + $setRequest->setArgument('password', $customer['pppoe_password']); + } else { + $setRequest->setArgument('password', $customer['password']); + } + if (!empty($customer['pppoe_username'])) { + $setRequest->setArgument('name', $customer['pppoe_username']); + } else { + $setRequest->setArgument('name', $customer['username']); + } + if (!empty($customer['pppoe_ip'])) { + $ips = $customer['pppoe_ip']; + $setRequest->setArgument('remote-address', $customer['pppoe_ip']); + } else { + $ips = $this->checkIpAddr($plan['pool'], $customer['id']); + $setRequest->setArgument('remote-address', $ips); + + } + $this->addNat($client, $plan, $customer, $ips); + $client->sendSync($setRequest); + $customer->service_type = 'VPN'; + $customer->pppoe_ip = $ips; + $customer->save(); + } + + function removeVpnActive($client, $username) + { + global $_app_stage; + if ($_app_stage == 'demo') { + return null; + } + $onlineRequest = new RouterOS\Request('/ppp/active/print'); + $onlineRequest->setArgument('.proplist', '.id'); + $onlineRequest->setQuery(RouterOS\Query::where('name', $username)); + $id = $client->sendSync($onlineRequest)->getProperty('.id'); + + $removeRequest = new RouterOS\Request('/ppp/active/remove'); + $removeRequest->setArgument('numbers', $id); + $client->sendSync($removeRequest); + } + + + function addIpToAddressList($client, $ip, $listName, $comment = '') + { + global $_app_stage; + if ($_app_stage == 'demo') { + return null; + } + $addRequest = new RouterOS\Request('/ip/firewall/address-list/add'); + $client->sendSync( + $addRequest + ->setArgument('address', $ip) + ->setArgument('comment', $comment) + ->setArgument('list', $listName) + ); + + } + + function removeIpFromAddressList($client, $ip) + { + global $_app_stage; + if ($_app_stage == 'demo') { + return null; + } + $printRequest = new RouterOS\Request( + '/ip firewall address-list print .proplist=.id', + RouterOS\Query::where('address', $ip) + ); + $id = $client->sendSync($printRequest)->getProperty('.id'); + $removeRequest = new RouterOS\Request('/ip/firewall/address-list/remove'); + $client->sendSync( + $removeRequest + ->setArgument('numbers', $id) + ); + } + + function addNat($client, $plan, $cust, $ips) + { + global $_app_stage; + if ($_app_stage == 'demo') { + return null; + } + $this->checkPort($cust['id'], 'Winbox', $plan['routers']); + $this->checkPort($cust['id'], 'Api', $plan['routers']); + $this->checkPort($cust['id'], 'Web', $plan['routers']); + $tcf = ORM::for_table('tbl_customers_fields') + ->where('customer_id', $cust['id']) + ->find_many(); + + foreach ($tcf as $cf) { + $dst = $cf['field_value']; + $cmnt = $cf['field_name']; + if ($cmnt == 'Winbox') { + $tp = '8291'; } + if ($cmnt == 'Web') { + $tp = '80'; } + if ($cmnt == 'Api') { + $tp = '8728'; } + if ($cmnt == 'Winbox' || $cmnt == 'Web' || $cmnt == 'Api') { + $addRequest = new RouterOS\Request('/ip/firewall/nat/add'); + $client->sendSync( + $addRequest + ->setArgument('chain', 'dstnat') + ->setArgument('protocol', 'tcp') + ->setArgument('dst-port', $dst) + ->setArgument('action', 'dst-nat') + ->setArgument('to-addresses', $ips) + ->setArgument('to-ports', $tp) + ->setArgument('address', $ip) + ->setArgument('comment', $cmnt.' || '.$cust['username']) + ); + } + } + } + + function rmNat($client, $cstid) + { + global $_app_stage; + if ($_app_stage == 'demo') { + return null; + } + $tcf = ORM::for_table('tbl_customers_fields') + ->where('customer_id', $cstid) + ->find_many(); + $cst = ORM::for_table('tbl_customers')->find_one($cstid); + $printRequest = new RouterOS\Request('/ip/firewall/nat/print'); + $printRequest->setQuery(RouterOS\Query::where('to-addresses', $cst['pppoe_ip'])); + $nats = $client->sendSync($printRequest); + foreach ($nats as $nat) { + $id = $client->sendSync($printRequest)->getProperty('.id'); + $removeRequest = new RouterOS\Request('/ip/firewall/nat/remove'); + $removeRequest->setArgument('numbers', $id); + $client->sendSync($removeRequest); + } + } + + + function checkPort($id, $portn, $router) + { + $tcf = ORM::for_table('tbl_customers_fields') + ->where('customer_id', $id) + ->where('field_name', $portn) + ->find_one(); + $ports = ORM::for_table('tbl_port_pool') + ->where('routers', $router) + ->find_one(); + $port = explode('-',$ports['range_port']); + if (empty($tcf) && !empty($ports)) { + repeat: + $portr = rand($port['0'], $port['1']); + if (ORM::for_table('tbl_customers_fields')->where('field_value', $portr)->find_one()) { + if($portr == $port['1']) + { + return; + } + goto repeat; + } + $cf = ORM::for_table('tbl_customers_fields')->create(); + $cf->customer_id = $id; + $cf->field_name = $portn; + $cf->field_value = $portr; + $cf->save(); + } + } + + function checkIpAddr($pname, $id) { + $c = ORM::for_table('tbl_customers')->find_one($id); + $ipp = ORM::for_table('tbl_pool') + ->where('pool_name', $pname) + ->find_one(); + $ip_r = explode('-',$ipp['range_ip']); + $ip_1 = explode('.',$ip_r['0']); + $ip_2 = explode('.',$ip_r['1']); + repeat: + $ipt = rand($ip_1['3'], $ip_2['3']); + $ips = $ip_1['0'].'.'.$ip_1['1'].'.'.$ip_1['2'].'.'.$ipt; + if (empty($c['pppoe_ip'])) { + if (ORM::for_table('tbl_customers')->where('pppoe_ip' ,$ips)->find_one()) { + if ($ip_2['3'] == $ipt) + { + return; + } + goto repeat; + } + return $ips; + } + } + +} From 82569239e2a1d43e355d06ed7f01a5eb8838554a Mon Sep 17 00:00:00 2001 From: Ibnu Maksum Date: Fri, 13 Sep 2024 14:46:14 +0700 Subject: [PATCH 310/841] update changelog --- CHANGELOG.md | 7 +++++++ version.json | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 21df89e6..8f9e0862 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,13 @@ # CHANGELOG +## 2024.9.13 + +- Add Selling Mikrotik VPN By @agstrxyz +- Theme Redesign by @Focuslinkstech +- Fix That and this + + ## 2024.8.28 - add Router Status Offline/Online by @Focuslinkstech diff --git a/version.json b/version.json index 1bd146b2..13f748ef 100644 --- a/version.json +++ b/version.json @@ -1,3 +1,3 @@ { - "version": "2024.9.6" + "version": "2024.9.13" } \ No newline at end of file From c2916da21541812a277b24c1772c95a9cf6d4f35 Mon Sep 17 00:00:00 2001 From: Focuslinkstech <45756999+Focuslinkstech@users.noreply.github.com> Date: Fri, 13 Sep 2024 09:33:59 +0100 Subject: [PATCH 311/841] fix dark button --- ui/ui/sections/header.tpl | 3 --- 1 file changed, 3 deletions(-) diff --git a/ui/ui/sections/header.tpl b/ui/ui/sections/header.tpl index bb5f8525..a86d1409 100644 --- a/ui/ui/sections/header.tpl +++ b/ui/ui/sections/header.tpl @@ -670,9 +670,6 @@ } .toggle-container { - position: absolute; - top: 17px; - right: 15px; cursor: pointer; } From a31286d7812f34fa12a99e21899476f3065be8d1 Mon Sep 17 00:00:00 2001 From: Focuslinkstech <45756999+Focuslinkstech@users.noreply.github.com> Date: Fri, 13 Sep 2024 09:47:43 +0100 Subject: [PATCH 312/841] fix toggle switch button mobile view --- ui/ui/sections/header.tpl | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/ui/ui/sections/header.tpl b/ui/ui/sections/header.tpl index a86d1409..862dbe4d 100644 --- a/ui/ui/sections/header.tpl +++ b/ui/ui/sections/header.tpl @@ -679,19 +679,6 @@ transition: color 0.5s ease; } - @media (max-width: 600px) { - .toggle-container { - top: 15px; - right: 60px; - } - - .toggle-container .toggle-icon { - font-size: 20px; - color: rgb(100 116 139); - transition: color 0.5s ease; - } - } - .dark-mode .toggle-container .toggle-icon { color: #ffdd57; } From 985ddda41f9c5cc07cd6e18d9563be475634da70 Mon Sep 17 00:00:00 2001 From: Focuslinkstech <45756999+Focuslinkstech@users.noreply.github.com> Date: Fri, 13 Sep 2024 09:55:58 +0100 Subject: [PATCH 313/841] fix panel warning bottom radius --- ui/ui/dashboard.tpl | 2 +- ui/ui/sections/header.tpl | 5 ----- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/ui/ui/dashboard.tpl b/ui/ui/dashboard.tpl index f0432982..b47f0796 100644 --- a/ui/ui/dashboard.tpl +++ b/ui/ui/dashboard.tpl @@ -198,7 +198,7 @@ {assign var="current_time" value=$smarty.now} {assign var="run_time" value=strtotime($run_date)} {if $current_time - $run_time > 3600} -
    +
      {Lang::T('Cron has not run for over 1 hour. Please check your setup.')}
    diff --git a/ui/ui/sections/header.tpl b/ui/ui/sections/header.tpl index 862dbe4d..a075a25a 100644 --- a/ui/ui/sections/header.tpl +++ b/ui/ui/sections/header.tpl @@ -157,11 +157,6 @@ border-bottom-left-radius: 21px; } - .panel-warning>.panel-heading { - border-bottom-right-radius: 21px; - border-bottom-left-radius: 21px; - } - .panel-danger>.panel-heading { color: #a94442; background-color: #f2dede; From 3c6ef3bcf34fac4a861036cdb55e8f9b5606057b Mon Sep 17 00:00:00 2001 From: AGSTR <144728914+agstrxyz@users.noreply.github.com> Date: Fri, 13 Sep 2024 16:31:03 +0700 Subject: [PATCH 314/841] Update MikrotikVpn.php --- system/devices/MikrotikVpn.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/system/devices/MikrotikVpn.php b/system/devices/MikrotikVpn.php index 6edeed2c..a8f41fec 100644 --- a/system/devices/MikrotikVpn.php +++ b/system/devices/MikrotikVpn.php @@ -400,8 +400,10 @@ class MikrotikVpn $this->checkPort($cust['id'], 'Web', $plan['routers']); $tcf = ORM::for_table('tbl_customers_fields') ->where('customer_id', $cust['id']) - ->find_many(); - + ->find_many(); + $ip = ORM::for_table('tbl_port_pool') + ->where('routers', $plan['routers']) + ->find_one(); foreach ($tcf as $cf) { $dst = $cf['field_value']; $cmnt = $cf['field_name']; @@ -421,7 +423,7 @@ class MikrotikVpn ->setArgument('action', 'dst-nat') ->setArgument('to-addresses', $ips) ->setArgument('to-ports', $tp) - ->setArgument('address', $ip) + ->setArgument('dst-address', $ip['public_ip']) ->setArgument('comment', $cmnt.' || '.$cust['username']) ); } @@ -434,9 +436,7 @@ class MikrotikVpn if ($_app_stage == 'demo') { return null; } - $tcf = ORM::for_table('tbl_customers_fields') - ->where('customer_id', $cstid) - ->find_many(); + $cst = ORM::for_table('tbl_customers')->find_one($cstid); $printRequest = new RouterOS\Request('/ip/firewall/nat/print'); $printRequest->setQuery(RouterOS\Query::where('to-addresses', $cst['pppoe_ip'])); From f81f3df700196ea2b022dd7f9c7bb578cb5a26ec Mon Sep 17 00:00:00 2001 From: Focuslinkstech <45756999+Focuslinkstech@users.noreply.github.com> Date: Fri, 13 Sep 2024 10:43:42 +0100 Subject: [PATCH 315/841] add mailer error reporting --- system/autoload/Message.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/system/autoload/Message.php b/system/autoload/Message.php index 988c98e0..cdc04525 100644 --- a/system/autoload/Message.php +++ b/system/autoload/Message.php @@ -154,6 +154,9 @@ class Message $mail->Body = $body; } $mail->send(); + if (!$mail->send()) { + _log(Lang::T("Email not sent, Mailer Error: ") . $mail->ErrorInfo); + } //

    } From f738c9b120b324c447f5fa4bf0db30481577c58a Mon Sep 17 00:00:00 2001 From: Focuslinkstech <45756999+Focuslinkstech@users.noreply.github.com> Date: Fri, 13 Sep 2024 12:03:18 +0100 Subject: [PATCH 316/841] add seperate css for cron monitor --- ui/ui/dashboard.tpl | 6 +++--- ui/ui/sections/header.tpl | 24 ++++++++++++++++++++++++ 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/ui/ui/dashboard.tpl b/ui/ui/dashboard.tpl index b47f0796..79db90d3 100644 --- a/ui/ui/dashboard.tpl +++ b/ui/ui/dashboard.tpl @@ -198,17 +198,17 @@ {assign var="current_time" value=$smarty.now} {assign var="run_time" value=strtotime($run_date)} {if $current_time - $run_time > 3600} -

    +
      {Lang::T('Cron has not run for over 1 hour. Please check your setup.')}
    {else} -
    +
    {Lang::T('Cron Job last ran on')}: {$run_date}
    {/if} {else} -
    +
      {Lang::T('Cron appear not been setup, please check your cron setup.')}
    diff --git a/ui/ui/sections/header.tpl b/ui/ui/sections/header.tpl index a075a25a..89c354d6 100644 --- a/ui/ui/sections/header.tpl +++ b/ui/ui/sections/header.tpl @@ -157,6 +157,30 @@ border-bottom-left-radius: 21px; } + .panel-cron-success>.panel-heading { + border-bottom-right-radius: 21px; + border-bottom-left-radius: 21px; + color: #fff; + background-color: #169210; + border-color: #25e01c; + + } + + .panel-cron-warning>.panel-heading { + border-bottom-right-radius: 21px; + border-bottom-left-radius: 21px; + color: #350808; + background-color: #efeb0a; + border-color: #efeb0a; + } + .panel-cron-danger>.panel-heading { + border-bottom-right-radius: 21px; + border-bottom-left-radius: 21px; + color: #fff; + background-color: #e61212; + border-color: #df1335; + } + .panel-danger>.panel-heading { color: #a94442; background-color: #f2dede; From 686d2a188a9d840dbc13180674d3b8b9b1a66be8 Mon Sep 17 00:00:00 2001 From: Ibnu Maksum Date: Fri, 20 Sep 2024 10:23:01 +0700 Subject: [PATCH 317/841] Add Public Header and Footer in user-ui folder, and use it for public page --- system/controllers/forgot.php | 114 +++++++++++++ system/controllers/login.php | 2 + system/controllers/register.php | 7 + system/devices/MikrotikVpn.php | 247 ++++++++++++++-------------- ui/ui/user-ui/404.tpl | 6 +- ui/ui/user-ui/footer-public.tpl | 39 +++++ ui/ui/user-ui/forgot.tpl | 73 +++++++++ ui/ui/user-ui/header-public.tpl | 43 +++++ ui/ui/user-ui/login-noreg.tpl | 195 +++++++++------------- ui/ui/user-ui/login.tpl | 187 +++++++++------------ ui/ui/user-ui/register-otp.tpl | 282 +++++++++++++------------------- ui/ui/user-ui/register-rotp.tpl | 168 ++++++------------- ui/ui/user-ui/register.tpl | 243 +++++++++------------------ 13 files changed, 810 insertions(+), 796 deletions(-) create mode 100644 system/controllers/forgot.php create mode 100644 ui/ui/user-ui/footer-public.tpl create mode 100644 ui/ui/user-ui/forgot.tpl create mode 100644 ui/ui/user-ui/header-public.tpl diff --git a/system/controllers/forgot.php b/system/controllers/forgot.php new file mode 100644 index 00000000..4b711dfe --- /dev/null +++ b/system/controllers/forgot.php @@ -0,0 +1,114 @@ +'; + } + if (Validator::Length($fullname, 36, 2) == false) { + $msg .= 'Full Name should be between 3 to 25 characters' . '
    '; + } + if (!Validator::Length($password, 35, 2)) { + $msg .= 'Password should be between 3 to 35 characters' . '
    '; + } + if (!Validator::Email($email)) { + $msg .= 'Email is not Valid
    '; + } + if ($password != $cpassword) { + $msg .= Lang::T('Passwords does not match') . '
    '; + } + + if (!empty($config['sms_url']) && $_c['allow_phone_otp'] == 'yes') { + $otpPath .= sha1($username . $db_pass) . ".txt"; + run_hook('validate_otp'); #HOOK + //expired 10 minutes + if (file_exists($otpPath) && time() - filemtime($otpPath) > 1200) { + unlink($otpPath); + r2(U . 'register', 's', 'Verification code expired'); + } else if (file_exists($otpPath)) { + $code = file_get_contents($otpPath); + if ($code != $otp_code) { + $ui->assign('username', $username); + $ui->assign('fullname', $fullname); + $ui->assign('address', $address); + $ui->assign('email', $email); + $ui->assign('phonenumber', $phonenumber); + $ui->assign('notify', 'Wrong Verification code'); + $ui->assign('notify_t', 'd'); + $ui->display('user-ui/register-otp.tpl'); + exit(); + } else { + unlink($otpPath); + } + } else { + r2(U . 'register', 's', 'No Verification code'); + } + } + $d = ORM::for_table('tbl_customers')->where('username', $username)->find_one(); + if ($d) { + $msg .= Lang::T('Account already axist') . '
    '; + } + if ($msg == '') { + run_hook('register_user'); #HOOK + $d = ORM::for_table('tbl_customers')->create(); + $d->username = alphanumeric($username, "+_.@-"); + $d->password = $password; + $d->fullname = $fullname; + $d->address = $address; + $d->email = $email; + $d->phonenumber = $phonenumber; + if ($d->save()) { + $user = $d->id(); + r2(U . 'login', 's', Lang::T('Register Success! You can login now')); + } else { + $ui->assign('username', $username); + $ui->assign('fullname', $fullname); + $ui->assign('address', $address); + $ui->assign('email', $email); + $ui->assign('phonenumber', $phonenumber); + $ui->assign('notify', 'Failed to register'); + $ui->assign('notify_t', 'd'); + run_hook('view_otp_register'); #HOOK + $ui->display('user-ui/register-rotp.tpl'); + } + } else { + $ui->assign('username', $username); + $ui->assign('fullname', $fullname); + $ui->assign('address', $address); + $ui->assign('email', $email); + $ui->assign('phonenumber', $phonenumber); + $ui->assign('notify', $msg); + $ui->assign('notify_t', 'd'); + $ui->display('user-ui/register.tpl'); + } + break; + + default: + $ui->display('user-ui/forgot.tpl'); + break; +} diff --git a/system/controllers/login.php b/system/controllers/login.php index 75bf4a35..94b74f01 100644 --- a/system/controllers/login.php +++ b/system/controllers/login.php @@ -290,9 +290,11 @@ switch ($do) { default: run_hook('customer_view_login'); #HOOK if ($config['disable_registration'] == 'yes') { + $ui->assign('_title', Lang::T('Activation')); $ui->assign('code', alphanumeric(_get('code'), "-")); $ui->display('user-ui/login-noreg.tpl'); } else { + $ui->assign('_title', Lang::T('Login')); $ui->display('user-ui/login.tpl'); } break; diff --git a/system/controllers/register.php b/system/controllers/register.php index 3ccedf26..daa0d55e 100644 --- a/system/controllers/register.php +++ b/system/controllers/register.php @@ -62,6 +62,7 @@ switch ($do) { $ui->assign('phonenumber', $phonenumber); $ui->assign('notify', 'Wrong Verification code'); $ui->assign('notify_t', 'd'); + $ui->assign('_title', Lang::T('Register')); $ui->display('user-ui/register-otp.tpl'); exit(); } else { @@ -95,6 +96,7 @@ switch ($do) { $ui->assign('phonenumber', $phonenumber); $ui->assign('notify', 'Failed to register'); $ui->assign('notify_t', 'd'); + $ui->assign('_title', Lang::T('Register')); run_hook('view_otp_register'); #HOOK $ui->display('user-ui/register-rotp.tpl'); } @@ -106,6 +108,7 @@ switch ($do) { $ui->assign('phonenumber', $phonenumber); $ui->assign('notify', $msg); $ui->assign('notify_t', 'd'); + $ui->assign('_title', Lang::T('Register')); $ui->display('user-ui/register.tpl'); } break; @@ -128,6 +131,7 @@ switch ($do) { $ui->assign('username', $username); $ui->assign('notify', 'Please wait ' . (600 - (time() - filemtime($otpPath))) . ' seconds before sending another SMS'); $ui->assign('notify_t', 'd'); + $ui->assign('_title', Lang::T('Register')); $ui->display('user-ui/register-otp.tpl'); } else { $otp = rand(100000, 999999); @@ -136,9 +140,11 @@ switch ($do) { $ui->assign('username', $username); $ui->assign('notify', 'Registration code has been sent to your phone'); $ui->assign('notify_t', 's'); + $ui->assign('_title', Lang::T('Register')); $ui->display('user-ui/register-otp.tpl'); } } else { + $ui->assign('_title', Lang::T('Register')); run_hook('view_otp_register'); #HOOK $ui->display('user-ui/register-rotp.tpl'); } @@ -148,6 +154,7 @@ switch ($do) { $ui->assign('address', ""); $ui->assign('email', ""); $ui->assign('otp', false); + $ui->assign('_title', Lang::T('Register')); run_hook('view_register'); #HOOK $ui->display('user-ui/register.tpl'); } diff --git a/system/devices/MikrotikVpn.php b/system/devices/MikrotikVpn.php index a8f41fec..502cd594 100644 --- a/system/devices/MikrotikVpn.php +++ b/system/devices/MikrotikVpn.php @@ -28,7 +28,7 @@ class MikrotikVpn $cid = self::getIdByCustomer($customer, $client); if (empty($cid)) { $this->addVpnUser($client, $plan, $customer); - }else{ + } else { $setRequest = new RouterOS\Request('/ppp/secret/set'); $setRequest->setArgument('numbers', $cid); if (!empty($customer['pppoe_password'])) { @@ -43,13 +43,13 @@ class MikrotikVpn } if (!empty($customer['pppoe_ip'])) { $setRequest->setArgument('remote-address', $customer['pppoe_ip']); - }else{ + } else { $setRequest->setArgument('remote-address', '0.0.0.0'); } $setRequest->setArgument('profile', $plan['name_plan']); $setRequest->setArgument('comment', $customer['fullname'] . ' | ' . $customer['email'] . ' | ' . implode(', ', User::getBillNames($customer['id']))); $client->sendSync($setRequest); - if(isset($isChangePlan) && $isChangePlan){ + if (isset($isChangePlan) && $isChangePlan) { $this->removeVpnActive($client, $customer['username']); if (!empty($customer['pppoe_username'])) { $this->removeVpnActive($client, $customer['pppoe_username']); @@ -64,7 +64,7 @@ class MikrotikVpn $client = $this->getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']); if (!empty($plan['plan_expired'])) { $p = ORM::for_table("tbl_plans")->find_one($plan['plan_expired']); - if($p){ + if ($p) { $this->add_customer($customer, $p); $this->removeVpnActive($client, $customer['username']); if (!empty($customer['pppoe_username'])) { @@ -117,26 +117,27 @@ class MikrotikVpn $unitup = 'M'; } $rate = $bw['rate_up'] . $unitup . "/" . $bw['rate_down'] . $unitdown; - if(!empty(trim($bw['burst']))){ - $rate .= ' '.$bw['burst']; + if (!empty(trim($bw['burst']))) { + $rate .= ' ' . $bw['burst']; } $pool = ORM::for_table("tbl_pool")->where("pool_name", $plan['pool'])->find_one(); $addRequest = new RouterOS\Request('/ppp/profile/add'); $client->sendSync( $addRequest ->setArgument('name', $plan['name_plan']) - ->setArgument('local-address', (!empty($pool['local_ip'])) ? $pool['local_ip']: $pool['pool_name']) + ->setArgument('local-address', (!empty($pool['local_ip'])) ? $pool['local_ip'] : $pool['pool_name']) ->setArgument('remote-address', $pool['pool_name']) ->setArgument('rate-limit', $rate) ); } - function getIdByCustomer($customer, $client){ + function getIdByCustomer($customer, $client) + { $printRequest = new RouterOS\Request('/ppp/secret/print'); $printRequest->setQuery(RouterOS\Query::where('name', $customer['username'])); $id = $client->sendSync($printRequest)->getProperty('.id'); - if(empty($id)){ + if (empty($id)) { if (!empty($customer['pppoe_username'])) { $printRequest = new RouterOS\Request('/ppp/secret/print'); $printRequest->setQuery(RouterOS\Query::where('name', $customer['pppoe_username'])); @@ -171,15 +172,15 @@ class MikrotikVpn $unitup = 'M'; } $rate = $bw['rate_up'] . $unitup . "/" . $bw['rate_down'] . $unitdown; - if(!empty(trim($bw['burst']))){ - $rate .= ' '.$bw['burst']; + if (!empty(trim($bw['burst']))) { + $rate .= ' ' . $bw['burst']; } $pool = ORM::for_table("tbl_pool")->where("pool_name", $new_plan['pool'])->find_one(); $setRequest = new RouterOS\Request('/ppp/profile/set'); $client->sendSync( $setRequest ->setArgument('numbers', $profileID) - ->setArgument('local-address', (!empty($pool['local_ip'])) ? $pool['local_ip']: $pool['pool_name']) + ->setArgument('local-address', (!empty($pool['local_ip'])) ? $pool['local_ip'] : $pool['pool_name']) ->setArgument('remote-address', $pool['pool_name']) ->setArgument('rate-limit', $rate) ->setArgument('on-up', $new_plan['on_login']) @@ -205,7 +206,8 @@ class MikrotikVpn ); } - function add_pool($pool){ + function add_pool($pool) + { global $_app_stage; if ($_app_stage == 'demo') { return null; @@ -220,7 +222,8 @@ class MikrotikVpn ); } - function update_pool($old_pool, $new_pool){ + function update_pool($old_pool, $new_pool) + { global $_app_stage; if ($_app_stage == 'demo') { return null; @@ -245,7 +248,8 @@ class MikrotikVpn } } - function remove_pool($pool){ + function remove_pool($pool) + { global $_app_stage; if ($_app_stage == 'demo') { return null; @@ -304,7 +308,7 @@ class MikrotikVpn $removeRequest = new RouterOS\Request('/ppp/secret/remove'); $removeRequest->setArgument('numbers', $id); $client->sendSync($removeRequest); - $this->rmNat($client, $cstid); + $this->rmNat($client, $cstid); } function addVpnUser($client, $plan, $customer) @@ -324,18 +328,17 @@ class MikrotikVpn $setRequest->setArgument('name', $customer['username']); } if (!empty($customer['pppoe_ip'])) { - $ips = $customer['pppoe_ip']; + $ips = $customer['pppoe_ip']; $setRequest->setArgument('remote-address', $customer['pppoe_ip']); } else { - $ips = $this->checkIpAddr($plan['pool'], $customer['id']); - $setRequest->setArgument('remote-address', $ips); - - } - $this->addNat($client, $plan, $customer, $ips); + $ips = $this->checkIpAddr($plan['pool'], $customer['id']); + $setRequest->setArgument('remote-address', $ips); + } + $this->addNat($client, $plan, $customer, $ips); $client->sendSync($setRequest); - $customer->service_type = 'VPN'; - $customer->pppoe_ip = $ips; - $customer->save(); + $customer->service_type = 'VPN'; + $customer->pppoe_ip = $ips; + $customer->save(); } function removeVpnActive($client, $username) @@ -368,7 +371,6 @@ class MikrotikVpn ->setArgument('comment', $comment) ->setArgument('list', $listName) ); - } function removeIpFromAddressList($client, $ip) @@ -395,110 +397,111 @@ class MikrotikVpn if ($_app_stage == 'demo') { return null; } - $this->checkPort($cust['id'], 'Winbox', $plan['routers']); - $this->checkPort($cust['id'], 'Api', $plan['routers']); - $this->checkPort($cust['id'], 'Web', $plan['routers']); - $tcf = ORM::for_table('tbl_customers_fields') - ->where('customer_id', $cust['id']) - ->find_many(); - $ip = ORM::for_table('tbl_port_pool') - ->where('routers', $plan['routers']) - ->find_one(); - foreach ($tcf as $cf) { - $dst = $cf['field_value']; - $cmnt = $cf['field_name']; - if ($cmnt == 'Winbox') { - $tp = '8291'; } - if ($cmnt == 'Web') { - $tp = '80'; } - if ($cmnt == 'Api') { - $tp = '8728'; } - if ($cmnt == 'Winbox' || $cmnt == 'Web' || $cmnt == 'Api') { - $addRequest = new RouterOS\Request('/ip/firewall/nat/add'); - $client->sendSync( - $addRequest - ->setArgument('chain', 'dstnat') - ->setArgument('protocol', 'tcp') - ->setArgument('dst-port', $dst) - ->setArgument('action', 'dst-nat') - ->setArgument('to-addresses', $ips) - ->setArgument('to-ports', $tp) - ->setArgument('dst-address', $ip['public_ip']) - ->setArgument('comment', $cmnt.' || '.$cust['username']) - ); - } - } + $this->checkPort($cust['id'], 'Winbox', $plan['routers']); + $this->checkPort($cust['id'], 'Api', $plan['routers']); + $this->checkPort($cust['id'], 'Web', $plan['routers']); + $tcf = ORM::for_table('tbl_customers_fields') + ->where('customer_id', $cust['id']) + ->find_many(); + $ip = ORM::for_table('tbl_port_pool') + ->where('routers', $plan['routers']) + ->find_one(); + foreach ($tcf as $cf) { + $dst = $cf['field_value']; + $cmnt = $cf['field_name']; + if ($cmnt == 'Winbox') { + $tp = '8291'; + } + if ($cmnt == 'Web') { + $tp = '80'; + } + if ($cmnt == 'Api') { + $tp = '8728'; + } + if ($cmnt == 'Winbox' || $cmnt == 'Web' || $cmnt == 'Api') { + $addRequest = new RouterOS\Request('/ip/firewall/nat/add'); + $client->sendSync( + $addRequest + ->setArgument('chain', 'dstnat') + ->setArgument('protocol', 'tcp') + ->setArgument('dst-port', $dst) + ->setArgument('action', 'dst-nat') + ->setArgument('to-addresses', $ips) + ->setArgument('to-ports', $tp) + ->setArgument('dst-address', $ip['public_ip']) + ->setArgument('comment', $cmnt . ' || ' . $cust['username']) + ); + } + } } - + function rmNat($client, $cstid) { global $_app_stage; if ($_app_stage == 'demo') { return null; } - - $cst = ORM::for_table('tbl_customers')->find_one($cstid); + + $cst = ORM::for_table('tbl_customers')->find_one($cstid); $printRequest = new RouterOS\Request('/ip/firewall/nat/print'); $printRequest->setQuery(RouterOS\Query::where('to-addresses', $cst['pppoe_ip'])); $nats = $client->sendSync($printRequest); - foreach ($nats as $nat) { - $id = $client->sendSync($printRequest)->getProperty('.id'); - $removeRequest = new RouterOS\Request('/ip/firewall/nat/remove'); - $removeRequest->setArgument('numbers', $id); - $client->sendSync($removeRequest); - } - } - - - function checkPort($id, $portn, $router) - { - $tcf = ORM::for_table('tbl_customers_fields') - ->where('customer_id', $id) - ->where('field_name', $portn) - ->find_one(); - $ports = ORM::for_table('tbl_port_pool') - ->where('routers', $router) - ->find_one(); - $port = explode('-',$ports['range_port']); - if (empty($tcf) && !empty($ports)) { - repeat: - $portr = rand($port['0'], $port['1']); - if (ORM::for_table('tbl_customers_fields')->where('field_value', $portr)->find_one()) { - if($portr == $port['1']) - { - return; - } - goto repeat; - } - $cf = ORM::for_table('tbl_customers_fields')->create(); - $cf->customer_id = $id; - $cf->field_name = $portn; - $cf->field_value = $portr; - $cf->save(); - } - } - - function checkIpAddr($pname, $id) { - $c = ORM::for_table('tbl_customers')->find_one($id); - $ipp = ORM::for_table('tbl_pool') - ->where('pool_name', $pname) - ->find_one(); - $ip_r = explode('-',$ipp['range_ip']); - $ip_1 = explode('.',$ip_r['0']); - $ip_2 = explode('.',$ip_r['1']); - repeat: - $ipt = rand($ip_1['3'], $ip_2['3']); - $ips = $ip_1['0'].'.'.$ip_1['1'].'.'.$ip_1['2'].'.'.$ipt; - if (empty($c['pppoe_ip'])) { - if (ORM::for_table('tbl_customers')->where('pppoe_ip' ,$ips)->find_one()) { - if ($ip_2['3'] == $ipt) - { - return; - } - goto repeat; - } - return $ips; - } - } - + foreach ($nats as $nat) { + $id = $client->sendSync($printRequest)->getProperty('.id'); + $removeRequest = new RouterOS\Request('/ip/firewall/nat/remove'); + $removeRequest->setArgument('numbers', $id); + $client->sendSync($removeRequest); + } + } + + + function checkPort($id, $portn, $router) + { + $tcf = ORM::for_table('tbl_customers_fields') + ->where('customer_id', $id) + ->where('field_name', $portn) + ->find_one(); + $ports = ORM::for_table('tbl_port_pool') + ->where('routers', $router) + ->find_one(); + $port = explode('-', $ports['range_port']); + if (empty($tcf) && !empty($ports)) { + repeat: + $portr = rand($port['0'], $port['1']); + if (ORM::for_table('tbl_customers_fields')->where('field_value', $portr)->find_one()) { + if ($portr == $port['1']) { + return; + } + goto repeat; + } + $cf = ORM::for_table('tbl_customers_fields')->create(); + $cf->customer_id = $id; + $cf->field_name = $portn; + $cf->field_value = $portr; + $cf->save(); + } + } + + function checkIpAddr($pname, $id) + { + $c = ORM::for_table('tbl_customers')->find_one($id); + $ipp = ORM::for_table('tbl_pool') + ->where('pool_name', $pname) + ->find_one(); + $ip_r = explode('-', $ipp['range_ip']); + $ip_1 = explode('.', $ip_r['0']); + $ip_2 = explode('.', $ip_r['1']); + repeat: + $ipt = rand($ip_1['3'], $ip_2['3']); + $ips = $ip_1['0'] . '.' . $ip_1['1'] . '.' . $ip_1['2'] . '.' . $ipt; + if (empty($c['pppoe_ip'])) { + if (ORM::for_table('tbl_customers')->where('pppoe_ip', $ips)->find_one()) { + if ($ip_2['3'] == $ipt) { + return; + } + goto repeat; + } + return $ips; + } + } } diff --git a/ui/ui/user-ui/404.tpl b/ui/ui/user-ui/404.tpl index 4d975e4c..eaf0b977 100644 --- a/ui/ui/user-ui/404.tpl +++ b/ui/ui/user-ui/404.tpl @@ -1,4 +1,5 @@ -{include file="user-ui/header.tpl"} +{include file="user-ui/header-public.tpl"} +
    @@ -6,5 +7,4 @@

    {Lang::T('Coming Soon! Next Version...')}

    - -{include file="user-ui/footer.tpl"} +{include file="user-ui/footer-public.tpl"} \ No newline at end of file diff --git a/ui/ui/user-ui/footer-public.tpl b/ui/ui/user-ui/footer-public.tpl new file mode 100644 index 00000000..8d31991c --- /dev/null +++ b/ui/ui/user-ui/footer-public.tpl @@ -0,0 +1,39 @@ + +
    + + + + {if $_c['tawkto'] != ''} + + + + {/if} + + + + \ No newline at end of file diff --git a/ui/ui/user-ui/forgot.tpl b/ui/ui/user-ui/forgot.tpl new file mode 100644 index 00000000..2289533c --- /dev/null +++ b/ui/ui/user-ui/forgot.tpl @@ -0,0 +1,73 @@ +{include file="user-ui/header-public.tpl"} +
    +
    +
    +
    {Lang::T('Announcement')}
    +
    + {$Announcement = "{$PAGES_PATH}/Announcement.html"} + {if file_exists($Announcement)} + {include file=$Announcement} + {/if} +
    +
    +
    +
    +
    +
    {Lang::T('Log in to Member Panel')}
    +
    +
    +
    + +
    + {if $_c['country_code_phone']!= ''} + + {else} + + {/if} + +
    + +
    +
    + +
    + + +
    +
    + + +
    + +
    + +
    +
    +
    +
    + {Lang::T('Forgot Password')} +
    + Privacy + • + T & C +
    +
    +
    +
    +
    +
    +{include file="user-ui/footer-public.tpl"} \ No newline at end of file diff --git a/ui/ui/user-ui/header-public.tpl b/ui/ui/user-ui/header-public.tpl new file mode 100644 index 00000000..d9a478b2 --- /dev/null +++ b/ui/ui/user-ui/header-public.tpl @@ -0,0 +1,43 @@ + + + + + + + {$_title} - {$_c['CompanyName']} + + + + + + + + + + + + +
    +
    +

    {$_c['CompanyName']}

    +
    +
    + {if isset($notify)} + + {/if} \ No newline at end of file diff --git a/ui/ui/user-ui/login-noreg.tpl b/ui/ui/user-ui/login-noreg.tpl index c1163695..88e81df2 100644 --- a/ui/ui/user-ui/login-noreg.tpl +++ b/ui/ui/user-ui/login-noreg.tpl @@ -1,118 +1,83 @@ - - - - - - - {Lang::T('Login')} - {$_c['CompanyName']} - - - - - - - - - -
    - -
    -

    {$_c['CompanyName']}

    -
    -
    - {if isset($notify)} -
    - -
    {$notify}
    -
    - {/if} -
    -
    -
    -
    {Lang::T('Announcement')}
    -
    - {include file="$_path/../pages/Announcement.html"} -
    -
    -
    -
    -
    -
    {Lang::T('Login / Activate Voucher')}
    -
    -
    -
    - -
    - {if $_c['country_code_phone']!= ''} - - {else} - - {/if} - -
    -
    -
    - -
    - - - - -
    -
    -
    -
    - -
    -
    -
    -
    -
    -
    -
    {Lang::T('Activate Voucher')}
    -
    -
    -
    - -
    - - - - -
    -
    -
    -
    - -
    -
    -
    -
    -
    -
    -
    - Privacy - • - ToC -
    +{include file="user-ui/header-public.tpl"} + +
    +
    +
    +
    {Lang::T('Announcement')}
    +
    + {include file="$_path/../pages/Announcement.html"}
    - - - - \ No newline at end of file +
    +
    +
    {Lang::T('Login / Activate Voucher')}
    +
    +
    +
    + +
    + {if $_c['country_code_phone']!= ''} + + {else} + + {/if} + +
    +
    +
    + +
    + + + + +
    +
    +
    +
    + +
    +
    +
    +
    +
    +
    +
    {Lang::T('Activate Voucher')}
    +
    +
    +
    + +
    + + + + +
    +
    +
    +
    + +
    +
    +
    +
    +
    +
    +
    + Privacy + • + ToC +
    +
    +
    +{include file="user-ui/footer-public.tpl"} \ No newline at end of file diff --git a/ui/ui/user-ui/login.tpl b/ui/ui/user-ui/login.tpl index b8f0b033..1019a2ff 100644 --- a/ui/ui/user-ui/login.tpl +++ b/ui/ui/user-ui/login.tpl @@ -1,119 +1,92 @@ - - +{include file="user-ui/header-public.tpl"} - - - - {Lang::T('Login')} - {$_c['CompanyName']} - - - - - - - -
    - -
    -

    {$_c['CompanyName']}

    -
    + +
    +
    +
    +
    {Lang::T('Announcement')}
    +
    + {$Announcement = "{$PAGES_PATH}/Announcement.html"} + {if file_exists($Announcement)} + {include file=$Announcement} + {/if} +
    - {if isset($notify)} -
    - -
    {$notify}
    -
    - {/if} -
    -
    -
    -
    {Lang::T('Announcement')}
    -
    - {$Announcement = "{$PAGES_PATH}/Announcement.html"} - {if file_exists($Announcement)} - {include file=$Announcement} - {/if} -
    -
    -
    -
    -
    -
    {Lang::T('Log in to Member Panel')}
    -
    -
    -
    - -
    - {if $_c['country_code_phone']!= ''} - +
    +
    +
    {Lang::T('Log in to Member Panel')}
    +
    + +
    + +
    + {if $_c['country_code_phone']!= ''} + - {else} - - {/if} - + {/if} + -
    +
    -
    -
    - -
    - - +
    +
    + +
    + + +
    +
    + + +
    + +
    + +
    +
    +
    +
    + {Lang::T('Forgot Password')} +
    + Privacy + • + T & C +
    + +
    +
    - -
    - -
    - -
    -
    -
    -
    - Privacy - • - T & C -
    - -
    -
    + + - - - - - - - - +{include file="user-ui/footer-public.tpl"} \ No newline at end of file diff --git a/ui/ui/user-ui/register-otp.tpl b/ui/ui/user-ui/register-otp.tpl index 942417d4..3ac50674 100644 --- a/ui/ui/user-ui/register-otp.tpl +++ b/ui/ui/user-ui/register-otp.tpl @@ -1,170 +1,122 @@ - - +{include file="user-ui/header-public.tpl"} + - - - - {Lang::T('Register')} - {$_c['CompanyName']} - - - - - - - - - - - - - -
    - -
    -

    {$_c['CompanyName']}

    -
    -
    - {if isset($notify)} - - {/if} -
    -
    -
    -
    {Lang::T('Registration Info')}
    -
    - {include file="$_path/../pages/Registration_Info.html"} -
    -
    -
    -
    -
    -
    -
    1. {Lang::T('Register as Member')}
    -
    -
    -
    - -
    - {if $_c['country_code_phone']!= ''} - - {else} - - {/if} - -
    -
    -
    - - -
    -
    - - -
    -
    - - -
    -
    - - -
    -
    -
    -
    -
    -
    -
    -
    2. {Lang::T('Password')}
    -
    -
    -
    - - -
    -
    - - -
    -
    - -
    - -
    -
    -
    -
    - Privacy - • - T & C -
    -
    -
    -
    -
    -
    -
    -
    - - -