Compare commits

..

1003 Commits

Author SHA1 Message Date
ae3db05649 2024.5.14 2024-05-14 13:40:30 +07:00
fa45d5f4b5 Customizeable Payment Recharge 2024-05-14 10:25:21 +07:00
895bb26b02 add Internet Plan and Location in expired list Dashboard 2024-05-14 09:11:56 +07:00
a5affdb674 add refresh dashboard to get latest data 2024-05-14 08:55:38 +07:00
238fc03d03 update ORM so it can use array for select 2024-05-14 08:43:26 +07:00
cf8e23ae88 Fix Burst 2024-05-08 17:24:41 +07:00
b9132082e5 Merge pull request #197 from gerandonk/Development
Fix bugs burst
2024-05-08 17:22:07 +07:00
ee63abb618 Fix bugs burst
Fix Burst on php7
Fix edit hotspot plan
Fix burs reset if klick sync button on plan page
2024-05-08 13:39:15 +07:00
060718dfda Fix Validity,, forgot to explode 2024-05-07 19:11:31 +07:00
651969924c add remove Active user when extends 2024-05-07 11:28:51 +07:00
a40b2cbea3 add numeric option at Settings 2024-05-07 10:53:04 +07:00
fc73a83732 2024.5.7 2024-05-07 10:15:28 +07:00
6763fe09d8 fix validity_unit time for Days 2024-05-07 10:15:28 +07:00
0ea9de70fc Merge pull request #195 from agstrxyz/master
Update services.php
2024-05-07 08:55:29 +07:00
c7ec8e2d27 Merge pull request #194 from agstrxyz/patch-12
Update cron.php
2024-05-07 08:54:51 +07:00
822acef6d8 Merge pull request #192 from agstrxyz/Development
Update Radius.php
2024-05-07 08:54:10 +07:00
892c6bf7f5 Merge pull request #189 from pro-cms/patch-4
Added generate voucher function.
2024-05-07 08:50:25 +07:00
c0c857e735 Merge pull request #188 from pro-cms/patch-3
Add voucher type numbers in Option
2024-05-07 08:49:48 +07:00
49794b99de Merge pull request #187 from pro-cms/patch-2
Added generate numeric only vouchers
2024-05-07 08:49:11 +07:00
126212f4c2 Merge branch 'Development' into patch-2 2024-05-07 08:49:01 +07:00
e3de07d435 Update services.php
busrt radius plan
2024-05-07 08:11:16 +07:00
2f551b1755 Update cron.php
Fix Autorenewal radius plan base
2024-05-07 04:55:20 +07:00
f766393e52 Update Radius.php
Fix radius plan base
*uptime limit
*burst bw profile limit
*data limit
*user can't login after recharge radius plan base

please add this variable in "mods-available/sqlcounter" for freeradius installation wiki

sqlcounter uptimelimit {
counter_name = 'Max-All-Session-Time'
check_name = 'Max-All-Session'
sql_module_instance = sql
key = 'User-Name'
reset = never
query = "SELECT SUM(AcctSessionTime) FROM radacct WHERE UserName='%{${key}}'"
}

and this variable in "sites-enabled/default"
authorize {
expiration
quotalimit
accessperiod
uptimelimit
}
2024-05-07 04:27:13 +07:00
0bd587522a Search all field 2024-05-02 16:31:25 +07:00
47c6e90624 delete die() debug, forgot to delete it 2024-05-01 10:21:32 +07:00
fc0ef5b41a Added generate voucher function. 2024-04-30 23:16:20 +03:00
dff3970ff4 Add voucher type numbers in Option 2024-04-30 23:15:05 +03:00
4c4fe4e99f Added generate numeric only vouchers 2024-04-30 23:14:08 +03:00
2ed3dc991a CRITICAL UPDATE: last update Logic recharge not check is status on or off, it make expired customer stay in expired pool 2024-04-30 22:36:24 +07:00
be43a5b385 add anti double submit when refill balance 2024-04-29 14:01:05 +07:00
61bd042b15 add notif if Customer is not expired yet when extend 2024-04-29 13:50:26 +07:00
b6fde35eb6 add search and pagination at Customer maps, fix query 2024-04-29 13:44:59 +07:00
980af58eb1 fix logic extend from admin 2024-04-29 13:20:57 +07:00
f7deb828ac don't delete customer when plan not change 2024-04-29 13:18:07 +07:00
4c1e5da601 fix variable forsendPackageNotification 2024-04-23 15:34:40 +07:00
9712d411f5 Merge branch 'Development' 2024-04-23 11:52:04 +07:00
8dc7707b3a fix pagination Voucher 2024-04-23 11:51:34 +07:00
18bdf185d6 Update plan.php 2024-04-23 11:32:58 +07:00
2a70236576 Merge pull request #181 from agstrxyz/patch-10
Update plan.php
2024-04-23 11:31:52 +07:00
7b40fc850e Merge pull request #180 from freeispradius/master
Update to case csv. added columns
2024-04-23 11:31:18 +07:00
ad411e2223 Update plan.php 2024-04-23 09:24:47 +07:00
45a6085205 Update case csv-prepaid
changed the url
2024-04-22 23:33:54 +03:00
91fe5a4b46 Update to case csv. added columns
separated case csv now we will have one for all customers and another one for prepaid users.
for all customers csv will be downloaded from list and prepaid csv will be from prepaid users.
Also added columns instead of the previous one
2024-04-22 23:31:36 +03:00
c0cd197df2 Fix Extend Confirmation long text 2024-04-22 14:02:33 +07:00
3e89efcf46 add Customer Fullname 2024-04-22 11:33:21 +07:00
31b710e03c add username to telegram notif 2024-04-22 10:30:01 +07:00
4d6041f614 send Telegram for Extend 2024-04-22 10:30:01 +07:00
fbaf9dbe3f Merge pull request #179 from ahmadhusein17/patch-21
Indonesian Language Improvement
2024-04-22 09:51:18 +07:00
a4f5c1d422 Update indonesia.json
Improvements to the use of letter size in the language and minor improvements
2024-04-21 21:46:31 +07:00
d08137e0c3 Merge branch 'master' into Development 2024-04-21 20:55:42 +07:00
961f4770c0 Update cron_reminder.php 2024-04-21 20:54:10 +07:00
2d6fe9526c Update cron_reminder.php 2024-04-21 20:54:10 +07:00
bebc20e39f Update cron_reminder.php 2024-04-21 20:54:10 +07:00
964c141668 Update cron_reminder.php 2024-04-21 20:54:10 +07:00
88bbf3ed35 fix lang.php 2024-04-21 20:54:10 +07:00
bf00b21786 fix Lang 2024-04-21 20:54:10 +07:00
0e81db5ada indonesia lang 2024-04-21 20:54:10 +07:00
c0382c569a Update cron_reminder.php 2024-04-21 20:54:10 +07:00
c32542afda Update cron_reminder.php 2024-04-21 20:54:10 +07:00
8d17cd3f90 fix [[expired_date]] 2024-04-21 20:54:10 +07:00
6dafd549d9 Restore old cron 2024-04-21 20:54:10 +07:00
20c4be9121 As exp dev says, if it works, dont touch it 2024-04-21 20:54:10 +07:00
2f757f1006 Update cron_reminder.php 2024-04-21 20:54:10 +07:00
0ce112dc70 order activated by desc 2024-04-21 20:54:10 +07:00
ea3f5caf59 Update voucher.tpl 2024-04-21 20:54:09 +07:00
5a5032bbcc fix [[expired_date]] 2024-04-21 10:59:20 +07:00
0d44fec338 Restore old cron 2024-04-21 10:54:04 +07:00
7396c2f1d4 As exp dev says, if it works, dont touch it 2024-04-21 10:54:04 +07:00
73cf67b4cb Update cron_reminder.php 2024-04-21 10:54:04 +07:00
9e0f74926c Update cron_reminder.php 2024-04-21 10:54:04 +07:00
09af3474a9 Update cron.php 2024-04-21 10:54:04 +07:00
9b8f1fedf8 Merge pull request #178 from ahmadhusein17/master
restore cron.php and cron_reminder.php
2024-04-21 10:48:11 +07:00
05c77df315 order activated by desc 2024-04-19 14:43:06 +07:00
e88f662d8c Merge pull request #177 from ahmadhusein17/Development
Update voucher.tpl
2024-04-19 13:37:39 +07:00
2956cc2315 Update cron_reminder.php 2024-04-19 11:23:50 +07:00
3c8b2c906d Update cron_reminder.php 2024-04-19 11:22:34 +07:00
acded8eb29 Update cron.php 2024-04-19 11:21:44 +07:00
b63aeb5298 Update voucher.tpl 2024-04-16 14:10:40 +07:00
115a5c81a7 Fix variable cron for notification 2024-04-16 13:53:29 +07:00
ad565c15ca Remove question mark 2024-04-15 15:39:43 +07:00
a0c5cec31e Fix Notifications Page 2024-04-15 15:36:18 +07:00
fb4901be9f add log when extend expiraton 2024-04-15 14:35:36 +07:00
a164b345b6 dont send if message empty 2024-04-15 14:30:51 +07:00
8f07c7640c edit changelog 2024-04-15 14:15:15 +07:00
8891cd5aaa allow extend expired for postpaid customer 2024-04-15 14:09:02 +07:00
854fd54834 delete $_c = $config; as it already exists in init.php 2024-04-15 14:08:34 +07:00
21876601ba Hide Tax Settings as it still have a bug 2024-04-15 11:13:19 +07:00
6955d3fd8b Merge pull request #173 from Focuslinkstech/Development
Update: Tax System
2024-04-15 09:10:08 +07:00
d6510dffa7 Merge pull request #175 from agstrxyz/patch-9
Update home.php
2024-04-15 09:07:01 +07:00
419595554b Update home.php
fix token to prevent double recharge
2024-04-15 09:06:26 +07:00
bcc84aed9a Merge pull request #174 from agstrxyz/patch-8
Update cron.php
2024-04-15 09:01:02 +07:00
05caee1193 Merge branch 'Development' into patch-8 2024-04-15 09:00:53 +07:00
071feb3a48 Merge pull request #172 from ahmadhusein17/patch-19
Update cron.php
2024-04-15 08:54:48 +07:00
a5774fe335 Merge pull request #171 from ahmadhusein17/patch-18
Update cron_reminder.php
2024-04-15 08:53:13 +07:00
92a2690ec6 Update home.php 2024-04-14 21:13:11 +07:00
519bef21e0 Update home.php
fix user self recharge in user dashboard for radius plan base
2024-04-14 06:45:45 +07:00
1a40606720 Update cron.php
Fix auto renewal radius plan based
2024-04-14 06:40:47 +07:00
eff79df39a Update customers.tpl
add length Menu  5, 10, 25, 50, 100 and All, as suggested by one of our member and also use 5 as default page length to make the page fit the screen when loaded
2024-04-13 18:19:09 +01:00
425ed2362b Update: Tax System
Tax System Feature Added

The Tax System feature allows you to apply taxes to the prices of Internet plans. This feature is useful for businesses that are required to collect taxes on their services. With the Tax System, you can define tax rates based on your local tax regulations.

Enable Tax System: Choose whether to enable or disable the Tax System. When enabled, taxes will be calculated and added to the prices of Internet plans.

Tax Rate: Select from predefined tax rates such as 0.5%, 1%, 1.5%, 2%, 5%, and 10%. These rates are commonly used and can be selected easily.

Custom Tax Rate: If you have a specific tax rate that is not listed, you can enter a custom tax rate. This allows flexibility in configuring the tax rate to match your local tax requirements.
2024-04-12 19:42:12 +01:00
1fdf1d9573 Update cron.php
Changes made:
 1. Use the $recharges variable to hold the query results to clarify the context.
 2. Use the ternary operator to determine whether the application is running in a CLI environment or not
 3. Simplify the logic by combining several redundant code blocks.
 4. Unify Mikrotik client retrieval logic based on type (Hotspot or PPPOE) to reduce code duplication.
 5. Tidy up the indents to make them consistent and easier to read.
2024-04-08 21:21:54 +07:00
b893827463 Update cron_reminder.php
Improve the writing so that it is easy to read and understand (⁠.⁠ ⁠❛⁠ ⁠ᴗ⁠ ⁠❛⁠.⁠)
2024-04-08 21:12:01 +07:00
aa756fceb1 Merge pull request #166 from ahmadhusein17/patch-12
Update indonesia.json
2024-04-08 20:19:22 +07:00
186dd5571f Merge pull request #162 from ahmadhusein17/patch-9
Update user-login.tpl
2024-04-06 15:14:43 +07:00
14067f2917 Merge pull request #163 from ahmadhusein17/patch-10
Update voucher.tpl
2024-04-06 15:13:48 +07:00
887a0185fa Merge pull request #165 from ahmadhusein17/patch-13
Update header.tpl
2024-04-06 15:13:02 +07:00
88969526be Merge pull request #168 from ahmadhusein17/patch-15
Update app-notifications.tpl
2024-04-06 15:12:40 +07:00
eb18eebc8c Merge pull request #169 from ahmadhusein17/patch-16
Update indonesia.json
2024-04-06 15:11:51 +07:00
e274ca82b0 Merge branch 'Development' into patch-16 2024-04-06 15:11:40 +07:00
9ec8b54435 Merge pull request #167 from ahmadhusein17/patch-14
Update indonesia.json
2024-04-06 15:10:37 +07:00
9dba708c2c Update indonesia.json 2024-04-06 00:33:29 +07:00
cbbb77b636 Update app-notifications.tpl
Add language to the placeholder
2024-04-06 00:29:45 +07:00
1733472ad1 Update indonesia.json
Add language to customer notifications
2024-04-06 00:01:37 +07:00
11c111805d Update header.tpl
Additional Privacy and toc translations
2024-04-05 23:22:59 +07:00
4c35e79a16 Update indonesia.json
Language improvements and additions
2024-04-05 23:20:59 +07:00
fc1cc54378 Update voucher.tpl
Fix unresponsive buttons on mobile phone display
2024-04-05 22:02:26 +07:00
f62e7707a1 Update user-login.tpl
Add a lock icon to the password
2024-04-05 21:35:19 +07:00
bab56be9c7 change to username if country code empty 2024-04-05 18:01:11 +07:00
0422c1e9bb allow [[plan]] and [[package]] to be replaced with plan name 2024-04-05 17:37:41 +07:00
1f5033b471 remove [[bills]] if there no bills found 2024-04-05 17:21:06 +07:00
53a309fee8 Fix recharge friend 2024-04-05 11:18:28 +07:00
766ba59734 add new field trx_invoice to tbl_payment_gateway, to know which transaction is for 2024-04-05 10:42:30 +07:00
2e3e5d2b84 add new variable to notification settings 2024-04-05 09:43:07 +07:00
e285e53887 Total Bills 2024-04-05 09:40:11 +07:00
afd75d757e add full name in invoice 2024-04-05 09:35:05 +07:00
006693982b fix sending notif package 2024-04-04 17:42:28 +07:00
71437b9a0e Prevent double submit for recharge and renew 2024-04-04 15:27:13 +07:00
eba6048abf Add Bills to Reminder 2024-04-04 15:02:16 +07:00
f97651695d add Note to reminder 2024-04-04 15:01:45 +07:00
72c3ff6750 Lang Internet Plan 2024-04-04 14:53:11 +07:00
787f666efe Merge pull request #161 from Focuslinkstech/Development
Patch Update
2024-04-04 14:52:20 +07:00
5db8df0c3e Patch Update
customers list tables replaced with DataTables
2024-04-03 23:39:31 +01:00
f77c96f3c3 Change to Username if Country code empty 2024-04-03 11:14:50 +07:00
ffd9f2e524 Merge pull request #160 from agstrxyz/patch-6
Update logs-radius.tpl
2024-04-03 10:32:24 +07:00
366208d6d1 Merge pull request #159 from agstrxyz/patch-5
Update logs.tpl
2024-04-03 10:31:55 +07:00
db28570610 Merge pull request #158 from agstrxyz/patch-4
Update logs.php
2024-04-03 10:31:23 +07:00
feaf88fc00 Update logs-radius.tpl
add export to csv button
2024-04-03 02:37:09 +07:00
4bd5e399de Update logs.tpl
add export to csv button
2024-04-03 02:34:39 +07:00
76047a6b39 Update logs.php
Export to csv
2024-04-03 02:32:30 +07:00
68c9ab0b2e 2024.4.2 2024-04-02 14:08:03 +07:00
198dfee3cc fix package 2024-04-02 10:23:06 +07:00
5161874cf2 $ui->display will show json for api 2024-04-01 13:48:58 +07:00
254fd4ccf7 fix rest api, need to change every variable to readable 2024-04-01 13:01:21 +07:00
ee73621c85 Found lazy way to create api 2024-03-31 21:23:19 +07:00
4bf6f9c0ac Fix API Structure 2024-03-30 12:04:30 +07:00
3a2e7c9192 remove $_L 2024-03-30 12:03:12 +07:00
dcbb9434d6 Merge pull request #155 from Focuslinkstech/Development
Update hotspot.tpl
2024-03-29 16:49:09 +07:00
faca5d0359 Merge pull request #154 from gerandonk/Development
Fix Ip Log for cloudflare tunnel
2024-03-29 16:38:27 +07:00
aeddc86796 Merge pull request #153 from ahmadhusein17/patch-8
Update indonesia.json
2024-03-29 16:37:53 +07:00
c34a34ee8e Update hotspot.tpl
List rearrangement
2024-03-28 23:31:53 +01:00
7b0bc12e98 Fix Ip Log for cloudflare tunnel 2024-03-28 23:20:14 +07:00
8ff84b2c01 Update indonesia.json
Language improvements
2024-03-28 20:03:45 +07:00
954a49978c Show Personal/Bussines in Plan Customer Dashboard 2024-03-28 18:55:10 +07:00
773cfe0139 update Client.php routerOS 2024-03-28 18:53:41 +07:00
7eae86d861 Merge pull request #150 from agstrxyz/patch-1
Update indonesia.json
2024-03-28 18:44:28 +07:00
ea9974f668 Merge pull request #152 from ahmadhusein17/master
Update english.json
2024-03-28 18:43:52 +07:00
eda1750608 Merge pull request #151 from ahmadhusein17/Development
Language improvements
2024-03-28 18:43:40 +07:00
9a1c264173 Merge branch 'Development' into Development 2024-03-28 18:43:32 +07:00
6865b388d0 Merge branch 'Development' into master 2024-03-28 18:41:33 +07:00
ef15ec0ae2 Send Email Function 2024-03-27 14:32:55 +07:00
e0d21e6284 price + $add_cost in telegram 2024-03-27 11:42:17 +07:00
37a7da614e Fixing Pagination, more Simple 2024-03-27 09:44:48 +07:00
e11ab5ba01 remove print_r 2024-03-26 15:46:45 +07:00
0767c6ab23 Change paginator, to make easy customization using pagination.tpl 2024-03-26 14:39:28 +07:00
8e90cf933b Update english.json
Language improvements
2024-03-26 00:47:57 +07:00
a5ffee688c Language improvements 2024-03-26 00:40:54 +07:00
36a24238ef Fix Cancel 2024-03-25 10:27:06 +07:00
7eda29d02c Update indonesia.json 2024-03-24 19:20:54 +07:00
e709ea4353 fix maps when http 2024-03-24 13:39:00 +07:00
18967b59e2 Handle Http for maps 2024-03-24 13:35:31 +07:00
3c2ca66b48 fix sql 2024-03-23 17:46:20 +07:00
63c364a6c5 Merge pull request #149 from siavashmirtaheri/patch-1
Update country.json Iran-Persian
2024-03-23 17:45:33 +07:00
338861a630 Change to icon 2024-03-23 15:34:44 +07:00
90f72852ca Update country.json
IR translate start
2024-03-23 11:45:58 +03:30
5426d9f35f show maps on customer view 2024-03-23 12:56:25 +07:00
58c4037d8c full height maps 2024-03-23 12:44:17 +07:00
04a21d3eb2 Maps always show Tooltip 2024-03-23 12:38:23 +07:00
273d98f3ad map-customer.tpl to customer-map.tpl 2024-03-23 12:16:42 +07:00
177cdef1cd Add Location Picker 2024-03-22 21:21:23 +07:00
ffe913cb8f .htaccess allow update.php 2024-03-22 20:29:05 +07:00
75955de6c5 Fix Broadcast Message by @Focuslinkstech 2024-03-22 10:40:51 +07:00
11d97c153f Merge pull request #142 from Focuslinkstech/Development
bulk SMS/WA message improvement
2024-03-22 10:30:56 +07:00
44cded581a Enhancement in bulk SMS/WA message
Enhancement in  SMS/WA message sending
2024-03-21 16:52:52 +01:00
b8ae562367 2024.3.20 2024-03-20 16:06:42 +07:00
d6bcb4edfc Merge branch 'master' into Development 2024-03-20 09:55:27 +07:00
5d16ff9484 show prepaid or postpaid in list 2024-03-20 09:54:48 +07:00
c1f815535d compiled folder missing in installation 2024-03-20 09:29:40 +07:00
37a8187f5a delete unused file 2024-03-20 09:28:10 +07:00
ec5aeedd1b Merge pull request #140 from gerandonk/Development
fix validity period is more than one month
2024-03-20 09:28:00 +07:00
7dd27e3080 Merge pull request #139 from Focuslinkstech/Development
Update message.php
2024-03-20 09:27:47 +07:00
93ca9fa586 Update customers-view.tpl
add account type
2024-03-19 19:23:34 +01:00
de302d2656 Update customers-add.tpl
fix customer add
2024-03-19 18:59:05 +01:00
4d8cec1a88 Merge branch 'hotspotbilling:Development' into Development 2024-03-19 18:46:54 +01:00
477dd11caa fix validity period is more than one month 2024-03-19 23:54:49 +07:00
36eb5ebd3b fix 1 payment gateway 2024-03-19 20:47:31 +07:00
6e2e907d85 move account_type 2024-03-19 19:05:35 +07:00
c460cdd2d6 Merge branch 'master' into Development 2024-03-19 19:00:21 +07:00
5b7683ae30 Update message.php
fix placeholder bugs
2024-03-19 12:27:38 +01:00
ea743b6db6 update plan type 2024-03-19 18:21:38 +07:00
1a165662ca Merge pull request #136 from Focuslinkstech/Development
Update map-customer.tpl
2024-03-19 18:10:54 +07:00
21058d5c4e Update map-customer.tpl
fix Map
2024-03-19 09:08:30 +01:00
af3995b421 plan price to Note 2024-03-19 11:38:32 +07:00
e9240f462d Merge branch 'development' 2024-03-19 11:05:42 +07:00
5b3be79420 2024.3.19 2024-03-19 11:05:08 +07:00
8f595af9a1 Fix map url 2024-03-19 10:22:54 +07:00
393a1195a5 Merge pull request #135 from pro-cms/master
Added Business/Personal System
2024-03-19 09:46:16 +07:00
0dd12b717d Merge branch 'Development' into master 2024-03-19 09:46:08 +07:00
d7d6709944 Merge pull request #134 from ahmadhusein17/patch-3
Update message-bulk.tpl
2024-03-19 09:41:25 +07:00
ef187817cf Merge pull request #131 from Focuslinkstech/Development
add send message button
2024-03-19 09:36:40 +07:00
24e45db017 break; the line 2024-03-19 09:34:28 +07:00
0a67ea25b5 Update phpnuxbill.sql
add coordinates
2024-03-19 01:10:19 +01:00
f27964dde6 map and customer geo location added
added map and customer geo location, we advice you to change/edit the customer coordinates according to their location, so that you can see where the customer is located on the Map
2024-03-19 00:59:34 +01:00
5b0e782efd fix syntax phpnuxbill.sql 2024-03-19 00:12:38 +03:00
865df09116 fixed account type ui 2024-03-18 23:28:16 +03:00
f44d800400 edit ,add customer type 2024-03-18 23:25:39 +03:00
aae5b58d57 added edit customer account type 2024-03-18 23:23:52 +03:00
19d60da919 added plan type to order user account 2024-03-18 23:12:23 +03:00
7be8552784 added plan type to service class 2024-03-18 22:55:08 +03:00
b92efe3d30 added plan type to front ui 2024-03-18 22:50:46 +03:00
f769e7b798 added plan type to listing 2024-03-18 22:40:27 +03:00
15ae5c844f added plan_type and account_type 2024-03-18 22:33:10 +03:00
0aff5f437a Update message-bulk.tpl
Removed translation in placeholder contents
2024-03-18 19:57:55 +07:00
605fbb73a6 fix translation error
fix translation error
2024-03-18 13:52:33 +01:00
3d2af75e5b add send message button
add send message button in customer
 view details
2024-03-18 12:28:54 +01:00
130451e1ae Fix notification 2024-03-18 11:48:22 +07:00
d36f39af8f Merge pull request #130 from Focuslinkstech/Development
send single and Bulk SMS, WhatsApp or Both WA/SMS message to customers
2024-03-18 11:05:03 +07:00
518917aac6 Add Message Feature
you can now send single and Bulk SMS, WhatsApp or Both WA/SMS message to customers based on their groups, more groups will be added later
2024-03-18 01:35:48 +01:00
dbc3a2623c Update customers.tpl
Functionality to filter table rows based on admin input
2024-03-17 15:56:42 +01:00
d31edde9d6 prepaid to plan file 2024-03-16 20:41:24 +07:00
32943b40be Fix Bills Zero 2024-03-16 20:41:24 +07:00
23790d3258 Merge pull request #129 from gerandonk/Development
Fix loop disconnect to all Nas
2024-03-16 20:24:25 +07:00
ffa55cdee5 Fix loop disconnect to all Nas
Fix loop disconnect to all Nas but still detecting Hotspot Multylogin from other Nas
2024-03-16 19:50:45 +07:00
6f5d49cd2f Show Paid 2024-03-15 10:56:08 +07:00
850581d328 Fix instalment finished 2024-03-15 10:48:17 +07:00
1d0d3f13ab 2024.3.14 2024-03-15 10:43:49 +07:00
c82b6b6acf Change Attribute to Bill Only 2024-03-15 10:38:05 +07:00
532fbf7337 Active plan on user page 2024-03-15 09:46:01 +07:00
c4afd6da7f Additional Cost at Cron 2024-03-15 09:29:15 +07:00
a812e3a3e0 Merge pull request #128 from gerandonk/Development
postpaid always zero for first time recharge and invoice atribute for…
2024-03-15 09:24:02 +07:00
a15510e62a postpaid always zero for first time recharge and invoice atribute for next month
for postpaid customer invoice reminder and order get from invoice attribute
2024-03-15 04:07:30 +07:00
78d1634470 Send plan to friend will pay for Additional Cost 2024-03-14 14:55:49 +07:00
cc8d810d45 Additional Cost Customer side 2024-03-14 14:42:20 +07:00
68d3c9181c View Invoice from Customer side 2024-03-14 13:40:44 +07:00
e206a583fd Additional Cost, and Confirm Recharge 2024-03-14 12:14:11 +07:00
ca27c47b75 fix get attributes 2024-03-14 11:38:32 +07:00
2c67108cf1 add Additional Cycle and check if price is zero 2024-03-14 10:28:36 +07:00
dee4c78e93 Change Menu Names 2024-03-13 16:59:12 +07:00
a6c004e1cb $day_exp 2024-03-13 16:33:06 +07:00
8318bb4e6b Merge branch 'Development' 2024-03-13 16:29:44 +07:00
b27e0adca9 Fix onclick prepaid 2024-03-13 16:29:22 +07:00
2925d3a1e3 Merge branch 'Development' 2024-03-13 15:51:23 +07:00
add28c2fca Merge pull request #124 from Focuslinkstech/Development
Update dashboard.php
2024-03-13 15:41:57 +07:00
afbab3dd42 Update dashboard.php
fix reporting
2024-03-13 09:34:57 +01:00
b68e4d2e68 2024.3.13 2024-03-13 14:54:36 +07:00
c8f4574984 Recharge with additional Cost 2024-03-13 14:53:33 +07:00
60c573821b Additional Cost from Customer Attributes 2024-03-13 14:48:01 +07:00
e6e993cf21 Expired day postpaid 2024-03-13 14:40:47 +07:00
ca0edb4e17 Postpaid 2024-03-13 14:32:10 +07:00
ed9a411095 Fix install Plugin 2024-03-13 09:37:45 +07:00
c69fb1cae2 Merge branch 'Development' 2024-03-12 16:40:58 +07:00
d30aadc5e4 Expired Date by created date 2024-03-12 16:39:01 +07:00
b732cfd90e Recharge with balance or zero cost 2024-03-12 16:39:01 +07:00
46a56c12e3 admin can recharge disabled plan 2024-03-12 16:39:01 +07:00
9b2d42610a delete allow_purchase in cron 2024-03-12 16:39:01 +07:00
ef85bdb02f Invoice number not Random 2024-03-12 16:39:01 +07:00
23763ed308 Period in hotspot 2024-03-12 16:39:00 +07:00
9fcdf04005 Show From Customer 2024-03-12 16:39:00 +07:00
60babfa7b5 Change button 2024-03-12 16:39:00 +07:00
4cdde32cb1 Multiple Payment gateway Fix 2024-03-12 16:39:00 +07:00
538850b323 delete button 2024-03-12 16:39:00 +07:00
47393b4da9 Delete Plugin 2024-03-12 16:39:00 +07:00
87167b7770 change path 2024-03-12 16:39:00 +07:00
81572a61a4 delete payment gateway 2024-03-12 16:39:00 +07:00
3412ecc7de Fix Logic Multiple Payment gateway 2024-03-12 16:39:00 +07:00
3ab38897f9 change path to /gateway/ 2024-03-12 16:39:00 +07:00
8c2471d1d2 delete none 2024-03-12 16:39:00 +07:00
b0937a424a .htaccess Firewall 2024-03-12 16:39:00 +07:00
171b938d3a Check if Period Validity 2024-03-12 16:39:00 +07:00
61c1d25096 We are excited to introduce a new feature
I am delighted to announce that a highly requested feature has been added to Nuxbill! We now support Multiple Payment Gateways, allowing customers to choose their preferred payment method. This update brings greater flexibility and convenience to our users.
2024-03-12 16:39:00 +07:00
f885b8e8a3 Update dashboard.php
Fix when user purchase services with his/her balance it wont be added as income because the balance has been added earlier
2024-03-12 16:39:00 +07:00
2bb664e241 Expired Date by created date 2024-03-12 15:28:32 +07:00
c9058769ce Recharge with balance or zero cost 2024-03-12 15:09:00 +07:00
6d15437333 admin can recharge disabled plan 2024-03-12 13:58:42 +07:00
7c5958c8c1 delete allow_purchase in cron 2024-03-12 13:46:40 +07:00
1a4a0f2c10 Invoice number not Random 2024-03-12 12:12:36 +07:00
629d9e8ed4 Period in hotspot 2024-03-12 12:01:49 +07:00
b9e987570c Show From Customer 2024-03-12 11:54:20 +07:00
b95788262d Change button 2024-03-12 11:48:17 +07:00
3bb55320e3 Multiple Payment gateway Fix 2024-03-12 11:17:05 +07:00
7a9f937a9e delete button 2024-03-12 10:43:34 +07:00
c00e51adda Delete Plugin 2024-03-12 10:42:42 +07:00
0cc526e29a change path 2024-03-12 10:00:40 +07:00
16f0642007 delete payment gateway 2024-03-12 10:00:28 +07:00
e1f7b324cb Fix Logic Multiple Payment gateway 2024-03-12 09:33:45 +07:00
8f0ff3e786 change path to /gateway/ 2024-03-12 09:24:16 +07:00
9023f89456 delete none 2024-03-12 09:23:59 +07:00
140b756994 .htaccess Firewall 2024-03-12 09:07:12 +07:00
ca59c89e1d Check if Period Validity 2024-03-12 09:07:12 +07:00
4e23918999 Merge pull request #122 from Focuslinkstech/Development
We are excited to introduce a new feature
2024-03-12 09:06:43 +07:00
758a0a99a9 We are excited to introduce a new feature
I am delighted to announce that a highly requested feature has been added to Nuxbill! We now support Multiple Payment Gateways, allowing customers to choose their preferred payment method. This update brings greater flexibility and convenience to our users.
2024-03-11 09:34:25 +01:00
b6cf9bec0b Merge pull request #121 from Focuslinkstech/Development
Update dashboard.php
2024-03-11 14:43:13 +07:00
6e07c3ae85 Update dashboard.php
Fix when user purchase services with his/her balance it wont be added as income because the balance has been added earlier
2024-03-10 22:41:48 +01:00
ef76aadc16 Merge pull request #120 from hotspotbilling/Development
fix delete customer attribute
2024-03-08 17:50:06 +07:00
8e960107fc Merge pull request #119 from Focuslinkstech/Development
Bug Fix
2024-03-08 17:47:44 +07:00
c4e702ee2f Update customers.php
Fix Delete the Customers Attributes with the given field name, it delete all from the table which belong to other customers
2024-03-08 10:43:07 +01:00
08790e7295 Merge branch 'Development' of https://github.com/Focuslinkstech/phpnuxbill into Development 2024-03-08 09:37:56 +01:00
cfefd38a31 if ($p['validity_unit'] == 'Period') then add Expired Date 2024-03-06 12:03:24 +07:00
37a5ee8566 Change the view of Attributes Customer 2024-03-06 11:15:45 +07:00
e5c8aae758 2024.3.5 2024-03-05 16:20:18 +07:00
99d393d0c0 Merge pull request #118 from gerandonk/Development
change due date for period plan to customer field attribute
2024-03-05 16:18:32 +07:00
e6280d597b change due date for period plan to customer field attribute
admin can change expired date for period plan as wish before recharger customer
2024-03-05 16:08:33 +07:00
18db9cd280 hide if balance off 2024-03-05 11:15:38 +07:00
6aab647f48 Company name in login 2024-03-05 11:15:26 +07:00
b8b4623078 notification variable fix 2024-03-04 14:26:36 +07:00
6a79cff233 checkUserType when edit is neq 2024-03-04 11:30:09 +07:00
4c02283fd0 add full name in telegram notification 2024-03-04 10:06:19 +07:00
403de91fba sendPackageNotification with customer variable 2024-03-04 10:02:23 +07:00
4ee3743cf3 Fix Password send to admin 2024-03-04 09:57:12 +07:00
77e48dae8b add is file exists 2024-03-03 19:54:04 +07:00
0745532951 2024.3.3 2024-03-03 17:29:53 +07:00
b53116d22a Customer Announcement 2024-03-03 17:24:01 +07:00
f7df824145 Merge pull request #116 from gerandonk/Development
Development
2024-03-03 17:11:38 +07:00
f154322f99 Merge pull request #115 from Focuslinkstech/master
improvement
2024-03-03 17:10:06 +07:00
a76ba6ee8b update db for validity period 2024-03-03 11:30:34 +07:00
61b3f5b5f5 Add planwith validity period 2024-03-03 11:03:25 +07:00
b153e5b595 distinguish between announcements on the user dashboard and the login page 2024-03-03 11:00:42 +07:00
9ab0b6a0fa improvement
just replace the save loading with css for better loading feature
2024-03-02 12:40:04 +01:00
a7f191f058 damn, that curly bracket make error :)) 2024-03-01 19:42:59 +07:00
012a1ecfab allow purchase = no, but can recharge 2024-03-01 16:10:01 +07:00
dc70a49f52 upload path 2024-03-01 13:44:46 +07:00
bc7380eab7 add variable to global 2024-03-01 10:36:24 +07:00
f4da09a26e move hook before sending notification 2024-03-01 10:11:18 +07:00
de3312055a add hook when recharge 2024-03-01 09:57:59 +07:00
699289662b Fix Upload URL 2024-03-01 09:37:13 +07:00
bae079f71c Fix Hook Functionality 2024-02-29 13:32:46 +07:00
28f4624e8d change Customer menu 2024-02-29 11:37:54 +07:00
fbd215e741 Merge branch 'master' into Development 2024-02-29 09:26:19 +07:00
2437096473 $_c to $config in php file 2024-02-29 09:25:26 +07:00
dfeee540cf Fix variable $_c 2024-02-28 18:19:17 +07:00
a0b9e85f38 Add Expired date for reminder 2024-02-28 11:31:36 +07:00
08153e6ec1 Fix Buy Plan with Balance 2024-02-28 11:31:31 +07:00
2660f5d2d0 Dashboard 2 Column 2024-02-27 14:22:17 +07:00
82e67f0b83 fix Recharge 2024-02-27 13:12:53 +07:00
41dd0d86e7 Fix Recharge 2024-02-27 13:12:25 +07:00
c8004f1a27 fix update file 2024-02-27 13:10:06 +07:00
61edfb932a fix wrong logic != to == 2024-02-27 12:00:49 +07:00
747a67b691 2024.2.27 2024-02-27 10:39:21 +07:00
b938db9e5d redirect after login 2024-02-27 10:37:41 +07:00
1ec8049068 fix path 2024-02-27 10:32:09 +07:00
848dcb5caf fix variable Admin.php 2024-02-27 07:12:02 +07:00
afe6b34fd6 Update Package.php
fix package recharge bug
2024-02-26 18:03:48 +01:00
fceb79bdc3 fix sql installer 2024-02-26 15:39:23 +07:00
83457fd9fc Remove unused font, too big 2024-02-26 15:18:54 +07:00
cdd5da757d 2024.2.26 2024-02-26 15:04:57 +07:00
c6086c615f Error Info 2024-02-26 15:02:36 +07:00
0cad73a17f Remove unused file 2024-02-26 14:42:54 +07:00
d2fa9be8d1 Path Configuration 2024-02-26 14:38:04 +07:00
617e628b04 Remove unused js, css and font 2024-02-26 11:43:57 +07:00
35d679ed2c Menu With Auth 2024-02-26 11:25:15 +07:00
8824489704 Formatting 2024-02-26 11:10:52 +07:00
a7502aa8fb Admin Permisions 2024-02-26 11:01:54 +07:00
375403135e 2024.2.23.1 2024-02-23 15:04:53 +07:00
db49d0f4b5 Fix variable customer 2024-02-23 14:57:00 +07:00
c4fb99479b fix resend 2024-02-23 14:54:28 +07:00
091f4fb638 Fix Cookies Admin 2024-02-23 14:52:10 +07:00
8db3d6c679 update changelog 2024-02-23 14:44:37 +07:00
ddd7fb49fe Fix invoice 2024-02-23 14:40:47 +07:00
c6a203b1f0 Add Alert Page 2024-02-23 14:20:12 +07:00
6de63bed63 Integrate with PhpNuxBill Printer 2024-02-23 11:39:25 +07:00
9552a14de5 add button print 2024-02-22 18:37:28 +07:00
9d379b3fbd Phpnuxbill android printer support 2024-02-22 18:27:18 +07:00
4f3e5972b0 Merge pull request #112 from Focuslinkstech/Development
Update accounts.php
2024-02-22 11:45:29 +07:00
be65976310 link to settings when hide widget 2024-02-22 11:42:17 +07:00
8728af4332 Add Loading when click submit 2024-02-22 11:41:55 +07:00
07870d05ad Update accounts.php
Fix OTP not sending bug
2024-02-21 11:58:13 +01:00
cee6f8949c Merge branch 'Development' 2024-02-21 16:15:21 +07:00
3bdf44ddbe Merge pull request #111 from Focuslinkstech/Development
Bug Fix: OTP bugs
2024-02-21 16:13:26 +07:00
17c1675b4a Update accounts.php
fix lang function
2024-02-21 10:13:05 +01:00
54d1c4439d Bug Fix: OTP bugs
add phone number validation to prevent invalid phone number, phone number must be 10 digits up

fix issue with updating phone number without OTP
2024-02-21 10:02:31 +01:00
e710bd2862 Merge branch 'Development' 2024-02-21 14:38:09 +07:00
5309cb26db Delete Table Responsive, first Column Freeze 2024-02-21 14:37:44 +07:00
8072fe40eb change burst form 2024-02-21 14:11:19 +07:00
702f2b443c remove multiple spaces 2024-02-21 11:54:22 +07:00
a44190c1c2 delete meta table 2024-02-21 11:11:14 +07:00
3871b51f0f change position table customer field 2024-02-21 11:11:13 +07:00
d9a20f7213 Merge pull request #110 from Focuslinkstech/Development
Update: New Features "Miscellaneous"
2024-02-21 11:10:54 +07:00
a70b954981 Update: New Features "Miscellaneous"
[option] OTP is required when user want to change phone number.

admin can choose option in
 [Miscellaneous]
2024-02-21 00:15:36 +01:00
95e79439a2 delete meta table 2024-02-20 20:01:26 +07:00
7ea118ec1e change position table customer field 2024-02-20 18:32:23 +07:00
ae83cbeef4 Fix Voucher Permission 2024-02-20 16:49:03 +07:00
8047ed9555 remaining last login 2024-02-20 16:48:48 +07:00
c907a4044f Fix Voucher View 2024-02-20 16:48:27 +07:00
f12c7724fd fix 1 account can have 1 pppoe and 1 hotspot in 1 router 2024-02-20 13:54:46 +07:00
c8696f8d1a clear compiled after update 2024-02-20 11:34:08 +07:00
63bba0efb0 2024.2.20 2024-02-20 11:01:02 +07:00
2063ae4159 Fix Admin List for Admin 2024-02-20 10:58:50 +07:00
349a1d3250 add to Address List 2024-02-20 10:07:17 +07:00
cfb81596ae Burst Limit 2024-02-20 10:07:17 +07:00
91c90f05f8 Merge pull request #109 from Focuslinkstech/Development
new feature: Pace Loading
2024-02-20 09:42:15 +07:00
abefcf4a73 new feature: Pace Loading
Pace Loading added
2024-02-19 23:42:29 +01:00
f9ad13b746 2024.2.19 2024-02-19 16:31:01 +07:00
fe082258cd creating API, Work in Progress 2024-02-19 16:28:55 +07:00
ade714e2ae View Admin and Init script 2024-02-19 14:24:34 +07:00
ce649220f5 indonesian lang 2024-02-19 09:53:53 +07:00
de4a783dba Language editor 2024-02-19 09:52:36 +07:00
f550af257a fix customer custom field 2024-02-19 09:29:11 +07:00
2c16bb289e any Users can change password 2024-02-19 09:13:19 +07:00
61060c4173 Select Agent after choose sales 2024-02-19 09:13:19 +07:00
e7c715f1b3 Merge pull request #107 from Focuslinkstech/Development
New Feature Added "Custom Fields"
2024-02-19 09:12:18 +07:00
aa8fa3f436 update
admin can add more fields when editing customers
2024-02-18 04:56:30 +01:00
941c723193 New Feature Added "Custom Fields"
admin can now add unlimited Custom Fields, and also edit or delete the Custom Fields
2024-02-17 19:30:35 +01:00
cb23ddb912 Sales are below agent, but admin add sales not yet select Agent 2024-02-16 17:26:15 +07:00
e1272ec531 print 1 voucher will go to print or share 2024-02-16 17:26:15 +07:00
8e3e715c8c trash icon 2024-02-16 17:26:15 +07:00
850ae079f4 Merge pull request #106 from Focuslinkstech/Development
Update: SweetAlert Introduction
2024-02-16 17:24:31 +07:00
21bea606c3 Update: SweetAlert Introduction
Introducing SweeAlerts for Notifications
2024-02-16 10:03:35 +01:00
11c226caf5 Sales, sub sccount Agent 2024-02-16 14:54:43 +07:00
98fb853591 set Permission 2024-02-16 14:52:49 +07:00
d17c434c7b Add Edit Admin 2024-02-15 16:13:55 +07:00
a06d7db0b1 Change Error Page 2024-02-15 11:00:59 +07:00
84138bd02e Merge pull request #105 from Focuslinkstech/Development
add new menu "Radius"
move Radius NAS from Network to Radius
2024-02-15 10:37:37 +07:00
9d1f05735f update
add new menu "Radius"
move Radius NAS from Network to Radius
2024-02-14 10:14:24 +01:00
c91cc0470b 2024.2.13 2024-02-13 17:43:19 +07:00
459b9b30f1 Auto translate Fix 2024-02-13 17:41:55 +07:00
8baf977a9a delete other lang 2024-02-13 16:25:12 +07:00
1022674780 Stay Collapse 2024-02-13 16:22:00 +07:00
3c9b05468e Auto Translate Language 2024-02-13 13:54:01 +07:00
e9f5d56f91 Update CHANGELOG 2024-02-12 17:04:38 +07:00
792b1367d3 UserType 'SuperAdmin','Admin','Report','Agent','Sales' 2024-02-12 17:02:43 +07:00
bf6ec9d4cd export csv 2024-02-12 11:35:59 +07:00
9543ee6e34 Session using cookie 2024-02-12 09:45:44 +07:00
66432eda56 2024.2.7 2024-02-07 13:35:23 +07:00
92eee8245d timeElapsed 2024-02-07 13:32:33 +07:00
f62f07d102 add Hide Dashboard Content 2024-02-07 12:02:39 +07:00
671154d146 add sub sales 2024-02-07 10:11:30 +07:00
ac84e4b235 settimezone 2024-02-07 09:39:49 +07:00
db7c6014dc Fix invoice keyword 2024-02-06 17:41:45 +07:00
21b57ef471 Fix price for logging 2024-02-06 16:54:57 +07:00
79e5c72ca2 2024.2.6 2024-02-06 16:48:59 +07:00
5921fef67e cache Voucher stocks for 5 Minutes 2024-02-06 16:46:50 +07:00
1e0b246d74 Cache for 12 hours 2024-02-06 16:43:06 +07:00
009c890ab6 Fix router_name for log 2024-02-06 16:41:41 +07:00
f3d7687cdb cache dashboard graph 2024-02-06 16:41:26 +07:00
80cecabfb0 Fix Calculation 2024-02-05 14:25:23 +07:00
00ac91903f Merge pull request #103 from Focuslinkstech/master
Dashboard Updates
2024-02-05 14:19:37 +07:00
500f3de6a9 Update dashboard.tpl
fixed inactive users in graph
2024-02-05 08:17:10 +01:00
6c2658bf03 Update dashboard.tpl
change all users to total users
2024-02-05 07:41:15 +01:00
59de353353 Merge branch 'hotspotbilling:master' into master 2024-02-05 07:33:47 +01:00
d5ea56d078 Update dashboard.tpl
change active users to All Users Insight
add All users to graph
2024-02-05 07:24:32 +01:00
7cc8034b8c 2024.2.5 2024-02-05 10:08:10 +07:00
c3a76bab90 Language add 2024-02-05 10:05:41 +07:00
8f32a7cfa9 Merge pull request #102 from Focuslinkstech/master
Dashboard update
2024-02-05 09:45:37 +07:00
cbe2602b69 Dashboard update
add monthly Sales Graph
add Monthly Registered Customers Graph
add Active Users Graph
2024-02-04 20:25:31 +01:00
771bc9d8d9 Fix edit plan for user 2024-02-02 13:40:08 +07:00
788e558171 activate plan when its on 2024-02-02 13:39:03 +07:00
4ab32bc68d Fix Edit Plan 2024-02-02 13:38:22 +07:00
bba09ca647 activate customer when edit Expired 2024-01-29 11:34:07 +07:00
adbac642ca 2024.1.24 2024-01-24 15:06:36 +07:00
7e7b70ba75 Add test SMS, WA and Telegram 2024-01-24 14:02:58 +07:00
72fbc27f97 2024.1.19 2024-01-19 09:27:22 +07:00
d386dc5eec Sell your own plugin 2024-01-19 09:24:24 +07:00
41481880ab support full package 2024-01-19 09:22:43 +07:00
f8a879dc0f paymentgateway to paymentgateway folder 2024-01-19 09:09:07 +07:00
da44e3f6da codecanyon theme install 2024-01-19 09:08:49 +07:00
afdd7edafa themes support 2024-01-19 09:07:48 +07:00
4e1a10d814 Envato Personal Token 2024-01-18 17:24:59 +07:00
7046aa5ed1 CodeCanyon integration fix 2024-01-18 17:24:21 +07:00
d81ba5d5fb codecanyon integration 2024-01-18 15:41:24 +07:00
a35506db1b 2024.1.18 2024-01-18 13:33:22 +07:00
96945ab813 Merge pull request #99 from axmad386/patch-1
fix(mikrotik): set pool $poolId always empty
2024-01-18 12:00:51 +07:00
2b8ca5fd85 fix(mikrotik): set pool $poolId always empty 2024-01-18 01:55:23 +07:00
2d095aef08 fix delete logs 2024-01-17 13:42:07 +07:00
c906d47674 minor change, for plugin, menu can have notifications 2024-01-17 10:56:39 +07:00
5dd430f9b2 Formatting code 2024-01-17 10:54:31 +07:00
7c88be8865 Merge pull request #98 from Focuslinkstech/master
Nav menu label added
2024-01-17 10:39:25 +07:00
b45f5a5587 Merge branch 'hotspotbilling:master' into master 2024-01-16 22:26:57 +01:00
10e788e9a2 update
Nav label added
2024-01-16 22:19:38 +01:00
7ceb883826 fix notifications 2024-01-16 15:16:59 +07:00
80e78d9796 Fix sendPackageNotification 2024-01-16 15:08:26 +07:00
534d62d944 2024.1.16.1 2024-01-16 11:41:25 +07:00
1857c145d1 fix print 2024-01-16 11:41:12 +07:00
12cdef4f66 remove debug 2024-01-16 10:36:55 +07:00
b4bec8964d Support thermal printer for invoice 2024-01-16 10:32:59 +07:00
64f52d6c1c add [[price]] to reminder notification 2024-01-16 09:52:12 +07:00
b504723e7c fix radius pool select 2024-01-16 09:39:20 +07:00
470c219e61 Add Yellow line for plan not allowed to purchase 2024-01-16 09:00:56 +07:00
5867a0c9ca Fix Cron for 2024-01-15 10:22:03 +07:00
f38da8d3c0 Merge pull request #95 from Focuslinkstech/master
Update cron.php
2024-01-15 10:01:29 +07:00
7e0e09f9bf Merge branch 'hotspotbilling:master' into master 2024-01-14 15:32:43 +01:00
90e6283426 urgent update
fix installation database
added plan name when editing service plan
2024-01-14 13:58:46 +01:00
24df116003 Update cron.php
stop user from auto renewing packages that has been disabled for purchase.
2024-01-13 09:41:58 +01:00
db240131e2 2024.1.11 2024-01-11 15:56:43 +07:00
2fdc3c9567 Merge pull request #94 from Focuslinkstech/master
Allow Package Purchase Option Added.
admin can now decide if clients can purchase a particular package or not.

if No option is selected the package wont display in the package list
2024-01-11 15:41:52 +07:00
a953157b68 fix plugin manager 2024-01-11 10:07:56 +07:00
4ba38485a0 New Feature Added
Allow Package Purchase Option Added.
admin can now decide if user can purchase a particular package or not.

if no option is selected the package wont display in the package list
2024-01-11 01:00:34 +01:00
dfef6807a5 Merge branch 'master' of https://github.com/Focuslinkstech/phpnuxbill 2024-01-11 00:47:38 +01:00
5ef0520c74 Update updates.json
Database : add allow purchase
2024-01-11 00:47:17 +01:00
263a1b6722 Merge branch 'hotspotbilling:master' into master 2024-01-11 00:30:28 +01:00
f4c5b6a8bb Update user-dashboard.tpl
fix typo error
2024-01-10 11:51:57 +01:00
05ed37d3d8 2024.1.9 2024-01-09 10:34:19 +07:00
055b855bc1 Delete Used Voucher which not exists in tbl recharges 2024-01-08 16:12:21 +07:00
b862a759d0 Add Prefix 2024-01-08 15:39:04 +07:00
41cc04cffb 2024.1.8 2024-01-08 15:28:13 +07:00
1d29f8111e Order Expired by Expired date 2024-01-08 15:24:35 +07:00
081dd1b1b9 add nasreload table 2024-01-02 13:51:26 +07:00
9804bcb9e8 log class 2024-01-02 13:35:06 +07:00
19e39dbefc templat bug report and Feature Request 2024-01-02 11:42:08 +07:00
b5c29f6c3d Merge remote-tracking branch 'origin/Development' into Development 2024-01-02 11:35:20 +07:00
fe94ae3011 2024.1.2 2024-01-02 11:34:23 +07:00
a25112a37f add paginator
add paginator to dashboard expire user list
2024-01-02 11:33:28 +07:00
9d1d287e9a 2024.1.2 2024-01-02 11:31:41 +07:00
4bddaf0260 Merge pull request #86 from Focuslinkstech/master
add paginator
2024-01-02 11:28:27 +07:00
43ed5e452e add paginator
add paginator to dashboard expire user list
2023-12-27 20:10:56 +01:00
12c339898c Fix header user 2023-12-21 14:00:58 +07:00
d087c9625d modern-skin-dark 2023-12-21 14:00:58 +07:00
98223c1abe no skinblue 2023-12-21 14:00:58 +07:00
402660e3e1 Modern AdminLTE 2023-12-21 14:00:58 +07:00
f42f410867 #changed the AdminLTE to Modern AdminLTE Template 2023-12-21 14:00:58 +07:00
df28e2b1c2 #changed the AdminLTE to Modern AdminLTE 2023-12-21 14:00:58 +07:00
74b5c47640 Merge pull request #83 from Focuslinkstech/master
Update user-dashboard.tpl
2023-12-21 14:00:31 +07:00
5f5213527f fix alert notify 2023-12-20 09:02:39 +07:00
5e76c3e214 detect if radius 2023-12-19 16:00:14 +07:00
e2c0fa5690 Fix title 2023-12-19 11:47:40 +07:00
3afb7b9954 Remove all used voucher codes 2023-12-19 11:45:18 +07:00
13b448da69 Disable Registration 2023-12-19 11:35:49 +07:00
017518b308 Fix Searching 2023-12-19 09:55:55 +07:00
4ae19849a1 2023.12.18 2023-12-18 16:48:23 +07:00
d666e052f4 split sms to 160 only for mikrotik 2023-12-18 16:47:08 +07:00
c1f04c17a5 Update user-dashboard.tpl
add condition to display service type
2023-12-14 10:21:27 +01:00
9c22c22f6c Update Readme 2023-12-14 11:59:50 +07:00
518fe7563e 2023.12.14 2023-12-14 11:49:48 +07:00
adc2c808e2 Added user Types for Internet Packages
ability to display packages according to the user type. Hotspot users Can now only see hotspot packages
PPPoE users can now see only PPPoE Packages
Others Can see both Hotspot and PPPoE packages
2023-12-14 11:34:28 +07:00
a7a0f84df5 add new feature "service type" Hotspot PPPoE and Others
ability to display packages according to the user type.
Hotspot users Can now see only hotspot packages
PPPoE users can now see only PPPoE Packages
Others Can see both Hotspot and PPPoE packages
2023-12-14 03:21:55 +01:00
b7c663f4ee split sms characters to 160 2023-12-12 13:36:00 +07:00
dd4329ad3d remove port=usb1 channel=2 2023-12-11 15:40:18 +07:00
41b981cb70 remove debug 2023-12-11 15:21:13 +07:00
431c971f3a selected router 2023-12-11 15:08:00 +07:00
653580722e /tool sms send port=usb1 channel=2 2023-12-11 15:06:21 +07:00
6a0ad7f178 sms using Mikrotik 2023-12-11 14:12:12 +07:00
9d79121696 cek if not radius 2023-11-21 14:41:21 +07:00
8e84c32616 fix prepaid update 2023-11-21 13:47:10 +07:00
486e22f020 fix change plan for radius 2023-11-20 09:02:33 +07:00
21d83268f7 2023.11.17 2023-11-17 14:44:22 +07:00
e886249091 redirect to home 2023-11-17 14:40:02 +07:00
d5ab0e1b44 Fix Error for Customer 2023-11-17 14:38:20 +07:00
05aca0356f edit changelog 2023-11-15 11:51:13 +07:00
cced38527b deactivate login logout fix 2023-11-15 11:49:03 +07:00
452642831c fix isLogin 2023-11-15 11:45:29 +07:00
69ea0d0b7f Customer Dashboard change 2023-11-15 11:39:05 +07:00
4b596d91bd Radius demo mode 2023-11-15 11:11:25 +07:00
9c5e3007a2 Fix Change package to another Mikrotik 2023-11-15 11:08:18 +07:00
d3893d88a4 dont show balance when edit active user 2023-11-15 10:53:39 +07:00
1ed55103a3 demo mode, not connecting to real router 2023-11-15 10:36:53 +07:00
bd8dd87384 fix bug cron and update plan 2023-11-09 14:52:41 +07:00
9190660c1c Fixed Error connecting to RouterOS during hotspot plan update
Fixed Error connecting to RouterOS during hotspot plan update
2023-10-30 17:15:40 +07:00
d241b2cec6 Update services.php
Fixed Error connecting to RouterOS when updating hotspot plan  from admin panel> services> Hotspot plan, edit plan
2023-10-30 12:18:36 +03:00
80c76cd6dc 2023.10.27 2023-10-27 10:40:39 +07:00
a1648a4178 alert about restoring data 2023-10-27 10:39:10 +07:00
c8d19a859f New Backup Restore System 2023-10-27 10:36:10 +07:00
90cfc3e6d9 check radius client if radius_enable 2023-10-27 08:57:57 +07:00
88a3e2d205 update Language 2023-10-26 11:24:47 +07:00
0039f47947 fix reminder.php -> cron_reminder.php 2023-10-25 15:27:26 +07:00
c2f1f07cfc Update Readme for Radiuss 2023-10-25 15:14:52 +07:00
f61ebb642e 2023.10.25 2023-10-25 15:10:31 +07:00
77e7a96f96 fix wrong file check in cron, error only for newly installed 2023-10-25 15:10:22 +07:00
5c57c5df11 fix wrong cheking file 2023-10-25 10:03:25 +07:00
9e09611816 Fix expired notification 2023-10-24 15:12:10 +07:00
09ead77d7b Merge branch 'master' into Development 2023-10-24 14:11:11 +07:00
703f9a7463 2023.10.24 2023-10-24 14:09:50 +07:00
ef25633275 Assign router to NAS 2023-10-24 14:09:50 +07:00
02a68589a1 check file if exists 2023-10-24 14:09:50 +07:00
25cd07e975 pagination Nas List 2023-10-24 14:09:49 +07:00
4e7a60aa6f change pagination class 2023-10-24 14:09:49 +07:00
baca2d706f alert move to tpl 2023-10-24 14:09:49 +07:00
4f975fbf0d fix logic pool_expired radius 2023-10-24 14:09:49 +07:00
cded80a632 2023.10.24 2023-10-24 14:08:18 +07:00
f0d130b6b9 Assign router to NAS 2023-10-24 13:55:34 +07:00
a18c07ba42 check file if exists 2023-10-24 13:38:58 +07:00
36b47a3e8d pagination Nas List 2023-10-24 12:30:15 +07:00
37f72d881e change pagination class 2023-10-24 12:27:30 +07:00
e99108a34a alert move to tpl 2023-10-24 09:27:51 +07:00
ddb3b8a718 fix logic pool_expired radius 2023-10-24 09:19:35 +07:00
3c4920f958 Update issue templates 2023-10-21 11:36:23 +07:00
e2da5b67bf Update issue templates 2023-10-21 11:34:28 +07:00
49c8fe5d55 Update issue templates 2023-10-21 11:33:52 +07:00
9402da311c 2023.10.20 2023-10-20 15:00:54 +07:00
51ab4a35c5 Transaction list 2023-10-20 14:31:56 +07:00
d037b2bef4 move alert 2023-10-20 14:07:49 +07:00
d95e4d1d84 resend invoice 2023-10-20 13:57:12 +07:00
7ebf95f4be paginator dynamic 2023-10-20 10:34:24 +07:00
8cbe32e313 StandWithPalestine 2023-10-20 08:53:42 +07:00
0d27503e8d view INVOICE again 2023-10-18 17:49:54 +07:00
1ae687bda2 Voucher Template 2023-10-18 17:26:02 +07:00
d59f696fde Voucher Template Full Custom 2023-10-18 17:24:00 +07:00
b9537d4a4b Voucher Format 2023-10-18 17:23:47 +07:00
e88d1f02a6 fix url update 2023-10-18 15:35:56 +07:00
eda7967f66 fix info cron 2023-10-18 15:35:45 +07:00
55f25a5b7f 2023.10.17 2023-10-17 16:59:10 +07:00
7094555f9f add cronjob info 2023-10-17 16:51:53 +07:00
a5a5969642 Fix Customer self Deactivate Radius 2023-10-17 16:32:18 +07:00
0c0d7a963e Check if PHP GD installed 2023-10-17 14:38:37 +07:00
3fb61d6a8c Fix delete logs 2023-10-17 13:36:07 +07:00
c69b43dbf6 Allow delete Pool and plan when Router already deleted 2023-10-17 09:53:38 +07:00
1583068f57 disable access period 2023-10-16 16:53:56 +07:00
67ec8f2f7a Link to activity logs 2023-10-16 15:08:49 +07:00
915108a1ae logs viewer 2023-10-16 15:06:56 +07:00
f806960ead Logs Viewer 2023-10-16 15:06:51 +07:00
700e861197 sync plan 2023-10-16 13:54:34 +07:00
bc763b476e Check radius in sync pool 2023-10-16 13:44:00 +07:00
3ae81d0105 info about radius pool 2023-10-16 10:31:50 +07:00
a54df9bdab Expired Pool 2023-10-16 10:31:50 +07:00
6a6434b39c radius move to expired pool 2023-10-16 10:31:50 +07:00
92f072a861 Fix Themes Path 2023-10-16 10:31:50 +07:00
6884701de1 Framed-Pool getTableCustomerAttr 2023-10-16 10:09:58 +07:00
7e4c638b07 add access-period 2023-10-16 09:57:22 +07:00
f9e62202c0 remove Max-Volume and only use Mikrotik-Total-Limit 2023-10-16 09:33:03 +07:00
03d3462f49 Mikrotik-Total-Limit 2023-10-13 16:58:07 +07:00
1e80e5d929 fix sync expired 2023-10-13 16:23:01 +07:00
88aca9bac5 hide table when stock 0 2023-10-13 16:17:23 +07:00
718b47ac49 dashboard only show plan who have voucher 2023-10-13 16:07:53 +07:00
492ea5985c add mikrotik spesific vendor atribut for radius 2023-10-13 16:03:12 +07:00
747e28e07c adding themes system 2023-10-12 16:15:50 +07:00
a1d9b63dcf Change credits 2023-10-12 15:55:42 +07:00
95097e4512 show error stacktrace 2023-10-12 15:47:45 +07:00
7e00feb02f if radius dont chek router 2023-10-12 15:10:10 +07:00
8df79c6454 can add quota based 2023-10-12 15:09:48 +07:00
0b7408f5b9 Disconnect radius user 2023-10-12 15:01:49 +07:00
113d4ce6b1 OTP expired 10 minutes 2023-10-12 14:53:29 +07:00
48583c869b radius_client 2023-10-12 14:37:25 +07:00
e19423471f add radius expiration 2023-10-12 14:37:25 +07:00
77f21ece61 Fix select router 2023-10-12 14:37:25 +07:00
5024df9c0b Customer update insert 2023-10-12 14:37:25 +07:00
b9828210ce Plan update insert 2023-10-12 14:37:24 +07:00
5bbf9bf09a check if radius enable inside post 2023-10-07 03:16:12 -07:00
9479ee6cc6 using radius class 2023-10-07 03:05:41 -07:00
68e4557172 nas not nasi 2023-10-07 00:09:37 -07:00
c76aefb7e0 check if radius tabel exists 2023-10-06 16:57:18 +07:00
1a48bfa0ff fix sql installation 2023-10-06 10:12:03 +07:00
fe81d0c62e fix add nas 2023-10-05 20:05:26 +07:00
071df91de0 update PEAR 2023-10-05 16:55:44 +07:00
1861358415 pay radius plan 2023-10-04 17:29:11 +07:00
1891dee6b2 View Order 2023-10-04 17:07:13 +07:00
0bb20d4a16 Radius name reserved 2023-10-04 16:25:21 +07:00
b2a99def98 Fix is_radius 2023-10-04 16:11:55 +07:00
087c5ab515 recharge radius 2023-10-04 15:51:51 +07:00
0ee60eff3d edit customer radius 2023-10-04 15:41:48 +07:00
e87623d918 cron radius, still unfinish 2023-10-04 15:07:38 +07:00
6d835620f5 Customer deactivate plan 2023-10-04 14:16:39 +07:00
7a524a50e3 Radius add plan user 2023-10-04 14:00:04 +07:00
78cbb105aa PPPOE Radius Plan 2023-10-04 11:37:32 +07:00
efc0ba93b6 allow radius pool 2023-10-04 11:25:58 +07:00
ce01771800 hotspot plan radius 2023-10-03 15:46:55 +07:00
9e33a5740b fix add nas 2023-10-03 15:03:47 +07:00
6e3df253c6 hide router when radius choosen 2023-10-02 17:18:18 +07:00
3b87630986 delete nas 2023-10-02 17:11:02 +07:00
d002ed2286 radius DB install 2023-09-29 14:11:44 +07:00
dc19583d95 add label 2023-09-29 14:04:30 +07:00
690584ee90 radius_enable settings 2023-09-29 13:58:22 +07:00
321ac3a35a 404 2023-09-27 15:01:48 +07:00
a313d45b03 Merge branch 'Development' into feature/radius 2023-09-27 14:26:12 +07:00
0bb1563641 disable log qrcode 2023-09-27 14:25:26 +07:00
9842bca5cb fix lang 2023-09-26 13:55:04 +07:00
8d83763b62 fix php 8 2023-09-26 13:50:02 +07:00
106aaf827f Modal Privacy and Toc 2023-09-21 16:36:43 +07:00
c51f04747d User extend plan 2023-09-21 16:04:18 +07:00
97a5c54e24 loading gif 2023-09-21 14:54:00 +07:00
04fcd77da0 red text for expired date 2023-09-21 14:14:33 +07:00
4df15819dd User can deactivate package 2023-09-21 14:12:49 +07:00
caad968655 space in balance 2023-09-21 13:51:50 +07:00
1832332d99 show plan by nux-router 2023-09-21 13:45:28 +07:00
c9eeefcf3d check if router has plan 2023-09-21 12:09:13 +07:00
c5b96df43f add nux-router 2023-09-21 12:09:03 +07:00
529b9c84bd PageFile 2023-09-20 15:13:17 +07:00
56bcbd810e 2023.9.20 2023-09-20 14:32:53 +07:00
c3fd8536eb if not exists, copy 2023-09-20 14:27:15 +07:00
b3057bd59e add NAS 2023-09-18 16:45:08 +07:00
e64f27bc63 Radius Add NAS 2023-09-18 16:25:47 +07:00
64a9e38cce Merge branch 'Development' into feature/radius 2023-09-18 15:07:24 +07:00
6acc342b26 Privacy and ToC not hidden 2023-09-18 15:07:08 +07:00
e59bf71230 Add Privacy Policy and Terms of Condition 2023-09-18 15:03:25 +07:00
b98d0b230d click to view customer from voucher list 2023-09-18 13:56:11 +07:00
00cc448230 change password view 2023-09-18 13:55:52 +07:00
a67a470a06 Merge branch 'Development' into feature/radius 2023-09-18 13:38:23 +07:00
58d5ca7040 change recharge link 2023-09-18 13:35:27 +07:00
e88c678f2f Merge branch 'Development' 2023-09-15 15:25:36 +07:00
eca64ef81e add hide password 2023-09-15 15:16:47 +07:00
3c711115ec remove sample 2023-09-15 14:17:04 +07:00
d4bffaf220 Sync Active Plan 2023-09-15 14:15:43 +07:00
f69885d358 sync hotspot to mikrotik 2023-09-15 14:03:23 +07:00
50ab20e68e sync pppoe to mikrotik 2023-09-15 14:03:16 +07:00
e494570807 sync pool to Mikrotik 2023-09-15 13:34:56 +07:00
b0cb79eeac 2023.9.15 2023-09-15 12:13:12 +07:00
95a8eaeadb recharge customer from profile 2023-09-15 11:57:07 +07:00
aab2282e78 red is off 2023-09-15 11:56:52 +07:00
609cf4b69d Sync Customer to mikrotik 2023-09-15 11:33:46 +07:00
84cd66ea9a add recharge link 2023-09-15 11:33:06 +07:00
3142e93d52 Fix Balance Header 2023-09-15 09:25:55 +07:00
6102637d7b Fix checking package 2023-09-14 17:03:27 +07:00
c754338599 hide backup 2023-09-14 14:28:44 +07:00
a85ccf06fa check error Database 2023-09-14 13:53:28 +07:00
e64527cee2 Show some error page when crash 2023-09-14 13:45:35 +07:00
fc5aa083a1 2023.9.13 2023-09-13 17:31:47 +07:00
53eb817de4 Add Balance to notification 2023-09-13 16:23:51 +07:00
309bbc0059 fix customer count 2023-09-13 15:50:20 +07:00
5fc2190f4a show customer package instead active only 2023-09-13 15:50:12 +07:00
f292da9d8d send package to friend 2023-09-13 15:38:56 +07:00
28fcabd1fd Balance on Top 2023-09-13 14:04:13 +07:00
4bbb98fb98 check if connection error 2023-09-13 10:07:58 +07:00
ee2e67f490 add proxy to connection 2023-09-13 10:00:26 +07:00
e3ec8b18fa Remove User before Remove Active User 2023-09-13 09:37:05 +07:00
f396d7183b add name to invoice notification 2023-09-11 16:26:41 +07:00
b5ddf37649 using Http::getData instead file_get_contents 2023-09-11 14:26:58 +07:00
c57bbeace3 show user active 2023-09-07 10:54:20 +07:00
eeae60d88e show mac and IP 2023-09-07 09:42:28 +07:00
14ed0236d0 Remove active user Before remove user 2023-09-07 09:35:00 +07:00
3833afb3be Fix delete PPPOE 2023-09-07 09:20:31 +07:00
593ca31f18 pool_expired in SQL Instalation 2023-09-06 11:52:09 +07:00
7cc8d6f5e3 delete debug script 2023-09-06 11:25:13 +07:00
11a2fb8fc0 2023.9.6 2023-09-06 10:57:54 +07:00
537623130c Fix expired pool in pppoe 2023-09-06 10:55:28 +07:00
910be1946b Fix cron can move plan 2023-09-06 10:48:52 +07:00
e23abc1377 move user to expired profile when expired if set 2023-09-06 10:02:31 +07:00
b912dd05d0 Set expired plan 2023-09-05 17:06:43 +07:00
5c9a0d8ea6 Expired IP Pool Hotspot/PPPOE 2023-09-05 16:40:23 +07:00
b7eca582a6 Not using tbl_language anymore 2023-09-05 15:25:41 +07:00
b460e862e8 fix git ignore 2023-09-01 16:43:53 +07:00
a33705c0c4 Fix Text Cron 2023-09-01 14:03:02 +07:00
183a5ab242 Fix Reminder text 2023-09-01 13:56:14 +07:00
04c480cafa Fix cronjob Delete customer 2023-09-01 13:40:26 +07:00
8be8737236 2023.9.1 2023-09-01 09:21:35 +07:00
a8515b7d60 Fix Username in user dashboard 2023-09-01 09:18:17 +07:00
d71eb37f48 add Cancel Button in user dashboard 2023-09-01 09:16:40 +07:00
8fcca70ead Time will not change while extending package 2023-09-01 09:06:00 +07:00
59f6c180cf Critical Fix extending user package 2023-09-01 09:02:39 +07:00
d53c4cf8c8 Best 2023-08-30 15:14:18 +07:00
6c45ef730e Merge branch 'Development' into feature/radius 2023-08-30 11:24:42 +07:00
620bfaeb29 unlink after upload 2023-08-30 11:24:08 +07:00
863dd65145 remove debug echo 2023-08-30 10:22:58 +07:00
4de849fe34 2023.8.30 2023-08-30 10:06:04 +07:00
18d68d68c8 fix time, using text 2023-08-30 10:02:58 +07:00
1b15da5c04 Upload Logo For PDF Reports 2023-08-30 09:55:39 +07:00
51416626fb Fix Print Invoice 2023-08-30 09:01:37 +07:00
5a10c19853 PHP NuxBill -> PHPNuxBill 2023-08-28 15:46:25 +07:00
44cdd8f594 info about PHPNuxBill 2023-08-28 15:45:47 +07:00
00cf90e6ea auto rename pages_example 2023-08-28 15:23:23 +07:00
341e26f4d6 rename pages 2023-08-28 15:21:57 +07:00
717b21e65e Fix Remove PPPOE user 2023-08-28 10:38:59 +07:00
d0cebe7458 2023.8.28 2023-08-28 10:27:31 +07:00
6dadb7040c Merge branch 'hotfix/calendar' 2023-08-28 10:24:06 +07:00
fe1310bd57 extend expiration after buy same package 2023-08-28 10:23:54 +07:00
1dd03168f0 Fix time Field 2023-08-28 10:12:55 +07:00
3eefec6e21 if enable_balance and allow_balance_transfer 2023-08-28 09:47:04 +07:00
3b4e3c7789 fix allow_balance_transfer in customer home 2023-08-28 09:46:19 +07:00
b4f5cf8954 Fix Recharge time 2023-08-28 09:44:57 +07:00
51ac162642 Fix date field 2023-08-28 08:57:33 +07:00
d680548eba recharged_on datetime 2023-08-28 08:57:08 +07:00
fd2c9b08e0 add NAS update NAS 2023-08-28 08:45:35 +07:00
cad57760bd Fix expiration date at view user 2023-08-24 15:12:31 +07:00
d51edefc10 Merge branch 'hotfix/2023.8.24.1' 2023-08-24 14:46:55 +07:00
faab21bccf fix sending money 2023-08-24 14:46:38 +07:00
19d5daf5b8 Merge pull request #14 from hotspotbilling/Development
2023.8.24
2023-08-24 13:34:01 +07:00
6166dd6768 2023.8.24 2023-08-24 13:33:01 +07:00
a175f96039 Sending balance Notification 2023-08-24 11:52:43 +07:00
15b9744b18 balance notification 2023-08-24 11:35:23 +07:00
75cbe2b1ec still think about balance reports 2023-08-24 11:00:33 +07:00
774b9e3f94 no scroll announcements 2023-08-23 16:58:24 +07:00
4fd8165d89 Add Balance to Reports 2023-08-23 16:52:17 +07:00
a09dc57495 send balance to other users 2023-08-23 16:46:05 +07:00
74ac7f3eb4 Customer View show Active package 2023-08-23 15:00:34 +07:00
8e45ac40c4 add back button 2023-08-23 12:11:48 +07:00
51565ad173 remove unused js css 2023-08-23 12:11:22 +07:00
54ff67fa49 ajax select customer 2023-08-23 12:11:07 +07:00
27a2938534 update idiorm 2023-08-23 12:10:16 +07:00
cefc6c0365 tuning cron using expiration date 2023-08-23 08:58:18 +07:00
136b7be164 fix default pppoe_passwordd 2023-08-23 08:56:46 +07:00
46e0f981b0 View User 2023-08-21 17:09:44 +07:00
1cb5d9236f add link to related config 2023-08-21 15:59:55 +07:00
9f30e7f0f6 hide password 2023-08-21 15:49:20 +07:00
60c37615ea Phone Input fix 2023-08-21 15:49:12 +07:00
59e1cf7798 Fix remove User 2023-08-21 14:33:44 +07:00
4b96e2c311 add default for balance in installation 2023-08-19 11:54:13 +07:00
4403a48dda Del user from mikrotik before package activation 2023-08-18 14:05:34 +07:00
ac4c98ca63 Buy Package with Balance 2023-08-18 14:01:59 +07:00
2c7d0a321e PPP Comment 2023-08-18 13:37:07 +07:00
4c8f0b27a1 add comment to mikrotik 2023-08-18 10:11:40 +07:00
e23b2464b8 Fix Auto Renewall Cronjob 2023-08-18 09:51:09 +07:00
62cc7bf8a5 Password auto show hide 2023-08-16 14:02:53 +07:00
4f57da8b7d panel-success 2023-08-16 14:00:37 +07:00
2f92cdce0b Forgot to add branch 2023-08-16 13:58:20 +07:00
2431aa2eb5 Merge pull request #13 from hotspotbilling/Development
From version 2023.8.1 need to run update twice or update Database in step 4
2023-08-16 13:49:41 +07:00
5f632fce72 2023.8.16 2023-08-16 13:47:38 +07:00
4238345622 Fix header link customer 2023-08-16 13:44:04 +07:00
aa72b3d8fd Move Menu Payment Gateway inside Settings 2023-08-16 13:41:54 +07:00
455ce90a45 Fix order 2023-08-16 13:41:34 +07:00
9c35962264 Fix edit/change Active Plan 2023-08-16 09:48:07 +07:00
7c41ebfb62 update community page 2023-08-16 09:27:36 +07:00
6f6fc05d16 fix typo 2023-08-16 09:25:15 +07:00
b315e3dba1 Using Select2 for dropdown 2023-08-16 09:05:59 +07:00
3fe9111824 Bring back invoice note 2023-08-16 08:30:05 +07:00
091275f380 Fix Phone number field if no country code 2023-08-15 17:06:03 +07:00
0dd4e39c8f Refill Balance From admin 2023-08-15 17:01:48 +07:00
d682d20035 Format Money in History 2023-08-15 16:21:35 +07:00
499a32015a Show Balance in Customer List 2023-08-15 16:21:20 +07:00
68f9399357 allow change url update from config.php 2023-08-15 14:04:21 +07:00
db2b5edff5 Fix field price 2023-08-15 13:24:44 +07:00
8cb277f6d2 Merge pull request #12 from hotspotbilling/Development
Update with Balance System
2023-08-15 10:42:47 +07:00
ad0f4599e7 Version 2023.8.15 2023-08-15 10:35:11 +07:00
783b541645 Auto Renewal Button 2023-08-15 10:27:46 +07:00
7e78c5db40 auto renewal from deposit 2023-08-15 10:17:28 +07:00
af0b2cda28 Buy Balance Done 2023-08-14 15:59:53 +07:00
e27c0da2aa Add Edit Delete Balance Package 2023-08-14 15:01:47 +07:00
a5a959eade Add Notification Message for Buy Balance 2023-08-14 14:16:56 +07:00
e5f18ec7e4 Send Message change Function name 2023-08-14 14:16:03 +07:00
942552e9ac Add Cron reminder 2023-08-14 14:15:15 +07:00
43590211a2 Merge Fix PPPOE Delete Customer 2023-08-14 13:35:54 +07:00
3b85e752af Fix Error Delete PPPOE User 2023-08-14 13:33:20 +07:00
d9bda444e9 ppoe_password Set to package 2023-08-14 13:21:41 +07:00
5b7e84fb75 Fix Header Admin 2023-08-14 11:42:31 +07:00
4fcb4342ab default pic 2023-08-14 11:37:24 +07:00
f770126f8c Username readonly 2023-08-14 11:37:15 +07:00
1904e5e8a0 Notification Message Editor 2023-08-14 11:24:27 +07:00
aeeb04fd67 add pppoe_password 2023-08-14 09:33:25 +07:00
759331105d Fix PDF export and logo 2023-08-14 09:25:29 +07:00
e3b736e222 Add Customer now all field shown 2023-08-09 14:54:38 +07:00
56cea36a33 Update Bahasa 2023-08-09 11:05:14 +07:00
3fbd5b2eb1 Add Country Code Number for Phone 2023-08-09 10:59:45 +07:00
0d0f59a9a0 Add Customer Balance Settings 2023-08-09 10:50:02 +07:00
755e857979 Add Money Format to Class 2023-08-09 10:49:29 +07:00
a33b299811 Add user Meta table for Custom Field User 2023-08-09 10:04:56 +07:00
abc1447ce5 update file can update SQL 2023-08-09 10:02:34 +07:00
11b54bdcc5 Merge pull request #11 from hotspotbilling/Development
Add self Update Script
2023-08-01 16:30:31 +07:00
f901da2b5f allow step 4 2023-08-01 16:10:00 +07:00
5b077f7773 add slash in the end folder 2023-08-01 16:09:04 +07:00
62c3002152 remove print_r 2023-08-01 16:05:52 +07:00
1111ea986e update Version 2023-08-01 16:01:21 +07:00
25a6491932 update Community Page 2023-08-01 15:58:33 +07:00
72146a3afa update finished dialog 2023-08-01 15:54:24 +07:00
5059c4dd3b Update Software Script 2023-08-01 15:50:28 +07:00
e0eed484e9 Remove Echo Debug 2023-08-01 15:50:01 +07:00
1f4bd28045 Add Custom UI Folder to customize UI 2023-08-01 15:00:17 +07:00
1515a44ae5 fix vendors.js path 2023-08-01 14:59:47 +07:00
6aa4fe8b96 Merge pull request #10 from hotspotbilling/Development
- Fix link buy Voucher
- Add email field to registration form
- Change registration design Form
- Add Setting to disable Voucher
- Fix Title for PPPOE plans
- Fix Plugin Cache
2023-07-28 01:44:32 -07:00
18834a7276 2023.7.28 2023-07-28 15:40:55 +07:00
4e86f4cb02 Fix cache for plugin manager 2023-07-28 15:38:52 +07:00
39d3c683bc Fix Title for PPPOE plans 2023-07-21 09:14:56 +07:00
5e474e4bf7 Add Setting to disable Voucher 2023-07-18 16:30:12 +07:00
dea73fb2a6 Add email in registration form 2023-07-18 09:51:43 +07:00
7e203eaa11 Fix link order Voucher 2023-07-18 09:28:45 +07:00
d31a37cf4d php 7.4 only 2023-07-07 15:52:10 +07:00
05a5b784aa add break; 2023-07-07 15:51:48 +07:00
670223f7e2 Version 2023.6.20 - hide package start time
Version 2023.6.20
2023-06-21 09:35:08 +07:00
2c75499a13 Version 2023.6.20 2023-06-21 09:33:21 +07:00
c3f1df05b8 Fixing start time package 2023-06-20 14:18:10 +07:00
ab01de68b7 recharged_on no time 2023-06-20 12:00:03 +07:00
001bc1e479 no time on recharge_on 2023-06-20 11:57:05 +07:00
ff2ec20400 Merge pull request #48 from hotspotbilling/master
merge pull
2023-06-16 09:30:09 +07:00
e8b428c330 2023.6.15
2023.6.15
2023-06-16 09:29:26 +07:00
877c7a29f0 Merge pull request #7 from hotspotbilling/Development
Remove unused
2023-06-16 09:28:44 +07:00
3f1262236e Remove unused 2023-06-16 09:26:59 +07:00
d9dbc817c4 Merge pull request #46 from hotspotbilling/Development
Version 2023.6.15
2023-06-16 09:18:57 +07:00
44084a764c Merge pull request #6 from hotspotbilling/Development
Version 2023.6.15
2023-06-16 09:18:24 +07:00
406f0f594d Merge remote-tracking branch 'origin/master' into Development 2023-06-16 09:17:28 +07:00
e79abb004e changelog 2023-06-16 09:15:07 +07:00
7d98844690 Selection text color 2023-06-16 09:09:49 +07:00
8ec7b6f080 2023.6.15 2023-06-15 17:07:28 +07:00
12e06a51e4 Fix redirect and check user in database 2023-06-15 17:06:22 +07:00
a9d10d330f fix confirm 2023-06-15 16:50:58 +07:00
a660ec5ddb fix search 2023-06-15 16:46:36 +07:00
dfbd7df367 Add telegram Group 2023-06-15 16:00:25 +07:00
ee840d2b75 Change logo 2023-06-15 16:00:18 +07:00
c1c3ce08cd Add login Internet from User account 2023-06-15 15:26:38 +07:00
a256e1eb42 Update language 2023-06-15 15:26:16 +07:00
1b51881f9b using Vendor from composer 2023-06-15 10:17:00 +07:00
c194b6a8a5 How it Works Link
How it Works Link
2023-06-09 09:18:18 +07:00
54ec065e98 How it Works Link 2023-06-09 09:10:59 +07:00
0d30aaf8fa Merge pull request #36 from hotspotbilling/Development
Fix bug setPpoeUser
2023-06-08 15:06:11 +07:00
cf0725e6a5 Fix bug setPpoeUser
Fix bug setPpoeUser
2023-06-08 15:05:07 +07:00
52d3e49d67 Fix bug setPpoeUser 2023-06-08 15:04:09 +07:00
cad7a4723f Fix bug setPpoeUser 2023-06-08 15:03:12 +07:00
39b840ffd0 2023.6.6
2023.6.6
2023-06-08 14:57:12 +07:00
476c838de1 Fixing registration without OTP, Username will not go to phonenumber
Fixing registration without OTP, Username will not go to phonenumber
2023-06-08 14:54:25 +07:00
7283ca9749 Merge pull request #32 from hotspotbilling/Development
Fixing registration without OTP, Username will not go to phonenumber
2023-06-08 14:54:03 +07:00
80e86ef6cc 2023.6.6 2023-06-08 14:52:53 +07:00
9115d1c41b alphanumeric 2023-06-08 14:46:00 +07:00
d9cda04f7d if register not using FTP, username willnot go to phonenumber 2023-06-08 14:43:18 +07:00
41352479d1 Update README
Merge pull request #27 from hotspotbilling/Development
2023-05-31 14:55:03 +07:00
6db447d79f docker info 2023-05-31 14:46:58 +07:00
f35c591b80 Technical Support 2023-05-31 14:44:05 +07:00
6f20e3f97f Merge pull request #3 from hotspotbilling/Development
Fix Voucher search and Bring back Delete
2023-04-06 10:01:52 +07:00
75f10ef50a Merge pull request #23 from hotspotbilling/Development
Fix Voucher search and Bring back Delete
2023-04-06 09:59:59 +07:00
33cf1413db bring back delete 2023-04-06 09:57:50 +07:00
5f07adf0ac fix search 2023-04-06 09:57:50 +07:00
0c3386f0d1 Fix Voucher Searching 2023-04-06 09:57:50 +07:00
a0af30c12b Merge pull request #2 from hotspotbilling/Development
Fix old deprecated function
2023-03-12 10:27:19 +07:00
f6e5bac86a Merge pull request #20 from hotspotbilling/Development
Fix old deprecated code
2023-03-12 10:26:36 +07:00
9f09909616 2023.3.12 2023-03-12 10:25:38 +07:00
bbc830de26 fix old deprecated code 2023-03-12 10:24:31 +07:00
b0cac9510d Merge pull request #18 from hotspotbilling/Development
Plugin Installer
2023-03-08 13:03:57 +07:00
36d7a8a0a4 Merge pull request #1 from hotspotbilling/Development
Add Notification and Plugin Downloader
2023-03-08 11:33:41 +07:00
b0542ab8be plugin manager 2023-03-08 11:08:56 +07:00
2155c3adae 2023.3.6 2023-03-06 14:57:36 +07:00
51984401d2 bold 2023-03-06 14:57:06 +07:00
fc6a5a26eb add new install 2023-03-06 14:52:09 +07:00
ec45d59a68 change sending message 2023-03-06 14:51:36 +07:00
ba85ed6d0e change text 2023-03-06 14:51:24 +07:00
41c3628eeb add new lang text 2023-03-06 14:51:13 +07:00
26be14bf0e add new lang text 2023-03-06 14:51:05 +07:00
1315621259 check notification 2023-03-06 14:50:55 +07:00
b10cfa2a8e add expired notification 2023-03-06 14:49:44 +07:00
3130310d9c add notification settings 2023-03-06 14:49:26 +07:00
6042538d8e Move send SMS/Wa/Telegram to class 2023-03-06 14:48:05 +07:00
976300bac7 Plugin Manager, install belum 2023-01-31 14:26:49 +07:00
d526ceb6bc Fix delete 2023-01-31 09:14:02 +07:00
d5f29a5c74 update readme 2022-12-14 15:57:20 +07:00
50e55744ec Merge pull request #12 from hotspotbilling/Development
Fixing some code to be able integrate with paypal payment gateway
2022-12-14 15:33:01 +07:00
b69552b44a add sponsors 2022-12-14 15:22:30 +07:00
51b5dbd6f7 Version 2022.12.14 2022-12-14 15:18:39 +07:00
ada4bc8b51 add translation 2022-12-14 15:08:49 +07:00
f3363856f3 Check user email and Desc History 2022-12-14 15:08:42 +07:00
376a3448b6 add postData 2022-12-14 15:08:23 +07:00
660f186004 WhatsappGateway Info 2022-12-14 15:08:14 +07:00
35667e9459 Fix registration info 2022-12-13 15:14:27 +07:00
4fe47612eb Merge pull request #4 from hotspotbilling/Development
rename sql
2022-11-18 14:22:01 +07:00
d777921fbd rename sql 2022-11-18 14:16:00 +07:00
fdbef99985 Merge pull request #3 from hotspotbilling/Development
Change design
2022-11-17 12:42:42 +07:00
7651697ae7 change table 2022-11-17 12:36:32 +07:00
1afa84e36f fixlogin and panel-primary 2022-10-17 11:57:39 +07:00
a2a3a7f0a6 hotspotbilling/phpnuxbill 2022-10-16 14:50:24 +07:00
a7e8335297 admin change to adminlte 2022-10-16 14:48:21 +07:00
9015d519c1 change to adminlte 2 2022-10-15 23:18:24 +07:00
98fe44d8aa tapi mau ganti ke paper admin aja 2022-10-13 15:19:51 +07:00
79c7ad1d98 bulma started 2022-10-13 14:00:54 +07:00
565f481a65 fix menu ? 2022-10-12 16:51:29 +07:00
658aa73540 add random anti cache 2022-10-10 10:50:13 +07:00
d7bdec6f29 check version 2022-10-10 10:49:01 +07:00
4f300df828 version file 2022-10-10 10:26:05 +07:00
e477bc90cc Fix Mobile Nav not open when cliecked 2022-10-09 19:43:48 +07:00
6033901886 masuk radius 2022-10-05 10:51:18 +07:00
0ca2dc2029 update install 2022-10-04 10:06:38 +07:00
ef7d122464 update readme and install files 2022-10-04 10:06:28 +07:00
89e0dd9380 Fix Pools 2022-10-03 11:03:56 +07:00
d7d9d9efa1 $_c ke $config 2022-09-21 14:15:00 +07:00
e7e32475cc add templat dir 2022-09-19 16:57:09 +07:00
3ff2e31ccf delete payment gateway 2022-09-19 10:45:50 +07:00
d5c3c23794 payment gateway not included 2022-09-19 10:45:37 +07:00
335c5e524b move config.php and install to root 2022-09-19 09:31:35 +07:00
ac813ca132 simplified Mikrotik Connection 2022-09-18 00:52:39 +07:00
e6f8826490 add hook 2022-09-18 00:00:40 +07:00
742e0df1f2 add menu hook 2022-09-17 22:34:55 +07:00
1c63cd674c no themes 2022-09-17 21:05:24 +07:00
b943a73cb4 fix separator with DIRECTORY_SEPARATOR 2022-09-17 21:03:47 +07:00
0b02b070d3 Merge remote-tracking branch 'origin/master' into Development 2022-09-16 14:21:03 +07:00
a502919165 fix installation 2022-09-16 14:20:42 +07:00
3f92e39185 Create FUNDING.yml 2022-09-16 14:00:22 +07:00
6c69dacdef Merge pull request #39 from ibnux/Development
- Add Router check before save
- Add Telegram Notification for Admin
- Username must phone number
- Add SMS and Whatsapp Notification, this will force user to validate their phone number
- Add Payment Gateway
- Enable and Disable Router/Plan
- Add Tawk.to chat support
2022-09-16 13:57:34 +07:00
1c18f6091d fix payment gateway and table 2022-09-16 11:38:03 +07:00
b6204a5f94 fix recharge 2022-09-16 11:19:53 +07:00
061224b469 plugin system for payment gateway 2022-09-16 11:05:33 +07:00
0bd6c9e3c7 add merge spanish lang 2022-09-15 11:51:02 +07:00
665e05deed Merge remote-tracking branch 'origin/master' into Development 2022-09-15 11:48:48 +07:00
3fa4282848 update README 2022-09-15 11:45:43 +07:00
4906768a02 Merge pull request #35 from alucard2303/patch-3
Update phpmixbill.sql for Spanish language
2022-09-14 19:11:16 +07:00
a860708a10 Merge pull request #34 from alucard2303/patch-2
Spanish language
2022-09-14 19:10:26 +07:00
cef6e2a2f6 Duitku ok 2022-09-14 16:54:29 +07:00
8a8c7f897f change to pg- and add duitku 2022-09-14 15:58:12 +07:00
48350941e9 add untranslated language 2022-09-11 11:04:41 +07:00
4067f3fa9a change table structure 2022-09-11 11:04:31 +07:00
3653fcbf87 fix history 2022-09-11 11:02:55 +07:00
9ca2933b5d get unpaid 2022-09-11 11:02:30 +07:00
98b592c8a9 fix wrong name 2022-09-11 11:02:21 +07:00
4d84efcf83 change menu, show history, show unpaid 2022-09-11 11:02:10 +07:00
9154c10c45 Lang class 2022-09-10 16:08:10 +07:00
a7fd02df12 order Button 2022-09-10 16:06:38 +07:00
4a6ea093c1 Payment Gateway Tripay done 2022-09-10 16:01:51 +07:00
5ce70b972b Drop Midtrans 2022-09-10 12:20:45 +07:00
71e8b8e22f midtrans succes paid, but will be drop 2022-09-10 12:17:38 +07:00
dd46273a04 midtrans pay, but not yet validated 2022-09-09 16:46:39 +07:00
e9d67ce220 make update script 2022-09-09 09:53:21 +07:00
46e534af6c without sales text 2022-09-08 17:11:15 +07:00
8d7b1c6ff0 xendit without callback OK 2022-09-08 17:09:21 +07:00
65666ac998 latest structure 2022-09-08 16:32:12 +07:00
99f9f73a70 dont show disabled plan and routers 2022-09-08 14:00:46 +07:00
6afcdfe1fa page Editor 2022-09-08 10:54:35 +07:00
4fa341d854 Enable disable router and plan 2022-09-08 10:43:46 +07:00
464f41ef16 Persiapan Radius Mode 2022-09-07 16:11:35 +07:00
19f79680ff Hashtag for telegram 2022-09-07 15:28:59 +07:00
6c64d0944f walled garden example 2022-09-07 15:09:56 +07:00
40d77bba7b add tawk to and example walled garden 2022-09-07 15:07:40 +07:00
b7394762b3 update tabel installer 2022-09-07 14:50:02 +07:00
a84095b13b SMS OTP registration 2022-09-07 14:44:20 +07:00
8b7001b5ef tripay pg and list channels 2022-09-07 14:44:04 +07:00
41aa9f74ea change template, no themes 2022-09-06 10:31:33 +07:00
deecd28cf7 set payment gateway 2022-09-06 10:31:22 +07:00
9dd85dc38e Change Header 2022-09-05 15:12:00 +07:00
e6eff99632 Minutes and Hour Plan Validity 2022-09-05 15:11:22 +07:00
ba83833e94 notif recharge to user 2022-09-02 15:44:22 +07:00
a0dc6c7274 notif to telegram 2022-09-01 15:35:54 +07:00
dd116ee248 Registration no need has voucher 2022-09-01 14:52:32 +07:00
719e7deb93 Update phpmixbill.sql 2022-08-28 19:34:44 -05:00
15ecd120e1 Create common.lan.php 2022-08-28 19:19:06 -05:00
eb3c84d333 change pages 2022-08-24 11:40:26 +07:00
6eaede3c6e Show error, and fix IP Port custom 2022-08-23 16:33:21 +07:00
90a08cb731 wrong hash default 2022-04-23 01:24:28 +07:00
5df998874a '/ppp/active/print' 2022-04-23 01:13:17 +07:00
1414 changed files with 143118 additions and 164742 deletions

4
.github/FUNDING.yml vendored Normal file
View File

@ -0,0 +1,4 @@
# These are supported funding model platforms
github: ibnux
custom: ['https://paypal.me/ibnux','https://trakteer.id/ibnux']

30
.github/ISSUE_TEMPLATE/bug_report.md vendored Normal file
View File

@ -0,0 +1,30 @@
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: ''
assignees: ibnux
---
Please Remember, this project is free and open source, and @ibnux don't get any money from this project, and if you post something not a bug, just you dont understand how to install it, you will get blocked from this Repository.
Post it in Discussion if you don't understand. Except you pay for $50 for support
**Describe the bug**
A clear and concise description of what the bug is. Error connecting to router is not a bug, is your router port is not accessable, ask community for help, go to discussion or telegram group
**To Reproduce**
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error
**Expected behavior**
A clear and concise description of what you expected to happen.
**Screenshots**
If applicable, add screenshots to help explain your problem.
**Additional context**
Add any other context about the problem here.

View File

@ -0,0 +1,22 @@
---
name: Feature request
about: Suggest an idea for this project
title: ''
labels: ''
assignees: ''
---
Please Remember, this project is free and open source, and @ibnux don't get any money from this project, any Feature Request will cost you $50-$5000
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.
**Additional context**
Add any other context or screenshots about the feature request here.

40
.gitignore vendored
View File

@ -1,6 +1,42 @@
system/config.php
config.php
.DS_Store
.vscode/
ui/ui/compiled
ui/compiled/*.php
ui/cache/*.php
test.php
test.php
sms.php
pages/
system/cache/**
system/plugin/*
!system/cache/index.html
!system/plugin/index.html
system/paymentgateway/ui/**
system/paymentgateway/**
!system/paymentgateway/ui/
!system/paymentgateway/ui/index.html
!system/paymentgateway/index.html
!system/plugin/ui/
system/plugin/ui/*
!system/plugin/ui/index.html
ui/ui_custom/**
!ui/ui_custom/index.html
!ui/ui_custom/README.md
system/uploads/**
!system/uploads/*.default.png
system/uploads/sms/**
!system/uploads/sms/index.html
system/uploads/system/**
!system/uploads/system/index.html
ui/themes/**
!ui/themes/index.html
!ui/themes/README.md
scanLang.php
system/lan/**
!system/lan/index.html
!system/lan/indonesia.json
!system/lan/spanish.json
!system/lan/turkish.json
!system/lan/english.json
!system/lan/country.json
*.zip

14
.htaccess_firewall Normal file
View File

@ -0,0 +1,14 @@
<Files *.php>
Order Deny,Allow
Deny from all
</Files>
<Files index.php>
Order Allow,Deny
Allow from all
</Files>
<Files update.php>
Order Allow,Deny
Allow from all
</Files>

476
CHANGELOG.md Normal file
View File

@ -0,0 +1,476 @@
![PHPNuxBill](install/img/logo.png)
# CHANGELOG
## 2024.5.14
- Show Plan and Location on expired list
- Customizeable payment for recharge
## 2024.5.8
- Fix bugs burst by @Gerandonk
- Fix sync for burst by @Gerandonk
## 2024.5.7
- Fix time for period Days
- Fix Free radius attributes by @agstrxyz
- Add Numeric Voucher Code by @pro-cms
## 2024.4.30
- CRITICAL UPDATE: last update Logic recharge not check is status on or off, it make expired customer stay in expired pool
- Prevent double submit for recharge balance
## 2024.4.29
- Maps Pagination
- Maps Search
- Fix extend logic
- Fix logic customer recharge to not delete when customer not change the plan
## 2024.4.23
- Fix Pagination Voucher
- Fix Languange Translation
- Fix Alert Confirmation for requesting Extend
- Send Telegram Notification when Customer request to extend expiration
- prepaid users export list by @freeispradius
- fix show voucher by @agstrxyz
## 2024.4.21
- Restore old cron
## 2024.4.15
- Postpaid Customer can request extends expiration day if it enabled
- Some Code Fixing by @ahmadhusein17 and @agstrxyz
## 2024.4.4
- Data Tables for Customers List by @Focuslinkstech
- Add Bills to Reminder
- Prevent double submit for recharge and renew
## 2024.4.3
- Export logs to CSV by @agstrxyz
- Change to Username if Country code empty
## 2024.4.2
- Fix REST API
- Fix Log IP Cloudflare by @Gerandonk
- Show Personal or Business in customer dashboard
## 2024.3.26
- Change paginator, to make easy customization using pagination.tpl
## 2024.3.25
- Fix maps on HTTP
- Fix Cancel payment
## 2024.3.23
- Maps full height
- Show Get Directions instead Coordinates
- Maps Label always show
## 2024.3.22
- Fix Broadcast Message by @Focuslinkstech
- Add Location Picker
## 2024.3.20
- Fixing some bugs
## 2024.3.19
- Add Customer Type Personal or Bussiness by @pro-cms
- Fix Broadcast Message by @Focuslinkstech
- Add Customer Geolocation by @Focuslinkstech
- Change Customer Menu
## 2024.3.18
- Add Broadcasting SMS by @Focuslinkstech
- Fix Notification with Bills
## 2024.3.16
- Fix Zero Charging
- Fix Disconnect Customer from Radius without loop by @Gerandonk
## 2024.3.15
- Fix Customer View to list active Plan
- Additional Bill using Customer Attributes
## 2024.3.14
- Add Note to Invoices
- Add Additional Bill
- View Invoice from Customer side
## 2024.3.13
- Postpaid System
- Additional Cost
## 2024.3.12
- Check if Validity Period, so calculate price will not affected other validity
- Add firewall using .htaccess for apache only
- Multiple Payment Gateway by @Focuslinkstech
- Fix Logic Multiple Payment gateway
- Fix delete Attribute
- Allow Delete Payment Gateway
- Allow Delete Plugin
## 2024.3.6
- change attributes view
## 2024.3.4
- add [[username]] for reminder
- fix agent show when editing
- fix password admin when sending notification
- add file exists for pages
## 2024.3.3
- Change loading button by @Focuslinkstech
- Add Customer Announcements by @Gerandonk
- Add PPPOE Period Validity by @Gerandonk
## 2024.2.29
- Fix Hook Functionality
- Change Customer Menu
## 2024.2.28
- Fix Buy Plan with Balance
- Add Expired date for reminder
## 2024.2.27
- fix path notification
- redirect to dashboard if already login
## 2024.2.26
- Clean Unused JS and CSS
- Add some Authorization check
- Custom Path for folder
- fix some bugs
## 2024.2.23
- Integrate with PhpNuxBill Printer
- Fix Invoice
- add admin ID in transaction
## 2024.2.22
- Add Loading when click submit
- link to settings when hide widget
## 2024.2.21
- Fix SQL Installer
- remove multiple space in language
- Change Phone Number require OTP by @Focuslinkstech
- Change burst Form
- Delete Table Responsive, first Column Freeze
## 2024.2.20
- Fix list admin
- Burst Limit
- Pace Loading by @Focuslinkstech
## 2024.2.19
- Start API Development
- Multiple Admin Level
- Customer Attributes by @Focuslinkstech
- Radius Menu
## 2024.2.13
- Auto translate language
- change language structur to json
- save collapse menu
## 2024.2.12
- Admin Level : SuperAdmin,Admin,Report,Agent,Sales
- Export Customers to CSV
- Session using Cookie
## 2024.2.7
- Hide Dashboard content
## 2024.2.6
- Cache graph for faster opening graph
## 2024.2.5
- Admin Dashboard Update
- Add Monthly Registered Customers
- Total Monthly Sales
- Active Users
## 2024.2.2
- Fix edit plan for user
## 2024.1.24
- Add Send test for SMS, Whatsapp and Telegram
## 2024.1.19
- Paid Plugin, Theme, and payment gateway marketplace using codecanyon.net
- Fix Plugin manager List
## 2024.1.18
- fix(mikrotik): set pool $poolId always empty
## 2024.1.17
- Add minor change, for plugin, menu can have notifications by @Focuslinkstech
## 2024.1.16
- Add yellow color to table for plan not allowed to purchase
- Fix Radius pool select
- add price to reminder notification
- Support thermal printer for invoice
## 2024.1.15
- Fix cron job for Plan only for admin by @Focuslinkstech
## 2024.1.11
- Add Plan only for admin by @Focuslinkstech
- Fix Plugin Manager
## 2024.1.9
- Add Prefix when generate Voucher
## 2024.1.8
- User Expired Order by Expired Date
## 2024.1.2
- Pagination User Expired by @Focuslinkstech
## 2023.12.21
- Modern AdminLTE by @sabtech254
- Update user-dashboard.tpl by @Focuslinkstech
## 2023.12.19
- Fix Search Customer
- Disable Registration, Customer just activate voucher Code, and the voucher will be their password
- Remove all used voucher codes
## 2023.12.18
- Split sms to 160 characters only for Mikrotik Modem
## 2023.12.14
- Can send SMS using Mikrotik with Modem Installed
- Add Customer Type, so Customer can only show their PPPOE or Hotspot Package or both
## 2023.11.17
- Error details not show in Customer
## 2023.11.15
- Customer Multi Router package
- Fix edit package, Admin can change Customer to another router
## 2023.11.9
- fix bug variable in cron
- fix update plan
## 2023.10.27
- Backup and restore database
- Fix checking radius client
## 2023.10.25
- fix wrong file check in cron, error only for newly installed
## 2023.10.24
- Fix logic cronjob
- assign router to NAS, but not yet used
- Fix Pagination
- Move Alert from hardcode
## 2023.10.20
- View Invoice
- Resend Invoice
- Custom Voucher
## 2023.10.17
- Happy Birthday To Me 🎂 \(^o^)/
- Support FreeRadius with Mysql
- Bring back Themes support
- Log Viewer
## 2023.9.21
- Customer can extend Plan
- Customer can Deactivate active plan
- add variable nux-router to select only plan from that router
- Show user expired until 30 items
## 2023.9.20
- Fix Customer balance header
- Deactivate Customer active plan
- Sync Customer Plan to Mikrotik
- Recharge Customer from Customer Details
- Add Privacy Policy and Terms and Conditions Pages
## 2023.9.13
- add Current balance in notification
- Buy Plan for Friend
- Recharge Friend plan
- Fix recharge Plan
- Show Customer active plan in Customer list
- Fix Customer counter in dashboard
- Show Customer Balance in header
- Fix Plugin Manager using Http::Get
- Show Some error page when crash
## 2023.9.7
- Fix PPPOE Delete Customer
- Remove active Customer before deleting
- Show IP and Mac even if it not Hotspot
## 2023.9.6
- Expired Pool
Customer can be move to expired pool after plan expired by cron
- Fix Delete customer
- tbl_language removed
## 2023.9.1.1
- Fix cronjob Delete customer
- Fix reminder text
## 2023.9.1
- Critical bug fixes, bug happen when user buy package, expired time will be calculated from last expired, not from when they buy the package
- Time not change after user buy package for extending
- Add Cancel Button to user dashboard when it show unpaid package
- Fix username in user dashboard
## 2023.8.30
- Upload Logo from settings
- Fix Print value
- Fix Time when editing prepaid
## 2023.8.28
- Extend expiration if buy same package
- Fix calendar
- Add recharge time
- Fix allow balance transfer
## 2023.8.24
- Balance transfer between Customer
- Optimize Cronjob
- View Customer Info
- Ajax for select customer
## 2023.8.18
- Fix Auto Renewall Cronjob
- Add comment to Mikrotik User
## 2023.8.16
- Admin Can Add Balance to Customer
- Show Balance in user
- Using Select2 for Dropdown
## 2023.8.15
- Fix PPPOE Delete Customer
- Fix Header Admin and Customer
- Fix PDF Export by Period
- Add pppoe_password for Customer, this pppoe_password only admin can change
- Country Code Number Settings
- Customer Meta Table for Customers Attributess
- Fix Add and Edit Customer Form for admin
- add Notification Message Editor
- cron reminder
- Balance System, Customer can deposit money
- Auto renewal when package expired using Customer Balance
## 2023.8.1
- Add Update file script, one click updating PHPNuxBill
- Add Custom UI folder, to custome your own template
- Delete debug text
- Fix Vendor JS
## 2023.7.28
- Fix link buy Voucher
- Add email field to registration form
- Change registration design Form
- Add Setting to disable Voucher
- Fix Title for PPPOE plans
- Fix Plugin Cache
## 2023.6.20
- Hide time for Created date.
Because the first time phpmixbill created, plan validity only for days and Months, many request ask for minutes and hours, i change it, but not the database.
## 2023.6.15
- Customer can connect to internet from Customer Dashboard
- Fix Confirm when delete
- Change Logo PHPNuxBill
- Using Composer
- Fix Search Customer
- Fix Customer check, if not found will logout
- Customer password show but hidden
- Voucher code hidden
## 2023.6.8
- Fixing registration without OTP
- Username will not go to phonenumber if OTP registration is not enabled
- Fix Bug PPOE

102
README.md
View File

@ -1,86 +1,102 @@
# PHP Mikrotik Billing
----
[![ReadMeSupportPalestine](https://raw.githubusercontent.com/Safouene1/support-palestine-banner/master/banner-project.svg)](https://s.id/standwithpalestine)
![N|phpmixbill](http://4.bp.blogspot.com/-3OWL5OI7pqU/VjocUDdzMDI/AAAAAAAAAiA/s_XJN0_mDlk/s640/Screenshot_8.png)
# PHPNuxBill - PHP Mikrotik Billing
----
![PHPNuxBill](install/img/logo.png)
This project maintained by [@ibnux](https://twitter.com/ibnux)
## Feature
Aplikasi ini dikelola oleh [@ibnux](https://twitter.com/ibnux)
----
Download [Mikrotik Login Template](https://github.com/ibnux/phpmixbill-mikrotik-login-template)
Features:
----
- Voucher Generator and Print
- Self registration, user must have voucher before registration
- FreeRadius
- Self registration
- User Balance
- Auto Renewal Package using Balance
- Multi Router Mikrotik
- Hotspot & PPPOE
- Easy Installation
- Multi Language
- Payment Gateway
- SMS validation for login
- Whatsapp Notification to Consumer
- Telegram Notification for Admin
TODOS:
----
See [How it Works / Cara Kerja](https://github.com/hotspotbilling/phpnuxbill/wiki/How-It-Works---Cara-kerja)
- SMS Notification to user
- send receipt via SMS or EMAIL
- Social Media Login
## Payment Gateway And Plugin
Installation
----
See [WIKI](https://github.com/ibnux/phpmixbill/wiki/Instalation)
- [Payment Gateway List](https://github.com/orgs/hotspotbilling/repositories?q=payment+gateway)
- [Plugin List](https://github.com/orgs/hotspotbilling/repositories?q=plugin)
baca [WIKI](https://github.com/ibnux/phpmixbill/wiki/Instalation)
You can download payment gateway and Plugin from Plugin Manager
System Requirements
----
Most current web servers with PHP & MySQL installed will be capable of running PHPMixBill
## System Requirements
Most current web servers with PHP & MySQL installed will be capable of running PHPNuxBill
Minimum Requirements
- Linux or Windows OS
- PHP Version 5.3+
- Minimum PHP Version 7.4
- Both PDO & MySQLi Support
- GD2 Image Library
- PHP-GD2 Image Library
- PHP-CURL
- PHP-ZIP
- PHP-Mbstring
- MySQL Version 4.1.x and above
can be Installed in Raspberry Pi Device.
The problem with windows is hard to set cronjob, better Linux
JASA
----
Terima jasa instalasi PHPMIXBILL beserta mikrotiknya.
## Changelog
Via Team Viewer maupun Barang dibeli dari saya dan tinggal pakai.
[CHANGELOG.md](CHANGELOG.md)
## Installation
1. Unit Mikrotik Router
2. Raspberry Pi Server (RasPi + Casing + Memory 4GB + Adaptor)
[Installation instructions](https://github.com/hotspotbilling/phpnuxbill/wiki)
Jasa kurang lebih Rp. 500.000, belum termasuk ongkir dan harga perangkat, Gratis Tanya Jawab via Messenger (Jika lagi senggang).
## Docker Version
hubungi ibnux di [Twitter](https://twitter.com/ibnux) atau di [facebook](https://facebook.com/ibnumaksum)
[Docker Repository](https://github.com/animegasan/phpnuxbill)
## Freeradius
License
----
Support [Freeradius with Database](https://github.com/hotspotbilling/phpnuxbill/wiki/FreeRadius)
## Community Support
- [Github Discussion](https://github.com/hotspotbilling/phpnuxbill/discussions)
- [Telegram Group](https://t.me/phpmixbill)
## Technical Support
Start from Rp 500.000 or $50
If you chat me for any technical support, you need to pay, except for Donors, ask anything for free in the [discussion](/hotspotbilling/phpnuxbill/discussions) page
[Telegram](https://t.me/ibnux)
[Website](https://ibnux.net/layanan)
## License
GNU General Public License version 2 or later
see LICENSE file
## [CHANGELOG](CHANGELOG.md)
Donate to ibnux
----
## Donate to ibnux
[![Donate](https://img.shields.io/badge/Donate-PayPal-green.svg)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=6RBNGRJMZVV7C)
[![Donate](https://img.shields.io/badge/Donate-PayPal-green.svg)](https://paypal.me/ibnux)
BCA: 5410454825
Mandiri: 163-000-1855-793
a.n Ibnu Maksum
## SPONSORS
- [mlink.id](https://mlink.id)
- [https://github.com/sonyinside](https://github.com/sonyinside)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 178 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 48 KiB

View File

@ -1,11 +1,8 @@
<?php
/**
* PHP Mikrotik Billing (https://ibnux.github.io/phpmixbill/)
* PHP Mikrotik Billing (https://github.com/hotspotbilling/phpnuxbill/)
* by https://t.me/ibnux
**/
* @copyright Copyright (C) 2014-2015 PHP Mikrotik Billing
* @license GNU General Public License version 2 or later; see LICENSE.txt
**/
header('location: ../index.php?_route=admin/');

16
composer.json Normal file
View File

@ -0,0 +1,16 @@
{
"name": "hotspotbilling/phpnuxbill",
"type": "template",
"description": "PHPNuxBill a Hotspot Billing Software.",
"keywords": ["template","PHPMixBill","PHPnuxBill","Mikrotik","Hotspot","Billing"],
"homepage": "https://github.com/hotspotbilling/phpnuxbill",
"license": "MIT",
"authors": [
{
"name": "ibnux",
"email": "me@ibnux.net",
"homepage": "https://ibnux.net",
"role": "Developer"
}
]
}

View File

@ -1,9 +1,9 @@
<?php
$db_host = "localhost"; # Database Host
$db_port = ""; # Database Port. Keep it blank if you are un sure.
$db_user = "root"; # Database Username
$db_password = ""; # Database Password
$db_name = "phpmixbill"; # Database Name
define('APP_URL', 'http://localhost/phpmixbill'); # Application URL.
#Please include http and do not use trailing slash after the url. For example use in this format- http://www.example.com Or http://www.example.com/finance
<?php
$db_host = "localhost"; # Database Host
$db_port = ""; # Database Port. Keep it blank if you are un sure.
$db_user = "root"; # Database Username
$db_password = ""; # Database Password
$db_name = "phpnuxbill"; # Database Name
define('APP_URL', 'http://localhost/phpnuxbill'); # Application URL.
#Please include http and do not use trailing slash after the url. For example use in this format- http://www.example.com Or http://www.example.com/finance
$_app_stage = 'Live'; # Do not change this

View File

@ -1,72 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>PHPMIXBILL - Voucher management for Mikrotik Hotspot</title>
<!-- Latest compiled and minified CSS -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<!-- Optional theme -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap-theme.min.css" integrity="sha384-rHyoN1iRsVXV4nD0JutlnGaslCJuC7uwjduW9SVrLvRYooPp2bWYgmgJQIXwl/Sp" crossorigin="anonymous">
<style>
@-ms-viewport { width: device-width; }
@-o-viewport { width: device-width; }
@viewport { width: device-width; }
body {
padding-top: 50px;
}
.starter-template {
padding: 40px 15px;
text-align: center;
}
</style>
<!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
<!--[if lt IE 9]>
<script src="https://oss.maxcdn.com/html5shiv/3.7.3/html5shiv.min.js"></script>
<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
<![endif]-->
</head>
<body>
<div class="container">
<div class="starter-template">
<h1>PHP PHPMIXBILL</h1>
<p class="lead">Aplikasi manajemen Voucher Hotspot untuk Mikrotik</p>
<div class="btn-group btn-group-justified" role="group">
<a href="https://github.com/ibnux/phpmixbill/releases" class="btn btn-primary">Download</a>
<a href="https://github.com/ibnux/phpmixbill" class="btn btn-success">Source</a>
</div>
</div>
<div class="row">
<div class="col-sm-12">
<div class="panel panel-hovered mb20 panel-default">
<div class="panel-heading">Public Disquss</div>
<div class="panel-body">
<div id="disqus_thread"></div>
<script>
var disqus_config = function () {
this.page.url = "https://ibnux.github.io/phpmixbill/diskusi.html"; // Replace PAGE_URL with your page's canonical URL variable
this.page.identifier = "phpmixbill"; // Replace PAGE_IDENTIFIER with your page's unique identifier variable
};
(function() { // DON'T EDIT BELOW THIS LINE
var d = document, s = d.createElement('script');
s.src = 'https://phpmixbill.disqus.com/embed.js';
s.setAttribute('data-timestamp', +new Date());
(d.head || d.body).appendChild(s);
})();
</script>
<noscript>Please enable JavaScript to view the <a href="https://disqus.com/?ref_noscript">comments powered by Disqus.</a></noscript>
</div>
</div>
</div>
</div>
</div><!-- /.container -->
</body>
</html>

View File

@ -1,50 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>PHPMIXBILL - Voucher management for Mikrotik Hotspot</title>
<!-- Latest compiled and minified CSS -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<!-- Optional theme -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap-theme.min.css" integrity="sha384-rHyoN1iRsVXV4nD0JutlnGaslCJuC7uwjduW9SVrLvRYooPp2bWYgmgJQIXwl/Sp" crossorigin="anonymous">
<style>
@-ms-viewport { width: device-width; }
@-o-viewport { width: device-width; }
@viewport { width: device-width; }
body {
padding-top: 50px;
}
.starter-template {
padding: 40px 15px;
text-align: center;
}
</style>
<!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
<!--[if lt IE 9]>
<script src="https://oss.maxcdn.com/html5shiv/3.7.3/html5shiv.min.js"></script>
<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
<![endif]-->
</head>
<body>
<div class="container">
<div class="starter-template">
<h1>PHPMIXBILL</h1>
<p class="lead">Aplikasi manajemen Voucher Hotspot untuk Mikrotik</p>
<div class="btn-group btn-group-justified" role="group">
<a href="https://github.com/ibnux/phpmixbill/releases" class="btn btn-primary">Download</a>
<a href="https://github.com/ibnux/phpmixbill" class="btn btn-success">Source</a>
<a href="https://ibnux.github.io/phpmixbill/diskusi.html" class="btn btn-info">Disquss</a>
</div>
</div>
</div><!-- /.container -->
</body>
</html>

BIN
favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

View File

@ -1,14 +1,23 @@
<?php
/**
* PHP Mikrotik Billing (https://ibnux.github.io/phpmixbill/)
* PHP Mikrotik Billing (https://github.com/hotspotbilling/phpnuxbill/)
* by https://t.me/ibnux
**/
session_start();
* @copyright Copyright (C) 2014-2015 PHP Mikrotik Billing
* @license GNU General Public License version 2 or later; see LICENSE.txt
if(isset($_GET['nux-mac']) && !empty($_GET['nux-mac'])){
$_SESSION['nux-mac'] = $_GET['nux-mac'];
}
**/
//ini_set('display_errors', 1);
//ini_set('display_startup_errors', 1);
//error_reporting(E_ALL);
require ('system/boot.php');
if(isset($_GET['nux-ip']) && !empty($_GET['nux-ip'])){
$_SESSION['nux-ip'] = $_GET['nux-ip'];
}
if(isset($_GET['nux-router']) && !empty($_GET['nux-router'])){
$_SESSION['nux-router'] = $_GET['nux-router'];
}
require_once 'system/vendor/autoload.php';
require_once 'system/boot.php';
App::_run();

324
init.php Normal file
View File

@ -0,0 +1,324 @@
<?php
/**
* PHP Mikrotik Billing (https://github.com/hotspotbilling/phpnuxbill/)
* by https://t.me/ibnux
**/
if (realpath(__FILE__) == realpath($_SERVER['SCRIPT_FILENAME'])) {
header('HTTP/1.0 403 Forbidden', TRUE, 403);
header('location: ../');
die();
}
$root_path = realpath(dirname(__FILE__)) . DIRECTORY_SEPARATOR;
if (!isset($isApi)) {
$isApi = false;
}
// on some server, it getting error because of slash is backwards
function _autoloader($class)
{
global $root_path;
if (strpos($class, '_') !== false) {
$class = str_replace('_', DIRECTORY_SEPARATOR, $class);
if (file_exists($root_path . DIRECTORY_SEPARATOR . 'system' . DIRECTORY_SEPARATOR . 'autoload' . DIRECTORY_SEPARATOR . $class . '.php')) {
include $root_path . DIRECTORY_SEPARATOR . 'system' . DIRECTORY_SEPARATOR . 'autoload' . DIRECTORY_SEPARATOR . $class . '.php';
} else {
$class = str_replace("\\", DIRECTORY_SEPARATOR, $class);
if (file_exists($root_path . DIRECTORY_SEPARATOR . 'system' . DIRECTORY_SEPARATOR . 'autoload' . DIRECTORY_SEPARATOR . $class . '.php'))
include $root_path . DIRECTORY_SEPARATOR . 'system' . DIRECTORY_SEPARATOR . 'autoload' . DIRECTORY_SEPARATOR . $class . '.php';
}
} else {
if (file_exists($root_path . DIRECTORY_SEPARATOR . 'system' . DIRECTORY_SEPARATOR . 'autoload' . DIRECTORY_SEPARATOR . $class . '.php')) {
include $root_path . DIRECTORY_SEPARATOR . 'system' . DIRECTORY_SEPARATOR . 'autoload' . DIRECTORY_SEPARATOR . $class . '.php';
} else {
$class = str_replace("\\", DIRECTORY_SEPARATOR, $class);
if (file_exists($root_path . DIRECTORY_SEPARATOR . 'system' . DIRECTORY_SEPARATOR . 'autoload' . DIRECTORY_SEPARATOR . $class . '.php'))
include $root_path . DIRECTORY_SEPARATOR . 'system' . DIRECTORY_SEPARATOR . 'autoload' . DIRECTORY_SEPARATOR . $class . '.php';
}
}
}
spl_autoload_register('_autoloader');
if (!file_exists($root_path . 'config.php')) {
$root_path .= '..' . DIRECTORY_SEPARATOR;
if (!file_exists($root_path . 'config.php')) {
r2('install');
}
}
if (!file_exists($root_path . File::pathFixer('system/orm.php'))) {
die($root_path . "orm.php file not found");
}
$UPLOAD_PATH = $root_path . File::pathFixer('system/uploads');
$CACHE_PATH = $root_path . File::pathFixer('system/cache');
$PAGES_PATH = $root_path . File::pathFixer('pages');
$PLUGIN_PATH = $root_path . File::pathFixer('system/plugin');
$PAYMENTGATEWAY_PATH = $root_path . File::pathFixer('system/paymentgateway');
$UI_PATH = 'ui';
if (!file_exists($UPLOAD_PATH . File::pathFixer('/notifications.default.json'))) {
die($UPLOAD_PATH . File::pathFixer("/notifications.default.json file not found"));
}
require_once $root_path . 'config.php';
require_once $root_path . File::pathFixer('system/orm.php');
require_once $root_path . File::pathFixer('system/autoload/PEAR2/Autoload.php');
include $root_path . File::pathFixer('system/autoload/Hookers.php');
ORM::configure("mysql:host=$db_host;dbname=$db_name");
ORM::configure('username', $db_user);
ORM::configure('password', $db_password);
ORM::configure('return_result_sets', true);
if ($_app_stage != 'Live') {
ORM::configure('logging', true);
}
if ($isApi) {
define('U', APP_URL . '/system/api.php?r=');
} else {
define('U', APP_URL . '/index.php?_route=');
}
// notification message
if (file_exists($UPLOAD_PATH . DIRECTORY_SEPARATOR . "notifications.json")) {
$_notifmsg = json_decode(file_get_contents($UPLOAD_PATH . DIRECTORY_SEPARATOR . 'notifications.json'), true);
}
$_notifmsg_default = json_decode(file_get_contents($UPLOAD_PATH . DIRECTORY_SEPARATOR . 'notifications.default.json'), true);
//register all plugin
foreach (glob(File::pathFixer($PLUGIN_PATH . DIRECTORY_SEPARATOR . '*.php')) as $filename) {
try {
include $filename;
} catch (Throwable $e) {
//ignore plugin error
} catch (Exception $e) {
//ignore plugin error
}
}
$result = ORM::for_table('tbl_appconfig')->find_many();
foreach ($result as $value) {
$config[$value['setting']] = $value['value'];
}
$_c = $config;
if (empty($http_proxy) && !empty($config['http_proxy'])) {
$http_proxy = $config['http_proxy'];
if (empty($http_proxyauth) && !empty($config['http_proxyauth'])) {
$http_proxyauth = $config['http_proxyauth'];
}
}
date_default_timezone_set($config['timezone']);
if ((!empty($radius_user) && $config['radius_enable']) || _post('radius_enable')) {
ORM::configure("mysql:host=$radius_host;dbname=$radius_name", null, 'radius');
ORM::configure('username', $radius_user, 'radius');
ORM::configure('password', $radius_pass, 'radius');
ORM::configure('driver_options', array(PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8'), 'radius');
ORM::configure('return_result_sets', true, 'radius');
}
if (empty($config['language'])) {
$config['language'] = 'english';
}
$lan_file = $root_path . File::pathFixer('system/lan/' . $config['language'] . '.json');
if (file_exists($lan_file)) {
$_L = json_decode(file_get_contents($lan_file), true);
$_SESSION['Lang'] = $_L;
} else {
$_L['author'] = 'Auto Generated by iBNuX Script';
$_SESSION['Lang'] = $_L;
file_put_contents($lan_file, json_encode($_L));
}
function safedata($value)
{
$value = trim($value);
return $value;
}
function _post($param, $defvalue = '')
{
if (!isset($_POST[$param])) {
return $defvalue;
} else {
return safedata($_POST[$param]);
}
}
function _get($param, $defvalue = '')
{
if (!isset($_GET[$param])) {
return $defvalue;
} else {
return safedata($_GET[$param]);
}
}
function _req($param, $defvalue = '')
{
if (!isset($_REQUEST[$param])) {
return $defvalue;
} else {
return safedata($_REQUEST[$param]);
}
}
function _auth($login = true)
{
if (User::getID()) {
return true;
} else {
if ($login) {
r2(U . 'login');
} else {
return false;
}
}
}
function _admin($login = true)
{
if (Admin::getID()) {
return true;
} else {
if ($login) {
r2(U . 'login');
} else {
return false;
}
}
}
function _log($description, $type = '', $userid = '0')
{
$d = ORM::for_table('tbl_logs')->create();
$d->date = date('Y-m-d H:i:s');
$d->type = $type;
$d->description = $description;
$d->userid = $userid;
if (!empty($_SERVER['HTTP_CF_CONNECTING_IP'])) //to check ip is pass from cloudflare tunnel
{
$d->ip = $_SERVER['HTTP_CF_CONNECTING_IP'];
} elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) //to check ip is pass from proxy
{
$d->ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
} elseif (!empty($_SERVER['HTTP_CLIENT_IP'])) //to check ip from share internet
{
$d->ip = $_SERVER['HTTP_CLIENT_IP'];
} else {
$d->ip = $_SERVER["REMOTE_ADDR"];
}
$d->save();
}
function Lang($key)
{
return Lang::T($key);
}
function alphanumeric($str, $tambahan = "")
{
return Text::alphanumeric($str, $tambahan);
}
function showResult($success, $message = '', $result = [], $meta = [])
{
header("Content-Type: Application/json");
$json = json_encode(['success' => $success, 'message' => $message, 'result' => $result, 'meta' => $meta]);
echo $json;
die();
}
function generateUniqueNumericVouchers($totalVouchers, $length = 8)
{
// Define characters allowed in the voucher code
$characters = '0123456789';
$charactersLength = strlen($characters);
$vouchers = array();
// Attempt to generate unique voucher codes
for ($j = 0; $j < $totalVouchers; $j++) {
do {
$voucherCode = '';
// Generate the voucher code
for ($i = 0; $i < $length; $i++) {
$voucherCode .= $characters[rand(0, $charactersLength - 1)];
}
// Check if the generated voucher code already exists in the array
$isUnique = !in_array($voucherCode, $vouchers);
} while (!$isUnique);
$vouchers[] = $voucherCode;
}
return $vouchers;
}
function sendTelegram($txt)
{
Message::sendTelegram($txt);
}
function sendSMS($phone, $txt)
{
Message::sendSMS($phone, $txt);
}
function sendWhatsapp($phone, $txt)
{
Message::sendWhatsapp($phone, $txt);
}
function r2($to, $ntype = 'e', $msg = '')
{
global $isApi;
if ($isApi) {
showResult(
($ntype == 's') ? true : false,
$msg
);
}
if ($msg == '') {
header("location: $to");
exit;
}
$_SESSION['ntype'] = $ntype;
$_SESSION['notify'] = $msg;
header("location: $to");
exit;
}
function _alert($text, $type = 'success', $url = "home", $time = 3)
{
global $ui, $isApi;
if ($isApi) {
showResult(
($type == 'success') ? true : false,
$text
);
}
if (!isset($ui)) return;
if (strlen($url) > 4) {
if (substr($url, 0, 4) != "http") {
$url = U . $url;
}
} else {
$url = U . $url;
}
$ui->assign('text', $text);
$ui->assign('type', $type);
$ui->assign('time', $time);
$ui->assign('url', $url);
$ui->display('alert.tpl');
die();
}
if (!isset($api_secret)) {
$api_secret = $db_password;
}

BIN
install/img/favicon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.1 KiB

BIN
install/img/logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

57
install/index.php Normal file
View File

@ -0,0 +1,57 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>PHPNuxBill Installer</title>
<link rel="shortcut icon" type="image/x-icon" href="img/favicon.png">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!--[if lt IE 9]>
<script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
<link type='text/css' href='css/style.css' rel='stylesheet' />
<link href="css/bootstrap.min.css" rel="stylesheet">
</head>
<body style='background-color: #FBFBFB;'>
<div id='main-container'>
<img src="img/logo.png" class="img-responsive" alt="Logo" />
<hr>
<!-- contents area start -->
<div class="row">
<div class="col-md-12">
<h4> PHPNuxBill Installer </h4>
<h5>Please Read Before Continue</h5>
<p><strong>Informasi Aplikasi</strong><br>
Application Name: PHPNuxBill <br>
Release Date: 30/10/2015<br>
By: PHPNuxBill [ <a href="https://github.com/hotspotbilling/phpnuxbill" target="_blank">https://github.com/hotspotbilling/phpnuxbill</a> ]<br>
Donasi Paypal: <b>me@ibnux.et</b><br>
<br>
<strong>Syarat Penggunaan:</strong><br>
Syarat Penggunaan ini berlaku untuk semua versi.<br><br>
<ul>
<li>Silahkan Anda menggunakan aplikasi ini dengan bijak, Anda dapat mendesain ulang script maupun tampilan pada
aplikasi ini sesuai dengan kebutuhan anda, memperbayak jumlah copy atau mendistribusikan aplikasi ini.
Dengan catatan tidak menghapus link developer.</li>
<li>Tidak ada garansi dari kami jika anda mengalami error atau merasa rugi ketika menggunakan aplikasi ini,
Anda hanya dapat memberikan feedback yang berisi laporan error, dengan syarat dan ketentuan yang berlaku.</li>
<li>Semua yang terkait biaya atau donasi apapun versi-nya, Anda dapat update seumur hidup atau selama aplikasi
ini masih dikembangkan. Mohon jangan salah pengertian bahwa kami tim pengembang mengkomersilkan produk ini
dan anda membeli produk kami.</li>
<li>Aplikasi ini bersifat sosial untuk dapat dikembangkan bersama. Karena itu kami juga mengundang relawan-relawan
yang mau menjadi pengembangkan aplikasi ini.</li>
<li>Penulis berhak setiap saat untuk mengubah ketentuan Syarat Penggunaan tanpa pemberitahuan sebelumnya.</li>
</ul>
</div>
<div class="col-md-12"><br>
<a href="step2.php" class="btn btn-primary">Accept &amp; Continue</a>
</div>
</div>
<!-- contents area end -->
</div>
<div class="footer">Copyright &copy; 2021 PHPNuxBill. All Rights Reserved<br /><br /></div>
</body>
</html>

324
install/phpnuxbill.sql Normal file
View File

@ -0,0 +1,324 @@
DROP TABLE IF EXISTS `tbl_appconfig`;
CREATE TABLE `tbl_appconfig` (
`id` int(11) NOT NULL,
`setting` mediumtext CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
`value` mediumtext CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
DROP TABLE IF EXISTS `tbl_bandwidth`;
CREATE TABLE `tbl_bandwidth` (
`id` int(10) UNSIGNED NOT NULL,
`name_bw` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
`rate_down` int(10) UNSIGNED NOT NULL,
`rate_down_unit` enum('Kbps','Mbps') CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
`rate_up` int(10) UNSIGNED NOT NULL,
`rate_up_unit` enum('Kbps','Mbps') CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
DROP TABLE IF EXISTS `tbl_customers`;
CREATE TABLE `tbl_customers` (
`id` int(10) NOT NULL,
`username` varchar(45) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
`password` varchar(45) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
`pppoe_password` varchar(45) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT 'For PPPOE Login',
`fullname` varchar(45) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
`address` mediumtext CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci,
`phonenumber` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT '0',
`email` varchar(128) COLLATE utf8mb4_general_ci NOT NULL DEFAULT '1',
`coordinates` VARCHAR(50) NOT NULL DEFAULT '' COMMENT 'Latitude and Longitude coordinates',
`balance` decimal(15,2) NOT NULL DEFAULT '0.00' COMMENT 'For Money Deposit',
`service_type` ENUM('Hotspot','PPPoE','Others') DEFAULT 'Others' COMMENT 'For selecting user type',
`account_type` ENUM('Business', 'Personal') DEFAULT 'Personal' COMMENT 'For selecting account type',
`auto_renewal` tinyint(1) NOT NULL DEFAULT '1' COMMENT 'Auto renewall using balance',
`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`last_login` datetime DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
DROP TABLE IF EXISTS `tbl_logs`;
CREATE TABLE `tbl_logs` (
`id` int(10) NOT NULL,
`date` datetime DEFAULT NULL,
`type` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
`description` mediumtext CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
`userid` int(10) NOT NULL,
`ip` mediumtext CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
DROP TABLE IF EXISTS `tbl_message`;
CREATE TABLE `tbl_message` (
`id` int(10) NOT NULL,
`from_user` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
`to_user` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
`title` varchar(60) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
`message` mediumtext CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
`status` enum('0','1') CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '0',
`date` datetime NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
DROP TABLE IF EXISTS `tbl_payment_gateway`;
CREATE TABLE `tbl_payment_gateway` (
`id` int(11) NOT NULL,
`username` varchar(32) COLLATE utf8mb4_general_ci NOT NULL,
`gateway` varchar(32) COLLATE utf8mb4_general_ci NOT NULL COMMENT 'xendit | midtrans',
`gateway_trx_id` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '',
`plan_id` int(11) NOT NULL,
`plan_name` varchar(40) COLLATE utf8mb4_general_ci NOT NULL,
`routers_id` int(11) NOT NULL,
`routers` varchar(32) COLLATE utf8mb4_general_ci NOT NULL,
`price` varchar(40) COLLATE utf8mb4_general_ci NOT NULL,
`pg_url_payment` varchar(256) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '',
`payment_method` varchar(32) COLLATE utf8mb4_general_ci NOT NULL DEFAULT '',
`payment_channel` varchar(32) COLLATE utf8mb4_general_ci NOT NULL DEFAULT '',
`pg_request` text COLLATE utf8mb4_general_ci,
`pg_paid_response` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci,
`expired_date` datetime DEFAULT NULL,
`created_date` datetime NOT NULL,
`paid_date` datetime DEFAULT NULL,
`status` tinyint(1) NOT NULL DEFAULT '1' COMMENT '1 unpaid 2 paid 3 failed 4 canceled'
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
DROP TABLE IF EXISTS `tbl_plans`;
CREATE TABLE `tbl_plans` (
`id` int(10) NOT NULL,
`name_plan` varchar(40) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
`id_bw` int(10) NOT NULL,
`price` varchar(40) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
`type` enum('Hotspot','PPPOE','Balance') CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
`typebp` enum('Unlimited','Limited') CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
`limit_type` enum('Time_Limit','Data_Limit','Both_Limit') CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
`time_limit` int(10) UNSIGNED DEFAULT NULL,
`time_unit` enum('Mins','Hrs') CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
`data_limit` int(10) UNSIGNED DEFAULT NULL,
`data_unit` enum('MB','GB') CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
`validity` int(10) NOT NULL,
`validity_unit` enum('Mins','Hrs','Days','Months','Period') CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
`shared_users` int(10) DEFAULT NULL,
`routers` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
`is_radius` tinyint(1) NOT NULL DEFAULT '0' COMMENT '1 is radius',
`pool` varchar(40) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
`pool_expired` varchar(40) COLLATE utf8mb4_general_ci NOT NULL DEFAULT '',
`enabled` tinyint(1) NOT NULL DEFAULT '1' COMMENT '0 disabled',
`allow_purchase` enum('yes','no') DEFAULT 'yes' COMMENT 'allow to show package in buy package page',
`plan_type` ENUM('Business', 'Personal') DEFAULT 'Personal' COMMENT 'For switching plan according to user type'
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
DROP TABLE IF EXISTS `tbl_pool`;
CREATE TABLE `tbl_pool` (
`id` int(10) NOT NULL,
`pool_name` varchar(40) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
`range_ip` varchar(40) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
`routers` varchar(40) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
DROP TABLE IF EXISTS `tbl_routers`;
CREATE TABLE `tbl_routers` (
`id` int(10) NOT NULL,
`name` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
`ip_address` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
`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,
`enabled` tinyint(1) NOT NULL DEFAULT '1' COMMENT '0 disabled'
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
DROP TABLE IF EXISTS `tbl_transactions`;
CREATE TABLE `tbl_transactions` (
`id` int(10) NOT NULL,
`invoice` varchar(25) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
`username` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
`plan_name` varchar(40) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
`price` varchar(40) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
`recharged_on` date NOT NULL,
`recharged_time` time NOT NULL DEFAULT '00:00:00',
`expiration` date NOT NULL,
`time` time NOT NULL,
`method` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
`routers` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
`type` enum('Hotspot','PPPOE','Balance') CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
DROP TABLE IF EXISTS `tbl_users`;
CREATE TABLE `tbl_users` (
`id` int(10) UNSIGNED NOT NULL,
`username` varchar(45) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '',
`fullname` varchar(45) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '',
`password` mediumtext CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
`user_type` enum('SuperAdmin','Admin','Report','Agent','Sales') CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
`status` enum('Active','Inactive') CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT 'Active',
`last_login` datetime DEFAULT NULL,
`creationdate` datetime NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
DROP TABLE IF EXISTS `tbl_user_recharges`;
CREATE TABLE `tbl_user_recharges` (
`id` int(10) NOT NULL,
`customer_id` int(10) NOT NULL,
`username` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
`plan_id` int(10) NOT NULL,
`namebp` varchar(40) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
`recharged_on` date NOT NULL,
`recharged_time` time NOT NULL DEFAULT '00:00:00',
`expiration` date NOT NULL,
`time` time NOT NULL,
`status` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
`method` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '',
`routers` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
`type` varchar(15) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
DROP TABLE IF EXISTS `tbl_voucher`;
CREATE TABLE `tbl_voucher` (
`id` int(10) NOT NULL,
`type` enum('Hotspot','PPPOE') CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
`routers` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
`id_plan` int(10) NOT NULL,
`code` varchar(55) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
`user` varchar(45) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
`status` varchar(25) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
DROP TABLE IF EXISTS `tb_languages`;
CREATE TABLE `tb_languages` (
`id` int(11) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
ALTER TABLE `tbl_appconfig`
ADD PRIMARY KEY (`id`);
ALTER TABLE `tbl_bandwidth`
ADD PRIMARY KEY (`id`);
ALTER TABLE `tbl_customers`
ADD PRIMARY KEY (`id`);
ALTER TABLE `tbl_logs`
ADD PRIMARY KEY (`id`);
ALTER TABLE `tbl_message`
ADD PRIMARY KEY (`id`);
ALTER TABLE `tbl_payment_gateway`
ADD PRIMARY KEY (`id`);
ALTER TABLE `tbl_plans`
ADD PRIMARY KEY (`id`);
ALTER TABLE `tbl_pool`
ADD PRIMARY KEY (`id`);
ALTER TABLE `tbl_routers`
ADD PRIMARY KEY (`id`);
ALTER TABLE `tbl_transactions`
ADD PRIMARY KEY (`id`);
ALTER TABLE `tbl_users`
ADD PRIMARY KEY (`id`);
ALTER TABLE `tbl_user_recharges`
ADD PRIMARY KEY (`id`);
ALTER TABLE `tbl_voucher`
ADD PRIMARY KEY (`id`);
ALTER TABLE `tbl_appconfig`
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT;
ALTER TABLE `tbl_bandwidth`
MODIFY `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT;
ALTER TABLE `tbl_customers`
MODIFY `id` int(10) NOT NULL AUTO_INCREMENT;
ALTER TABLE `tbl_logs`
MODIFY `id` int(10) NOT NULL AUTO_INCREMENT;
ALTER TABLE `tbl_message`
MODIFY `id` int(10) NOT NULL AUTO_INCREMENT;
ALTER TABLE `tbl_payment_gateway`
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT;
ALTER TABLE `tbl_plans`
MODIFY `id` int(10) NOT NULL AUTO_INCREMENT;
ALTER TABLE `tbl_pool`
MODIFY `id` int(10) NOT NULL AUTO_INCREMENT;
ALTER TABLE `tbl_routers`
MODIFY `id` int(10) NOT NULL AUTO_INCREMENT;
ALTER TABLE `tbl_transactions`
MODIFY `id` int(10) NOT NULL AUTO_INCREMENT;
ALTER TABLE `tbl_users`
MODIFY `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT;
ALTER TABLE `tbl_user_recharges`
MODIFY `id` int(10) NOT NULL AUTO_INCREMENT;
ALTER TABLE `tbl_voucher`
MODIFY `id` int(10) NOT NULL AUTO_INCREMENT;
--
-- Dumping data untuk tabel `tbl_appconfig`
--
INSERT INTO
`tbl_appconfig` (`id`, `setting`, `value`)
VALUES (1, 'CompanyName', 'PHPNuxBill'), (2, 'currency_code', 'Rp.'), (3, 'language', 'english'), (4, 'show-logo', '1'), (5, 'nstyle', 'blue'), (6, 'timezone', 'Asia/Jakarta'), (7, 'dec_point', ','), (8, 'thousands_sep', '.'), (9, 'rtl', '0'), (10, 'address', ''), (11, 'phone', ''), (12, 'date_format', 'd M Y'), (13, 'note', 'Thank you...');
--
-- Dumping data untuk tabel `tbl_users`
--
INSERT INTO
`tbl_users` (
`id`,
`username`,
`fullname`,
`password`,
`user_type`,
`status`,
`last_login`,
`creationdate`
)
VALUES (
1,
'admin',
'Administrator',
'd033e22ae348aeb5660fc2140aec35850c4da997',
'SuperAdmin',
'Active',
'2022-09-06 16:09:50',
'2014-06-23 01:43:07'
);
DROP TABLE IF EXISTS `tbl_customers_fields`;
CREATE TABLE tbl_customers_fields (
id INT PRIMARY KEY AUTO_INCREMENT,
customer_id INT NOT NULL,
field_name VARCHAR(255) NOT NULL,
field_value VARCHAR(255) NOT NULL,
FOREIGN KEY (customer_id) REFERENCES tbl_customers(id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
ALTER TABLE `tbl_voucher` ADD `generated_by` INT NOT NULL DEFAULT '0' COMMENT 'id admin' AFTER `status`;
ALTER TABLE `tbl_users` ADD `root` INT NOT NULL DEFAULT '0' COMMENT 'for sub account' AFTER `id`;
ALTER TABLE `tbl_users` CHANGE `password` `password` VARCHAR(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL;
ALTER TABLE `tbl_users` ADD `phone` VARCHAR(32) NOT NULL DEFAULT '' AFTER `password`, ADD `email` VARCHAR(128) NOT NULL DEFAULT '' AFTER `phone`, ADD `city` VARCHAR(64) NOT NULL DEFAULT '' COMMENT 'kota' AFTER `email`, ADD `subdistrict` VARCHAR(64) NOT NULL DEFAULT '' COMMENT 'kecamatan' AFTER `city`, ADD `ward` VARCHAR(64) NOT NULL DEFAULT '' COMMENT 'kelurahan' AFTER `subdistrict`;
ALTER TABLE `tbl_customers` ADD `created_by` INT NOT NULL DEFAULT '0' AFTER `auto_renewal`;
ALTER TABLE `tbl_plans` ADD `list_expired` VARCHAR(32) NOT NULL DEFAULT '' COMMENT 'address list' AFTER `pool_expired`;
ALTER TABLE `tbl_bandwidth` ADD `burst` VARCHAR(128) NOT NULL DEFAULT '' AFTER `rate_up_unit`;
ALTER TABLE `tbl_transactions` ADD `admin_id` INT NOT NULL DEFAULT '1' AFTER `type`;
ALTER TABLE `tbl_user_recharges` ADD `admin_id` INT NOT NULL DEFAULT '1' AFTER `type`;
ALTER TABLE `tbl_plans` CHANGE `allow_purchase` `prepaid` ENUM('yes','no') CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT 'yes' COMMENT 'is prepaid';
ALTER TABLE `tbl_transactions` ADD `note` VARCHAR(256) NOT NULL DEFAULT '' COMMENT 'for note' AFTER `type`;
ALTER TABLE `tbl_payment_gateway` ADD `trx_invoice` VARCHAR(25) NOT NULL DEFAULT '' COMMENT 'from tbl_transactions' AFTER `paid_date`;

182
install/radius.sql Normal file
View File

@ -0,0 +1,182 @@
DROP TABLE IF EXISTS `nas`;
CREATE TABLE `nas` (
`id` int(10) NOT NULL,
`nasname` varchar(128) COLLATE utf8mb4_general_ci NOT NULL,
`shortname` varchar(32) COLLATE utf8mb4_general_ci DEFAULT NULL,
`type` varchar(30) COLLATE utf8mb4_general_ci DEFAULT 'other',
`ports` int(5) DEFAULT NULL,
`secret` varchar(60) COLLATE utf8mb4_general_ci NOT NULL DEFAULT 'secret',
`server` varchar(64) COLLATE utf8mb4_general_ci DEFAULT NULL,
`community` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL,
`description` varchar(200) COLLATE utf8mb4_general_ci DEFAULT 'RADIUS Client',
`routers` varchar(32) COLLATE utf8mb4_general_ci NOT NULL DEFAULT ''
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
DROP TABLE IF EXISTS `radacct`;
CREATE TABLE `radacct` (
`radacctid` bigint(21) NOT NULL,
`acctsessionid` varchar(64) COLLATE utf8mb4_general_ci NOT NULL DEFAULT '',
`acctuniqueid` varchar(32) COLLATE utf8mb4_general_ci NOT NULL DEFAULT '',
`username` varchar(64) COLLATE utf8mb4_general_ci NOT NULL DEFAULT '',
`realm` varchar(64) COLLATE utf8mb4_general_ci DEFAULT '',
`nasipaddress` varchar(15) COLLATE utf8mb4_general_ci NOT NULL DEFAULT '',
`nasportid` varchar(32) COLLATE utf8mb4_general_ci DEFAULT NULL,
`nasporttype` varchar(32) COLLATE utf8mb4_general_ci DEFAULT NULL,
`acctstarttime` datetime DEFAULT NULL,
`acctupdatetime` datetime DEFAULT NULL,
`acctstoptime` datetime DEFAULT NULL,
`acctinterval` int(12) DEFAULT NULL,
`acctsessiontime` int(12) UNSIGNED DEFAULT NULL,
`acctauthentic` varchar(32) COLLATE utf8mb4_general_ci DEFAULT NULL,
`connectinfo_start` varchar(128) COLLATE utf8mb4_general_ci DEFAULT NULL,
`connectinfo_stop` varchar(128) COLLATE utf8mb4_general_ci DEFAULT NULL,
`acctinputoctets` bigint(20) DEFAULT NULL,
`acctoutputoctets` bigint(20) DEFAULT NULL,
`calledstationid` varchar(50) COLLATE utf8mb4_general_ci NOT NULL DEFAULT '',
`callingstationid` varchar(50) COLLATE utf8mb4_general_ci NOT NULL DEFAULT '',
`acctterminatecause` varchar(32) COLLATE utf8mb4_general_ci NOT NULL DEFAULT '',
`servicetype` varchar(32) COLLATE utf8mb4_general_ci DEFAULT NULL,
`framedprotocol` varchar(32) COLLATE utf8mb4_general_ci DEFAULT NULL,
`framedipaddress` varchar(15) COLLATE utf8mb4_general_ci NOT NULL DEFAULT '',
`framedipv6address` varchar(45) COLLATE utf8mb4_general_ci NOT NULL DEFAULT '',
`framedipv6prefix` varchar(45) COLLATE utf8mb4_general_ci NOT NULL DEFAULT '',
`framedinterfaceid` varchar(44) COLLATE utf8mb4_general_ci NOT NULL DEFAULT '',
`delegatedipv6prefix` varchar(45) COLLATE utf8mb4_general_ci NOT NULL DEFAULT '',
`class` varchar(64) COLLATE utf8mb4_general_ci DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
DROP TABLE IF EXISTS `radcheck`;
CREATE TABLE `radcheck` (
`id` int(11) UNSIGNED NOT NULL,
`username` varchar(64) COLLATE utf8mb4_general_ci NOT NULL DEFAULT '',
`attribute` varchar(64) COLLATE utf8mb4_general_ci NOT NULL DEFAULT '',
`op` char(2) COLLATE utf8mb4_general_ci NOT NULL DEFAULT '==',
`value` varchar(253) COLLATE utf8mb4_general_ci NOT NULL DEFAULT ''
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
DROP TABLE IF EXISTS `radgroupcheck`;
CREATE TABLE `radgroupcheck` (
`id` int(11) UNSIGNED NOT NULL,
`groupname` varchar(64) COLLATE utf8mb4_general_ci NOT NULL DEFAULT '',
`attribute` varchar(64) COLLATE utf8mb4_general_ci NOT NULL DEFAULT '',
`op` char(2) COLLATE utf8mb4_general_ci NOT NULL DEFAULT '==',
`value` varchar(253) COLLATE utf8mb4_general_ci NOT NULL DEFAULT ''
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
DROP TABLE IF EXISTS `radgroupreply`;
CREATE TABLE `radgroupreply` (
`id` int(11) UNSIGNED NOT NULL,
`groupname` varchar(64) COLLATE utf8mb4_general_ci NOT NULL DEFAULT '',
`attribute` varchar(64) COLLATE utf8mb4_general_ci NOT NULL DEFAULT '',
`op` char(2) COLLATE utf8mb4_general_ci NOT NULL DEFAULT '=',
`value` varchar(253) COLLATE utf8mb4_general_ci NOT NULL DEFAULT '',
`plan_id` int(11) NOT NULL DEFAULT '0'
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
DROP TABLE IF EXISTS `radpostauth`;
CREATE TABLE `radpostauth` (
`id` int(11) NOT NULL,
`username` varchar(64) COLLATE utf8mb4_general_ci NOT NULL DEFAULT '',
`pass` varchar(64) COLLATE utf8mb4_general_ci NOT NULL DEFAULT '',
`reply` varchar(32) COLLATE utf8mb4_general_ci NOT NULL DEFAULT '',
`authdate` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6),
`class` varchar(64) COLLATE utf8mb4_general_ci DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
DROP TABLE IF EXISTS `radreply`;
CREATE TABLE `radreply` (
`id` int(11) UNSIGNED NOT NULL,
`username` varchar(64) COLLATE utf8mb4_general_ci NOT NULL DEFAULT '',
`attribute` varchar(64) COLLATE utf8mb4_general_ci NOT NULL DEFAULT '',
`op` char(2) COLLATE utf8mb4_general_ci NOT NULL DEFAULT '=',
`value` varchar(253) COLLATE utf8mb4_general_ci NOT NULL DEFAULT ''
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
DROP TABLE IF EXISTS `radusergroup`;
CREATE TABLE `radusergroup` (
`id` int(11) UNSIGNED NOT NULL,
`username` varchar(64) COLLATE utf8mb4_general_ci NOT NULL DEFAULT '',
`groupname` varchar(64) COLLATE utf8mb4_general_ci NOT NULL DEFAULT '',
`priority` int(11) NOT NULL DEFAULT '1'
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
DROP TABLE IF EXISTS `nasreload`;
CREATE TABLE `nasreload` (
nasipaddress varchar(15) NOT NULL,
reloadtime datetime NOT NULL,
PRIMARY KEY (nasipaddress)
) ENGINE = INNODB;
ALTER TABLE `nas`
ADD PRIMARY KEY (`id`),
ADD KEY `nasname` (`nasname`);
ALTER TABLE `radacct`
ADD PRIMARY KEY (`radacctid`),
ADD UNIQUE KEY `acctuniqueid` (`acctuniqueid`),
ADD KEY `username` (`username`),
ADD KEY `framedipaddress` (`framedipaddress`),
ADD KEY `framedipv6address` (`framedipv6address`),
ADD KEY `framedipv6prefix` (`framedipv6prefix`),
ADD KEY `framedinterfaceid` (`framedinterfaceid`),
ADD KEY `delegatedipv6prefix` (`delegatedipv6prefix`),
ADD KEY `acctsessionid` (`acctsessionid`),
ADD KEY `acctsessiontime` (`acctsessiontime`),
ADD KEY `acctstarttime` (`acctstarttime`),
ADD KEY `acctinterval` (`acctinterval`),
ADD KEY `acctstoptime` (`acctstoptime`),
ADD KEY `nasipaddress` (`nasipaddress`),
ADD KEY `class` (`class`);
ALTER TABLE `radcheck`
ADD PRIMARY KEY (`id`),
ADD KEY `username` (`username`(32));
ALTER TABLE `radgroupcheck`
ADD PRIMARY KEY (`id`),
ADD KEY `groupname` (`groupname`(32));
ALTER TABLE `radgroupreply`
ADD PRIMARY KEY (`id`),
ADD KEY `groupname` (`groupname`(32));
ALTER TABLE `radpostauth`
ADD PRIMARY KEY (`id`),
ADD KEY `username` (`username`),
ADD KEY `class` (`class`);
ALTER TABLE `radreply`
ADD PRIMARY KEY (`id`),
ADD KEY `username` (`username`(32));
ALTER TABLE `radusergroup`
ADD PRIMARY KEY (`id`),
ADD KEY `username` (`username`(32));
ALTER TABLE `nas`
MODIFY `id` int(10) NOT NULL AUTO_INCREMENT;
ALTER TABLE `radacct`
MODIFY `radacctid` bigint(21) NOT NULL AUTO_INCREMENT;
ALTER TABLE `radcheck`
MODIFY `id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT;
ALTER TABLE `radgroupcheck`
MODIFY `id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT;
ALTER TABLE `radgroupreply`
MODIFY `id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT;
ALTER TABLE `radpostauth`
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT;
ALTER TABLE `radreply`
MODIFY `id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT;
ALTER TABLE `radusergroup`
MODIFY `id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT;
SET FOREIGN_KEY_CHECKS=1;

67
install/step2.php Normal file
View File

@ -0,0 +1,67 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>PHPNuxBill Installer</title>
<link rel="shortcut icon" type="image/x-icon" href="img/favicon.ico">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!--[if lt IE 9]>
<script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
<link type='text/css' href='css/style.css' rel='stylesheet' />
<link type='text/css' href="css/bootstrap.min.css" rel="stylesheet">
</head>
<body style='background-color: #FBFBFB;'>
<div id='main-container'>
<img src="img/logo.png" class="img-responsive" alt="Logo" />
<hr>
<div class="span12">
<h4> PHPNuxBill Installer </h4>
<?php
$passed = '';
$ltext = '';
if (version_compare(PHP_VERSION, '7.2.0') >= 0) {
$ltext .= 'To Run PHPNuxBill You need at least PHP version 7.2.0, Your PHP Version is: ' . PHP_VERSION . " Tested <strong>---PASSED---</strong><br/>";
$passed .= '1';
} else {
$ltext .= 'To Run PHPNuxBill You need at least PHP version 7.2.0, Your PHP Version is: ' . PHP_VERSION . " Tested <strong>---FAILED---</strong><br/>";
$passed .= '0';
}
if (extension_loaded('PDO')) {
$ltext .= 'PDO is installed on your server: ' . "Tested <strong>---PASSED---</strong><br/>";
$passed .= '1';
} else {
$ltext = 'PDO is installed on your server: ' . "Tested <strong>---FAILED---</strong><br/>";
$passed .= '0';
}
if (extension_loaded('pdo_mysql')) {
$ltext .= 'PDO MySQL driver is enabled on your server: ' . "Tested <strong>---PASSED---</strong><br/>";
$passed .= '1';
} else {
$ltext .= 'PDO MySQL driver is not enabled on your server: ' . "Tested <strong>---FAILED---</strong><br/>";
$passed .= '0';
}
if ($passed == '111') {
echo ("<br/> $ltext <br/> Great! System Test Completed. You can run PHPNuxBill on your server. Click Continue For Next Step.
<br><br>
<a href=\"step3.php\" class=\"btn btn-primary\">Continue</a><br><br><a href=\"update.php\" class=\"btn btn-primary\">Update System</a>");
} else {
echo ("<br/> $ltext <br/> Sorry. The requirements of PHPNuxBill is not available on your server.
Contact with us at Telegram <a href=\"https://t.me/phpnuxbill\">@phpnuxbill</a> with this code- $passed Or contact with your server administrator
<br><br>
<a href=\"#\" class=\"btn btn-primary disabled\">Correct The Problem To Continue</a>");
}
?>
</div>
</div>
<div class="footer">Copyright &copy; 2021 PHPNuxBill. All Rights Reserved<br /><br /></div>
</body>
</html>

View File

@ -1,72 +1,74 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>PHPMixBill Installer</title>
<link rel="shortcut icon" type="image/x-icon" href="img/favicon.ico">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!--[if lt IE 9]>
<script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
<link type='text/css' href='css/style.css' rel='stylesheet'/>
<link type='text/css' href="css/bootstrap.min.css" rel="stylesheet">
</head>
<body style='background-color: #FBFBFB;'>
<div id='main-container'>
<div class='header'>
<div class="header-box wrapper">
<div class="hd-logo"><a href="#"><img src="img/logo.png" alt="Logo"/></a></div>
</div>
</div>
<div class="span12">
<h4> PHPMixBill Installer </h4>
<?php
if (isset($_GET['_error']) && ($_GET['_error']) == '1') {
echo '<h4 style="color: red;"> Unable to Connect Database, Please make sure database info is correct and try again ! </h4>';
}
$cururl = 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
$appurl = str_replace('/install/step3.php', '', $cururl);
$appurl = str_replace('?_error=1', '', $appurl);
$appurl = str_replace('/system', '', $appurl);
?>
<form action="step4.php" method="post">
<fieldset>
<legend>Database Connection &amp Site config</legend>
<div class="form-group">
<label for="appurl">Application URL</label>
<input type="text" class="form-control" id="appurl" name="appurl" value="<?php echo $appurl; ?>">
<span class='help-block'>Application url without trailing slash at the end of url (e.g. http://172.16.10.10). Please keep default, if you are unsure.</span>
</div>
<div class="form-group">
<label for="dbhost">Database Host</label>
<input type="text" class="form-control" id="dbhost" name="dbhost">
</div>
<div class="form-group">
<label for="dbuser">Database Username</label>
<input type="text" class="form-control" id="dbuser" name="dbuser">
</div>
<div class="form-group">
<label for="dbpass">Database Password</label>
<input type="text" class="form-control" id="dbpass" name="dbpass">
</div>
<div class="form-group">
<label for="dbname">Database Name</label>
<input type="text" class="form-control" id="dbname" name="dbname">
</div>
<button type="submit" class="btn btn-primary">Submit</button>
</fieldset>
</form>
</div>
</div>
<div class="footer">Copyright &copy; 2021 PHPMixBill. All Rights Reserved<br/><br/></div>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<title>PHPNuxBill Installer</title>
<link rel="shortcut icon" type="image/x-icon" href="img/favicon.ico">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!--[if lt IE 9]>
<script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
<link type='text/css' href='css/style.css' rel='stylesheet'/>
<link type='text/css' href="css/bootstrap.min.css" rel="stylesheet">
</head>
<body style='background-color: #FBFBFB;'>
<div id='main-container'>
<img src="img/logo.png" class="img-responsive" alt="Logo" />
<hr>
<div class="span12">
<h4> PHPNuxBill Installer </h4>
<?php
if (isset($_GET['_error']) && ($_GET['_error']) == '1') {
echo '<h4 style="color: red;"> Unable to Connect Database, Please make sure database info is correct and try again ! </h4>';
}//
$cururl = (((!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off')|| $_SERVER['SERVER_PORT'] == 443)?'https':'http').'://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
$appurl = str_replace('/install/step3.php', '', $cururl);
$appurl = str_replace('?_error=1', '', $appurl);
$appurl = str_replace('/system', '', $appurl);
?>
<form action="step4.php" method="post">
<fieldset>
<legend>Database Connection &amp Site config</legend>
<div class="form-group">
<label for="appurl">Application URL</label>
<input type="text" class="form-control" id="appurl" name="appurl" value="<?php echo $appurl; ?>">
<span class='help-block'>Application url without trailing slash at the end of url (e.g. http://172.16.10.10). Please keep default, if you are unsure.</span>
</div>
<div class="form-group">
<label for="dbhost">Database Host</label>
<input type="text" class="form-control" id="dbhost" name="dbhost">
</div>
<div class="form-group">
<label for="dbuser">Database Username</label>
<input type="text" class="form-control" id="dbuser" name="dbuser">
</div>
<div class="form-group">
<label for="dbpass">Database Password</label>
<input type="text" class="form-control" id="dbpass" name="dbpass">
</div>
<div class="form-group">
<label for="dbname">Database Name</label>
<input type="text" class="form-control" id="dbname" name="dbname">
</div>
<div class="form-group">
<label for="dbname"><input type="checkbox" class="form-control" id="radius" name="radius" value="yes"> Install Radius Table?</label>
</div>
<button type="submit" class="btn btn-primary">Submit</button>
</fieldset>
</form>
</div>
</div>
<div class="footer">Copyright &copy; 2021 PHPNuxBill. All Rights Reserved<br/><br/></div>
</body>
</html>

148
install/step4.php Normal file
View File

@ -0,0 +1,148 @@
<?php
/**
* PHP Mikrotik Billing (https://github.com/hotspotbilling/phpnuxbill/)
* by https://t.me/ibnux
**/
//error_reporting (0);
$appurl = $_POST['appurl'];
$db_host = $_POST['dbhost'];
$db_user = $_POST['dbuser'];
$db_password = $_POST['dbpass'];
$db_name = $_POST['dbname'];
$cn = '0';
try {
$dbh = new pdo(
"mysql:host=$db_host;dbname=$db_name",
"$db_user",
"$db_password",
array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION)
);
$cn = '1';
} catch (PDOException $ex) {
$cn = '0';
}
if ($cn == '1') {
if (isset($_POST['radius']) && $_POST['radius'] == 'yes') {
$input = '<?php
define(\'APP_URL\', \'' . $appurl . '\');
$_app_stage = \'Live\';
// Database PHPNuxBill
$db_host = \'' . $db_host . '\';
$db_user = \'' . $db_user . '\';
$db_password = \'' . $db_password . '\';
$db_name = \'' . $db_name . '\';
// Database Radius
$radius_host = \'' . $db_host . '\';
$radius_user = \'' . $db_user . '\';
$radius_pass = \'' . $db_password . '\';
$radius_name = \'' . $db_name . '\';
if($_app_stage!=\'Live\'){
error_reporting(E_ERROR);
ini_set(\'display_errors\', 1);
ini_set(\'display_startup_errors\', 1);
}else{
error_reporting(E_ERROR);
ini_set(\'display_errors\', 0);
ini_set(\'display_startup_errors\', 0);
}
';
} else {
$input = '<?php
define(\'APP_URL\', \'' . $appurl . '\');
$_app_stage = \'Live\';
// Database PHPNuxBill
$db_host = \'' . $db_host . '\';
$db_user = \'' . $db_user . '\';
$db_password = \'' . $db_password . '\';
$db_name = \'' . $db_name . '\';
if($_app_stage!=\'Live\'){
error_reporting(E_ERROR);
ini_set(\'display_errors\', 1);
ini_set(\'display_startup_errors\', 1);
}else{
error_reporting(E_ERROR);
ini_set(\'display_errors\', 0);
ini_set(\'display_startup_errors\', 0);
}
';
}
$wConfig = "../config.php";
$fh = fopen($wConfig, 'w') or die("Can't create config file, your server does not support 'fopen' function,
please create a file named - config.php with following contents- <br/>$input");
fwrite($fh, $input);
fclose($fh);
$sql = file_get_contents('phpnuxbill.sql');
$qr = $dbh->exec($sql);
if (isset($_POST['radius']) && $_POST['radius'] == 'yes') {
$sql = file_get_contents('radius.sql');
$qrs = $dbh->exec($sql);
}
} else {
header("location: step3.php?_error=1");
exit;
}
?>
<!DOCTYPE html>
<html lang="en">
<head>
<title>PHPNuxBill Installer</title>
<link rel="shortcut icon" type="image/x-icon" href="img/favicon.ico">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!--[if lt IE 9]>
<script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
<link type='text/css' href='css/style.css' rel='stylesheet' />
<link type='text/css' href="css/bootstrap.min.css" rel="stylesheet">
</head>
<body style='background-color: #FBFBFB;'>
<div id='main-container'>
<img src="img/logo.png" class="img-responsive" alt="Logo" />
<hr>
<div class="span12">
<h4> PHPNuxBill Installer </h4>
<?php
if ($cn == '1') {
?>
<p><strong>Config File Created and Database Imported.</strong><br></p>
<form action="step5.php" method="post">
<fieldset>
<legend>Click Continue</legend>
<button type='submit' class='btn btn-primary'>Continue</button>
</fieldset>
</form>
<?php
} elseif ($cn == '2') {
?>
<p> MySQL Connection was successfull. An error occured while adding data on MySQL. Unsuccessfull
Installation. Please refer manual installation in the website github.com/ibnux/phpnuxbill/wiki or Contact Telegram @ibnux for
helping on installation</p>
<?php
} else {
?>
<p> MySQL Connection Failed.</p>
<?php
}
?>
</div>
</div>
<div class="footer">Copyright &copy; 2021 PHPNuxBill. All Rights Reserved<br /><br /></div>
</body>
</html>

55
install/step5.php Normal file
View File

@ -0,0 +1,55 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>PHPNuxBill Installer</title>
<link rel="shortcut icon" type="image/x-icon" href="img/favicon.ico">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!--[if lt IE 9]>
<script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
<link type='text/css' href='css/style.css' rel='stylesheet' />
<link type='text/css' href="css/bootstrap.min.css" rel="stylesheet">
</head>
<?php if (!file_exists('../pages')) rename('../pages_template', '../pages'); ?>
<body style='background-color: #FBFBFB;'>
<div id='main-container'>
<img src="img/logo.png" class="img-responsive" alt="Logo" />
<hr>
<div class="span12">
<h4> PHPNuxBill Installer </h4>
<p>
<strong>Congratulations!</strong><br>
You have just install PHPNuxBill !<br><br>
<span class="text-danger">But wait!!<br>
<ol>
<li>Don't forget to rename folder <b>pages_example</b> to <b>pages</b>.<br>
if it not yet renamed</li>
<li>Activate <a href="https://github.com/hotspotbilling/phpnuxbill/wiki/Cron-Jobs" target="_blank">Cronjob</a> for Expired and Reminder.</li>
<li>Check <a href="https://github.com/hotspotbilling/phpnuxbill/wiki/How-It-Works---Cara-kerja" target="_blank">how PHPNuxbill Works</a></li>
<li><a href="https://github.com/hotspotbilling/phpnuxbill/wiki#login-page-mikrotik" target="_blank">how to link Mikrotik Login to PHPNuxBill</a></li>
<li>or use <a href="https://github.com/hotspotbilling/phpnuxbill-mikrotik-login-template" target="_blank">Mikrotik Login Template for PHPNuxBill</a></li>
</ol>
</span><br><br>
To Login Admin Portal:<br>
Use this link -
<?php
$cururl = (((!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') || $_SERVER['SERVER_PORT'] == 443) ? 'https' : 'http') . '://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
$appurl = str_replace('/install/step5.php', '', $cururl);
$appurl = str_replace('/system', '', $appurl);
echo '<a href="' . $appurl . '/admin">' . $appurl . '/admin</a>';
?>
<br>
Username: admin<br>
Password: admin<br>
For security, Delete the <b>install</b> directory inside system folder.
</p>
</div>
</div>
<div class="footer">Copyright &copy; 2021 PHPNuxBill. All Rights Reserved<br /><br /></div>
</body>
</html>

106
install/update.php Normal file
View File

@ -0,0 +1,106 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>PHPNuxBill Updaters</title>
<link rel="shortcut icon" type="image/x-icon" href="img/favicon.ico">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!--[if lt IE 9]>
<script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
<link type='text/css' href='css/style.css' rel='stylesheet' />
<link type='text/css' href="css/bootstrap.min.css" rel="stylesheet">
</head>
<body style='background-color: #FBFBFB;'>
<div id='main-container'>
<img src="img/logo.png" class="img-responsive" alt="Logo" />
<hr>
<div class="span12">
<h4> PHPNuxBill Updater </h4>
<pre><?php
include '../config.php';
try{
$dbh = new pdo( "mysql:host=$db_host;dbname=$db_name",
"$db_user",
"$db_password",
array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION));
echo "CREATE TABLE `tbl_payment_gateway` (
`id` int(11) NOT NULL,
`username` varchar(32) COLLATE utf8mb4_general_ci NOT NULL,
`gateway` varchar(32) COLLATE utf8mb4_general_ci NOT NULL COMMENT 'xendit | midtrans',
`gateway_trx_id` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '',
`plan_id` int(11) NOT NULL,
`plan_name` varchar(40) COLLATE utf8mb4_general_ci NOT NULL,
`routers_id` int(11) NOT NULL,
`routers` varchar(32) COLLATE utf8mb4_general_ci NOT NULL,
`price` varchar(40) COLLATE utf8mb4_general_ci NOT NULL,
`pg_url_payment` varchar(256) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '',
`payment_method` varchar(32) COLLATE utf8mb4_general_ci NOT NULL DEFAULT '',
`payment_channel` varchar(32) COLLATE utf8mb4_general_ci NOT NULL DEFAULT '',
`pg_request` text COLLATE utf8mb4_general_ci,
`pg_paid_response` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci,
`expired_date` datetime DEFAULT NULL,
`created_date` datetime NOT NULL,
`paid_date` datetime DEFAULT NULL,
`status` tinyint(1) NOT NULL DEFAULT '1' COMMENT '1 unpaid 2 paid 3 failed 4 canceled'
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_general_ci;\n\n";
$dbh->exec("CREATE TABLE
`tbl_payment_gateway` (
`id` int(11) NOT NULL,
`username` varchar(32) COLLATE utf8mb4_general_ci NOT NULL,
`gateway` varchar(32) COLLATE utf8mb4_general_ci NOT NULL COMMENT 'xendit | midtrans',
`gateway_trx_id` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '',
`plan_id` int(11) NOT NULL,
`plan_name` varchar(40) COLLATE utf8mb4_general_ci NOT NULL,
`routers_id` int(11) NOT NULL,
`routers` varchar(32) COLLATE utf8mb4_general_ci NOT NULL,
`price` varchar(40) COLLATE utf8mb4_general_ci NOT NULL,
`pg_url_payment` varchar(256) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '',
`payment_method` varchar(32) COLLATE utf8mb4_general_ci NOT NULL DEFAULT '',
`payment_channel` varchar(32) COLLATE utf8mb4_general_ci NOT NULL DEFAULT '',
`pg_request` text COLLATE utf8mb4_general_ci,
`pg_paid_response` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci,
`expired_date` datetime DEFAULT NULL,
`created_date` datetime NOT NULL,
`paid_date` datetime DEFAULT NULL,
`status` tinyint(1) NOT NULL DEFAULT '1' COMMENT '1 unpaid 2 paid 3 failed 4 canceled'
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_general_ci;");
echo "ALTER TABLE `tbl_payment_gateway` ADD PRIMARY KEY (`id`);\n\n";
$dbh->exec("ALTER TABLE `tbl_payment_gateway` ADD PRIMARY KEY (`id`);");
echo "ALTER TABLE `tbl_payment_gateway` MODIFY `id` int(11) NOT NULL AUTO_INCREMENT;\n\n";
$dbh->exec("ALTER TABLE `tbl_payment_gateway` MODIFY `id` int(11) NOT NULL AUTO_INCREMENT;");
echo "ALTER TABLE `tbl_customers` ADD `email` VARCHAR(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' AFTER `phonenumber`;\n\n";
$dbh->exec("ALTER TABLE `tbl_customers` ADD `email` VARCHAR(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' AFTER `phonenumber`;");
echo "ALTER TABLE `tbl_plans` CHANGE `validity_unit` `validity_unit` ENUM('Mins','Hrs','Days','Months') CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL;\n\n";
$dbh->exec("ALTER TABLE `tbl_plans` CHANGE `validity_unit` `validity_unit` ENUM('Mins','Hrs','Days','Months') CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL");
echo "ALTER TABLE `tbl_plans` ADD `enabled` tinyint(1) NOT NULL DEFAULT '1' COMMENT '0 disabled' AFTER `pool`;\n\n";
$dbh->exec("ALTER TABLE `tbl_plans` ADD `enabled` tinyint(1) NOT NULL DEFAULT '1' COMMENT '0 disabled' AFTER `pool`;");
echo "ALTER TABLE `tbl_routers` ADD `enabled` tinyint(1) NOT NULL DEFAULT '1' COMMENT '0 disabled' AFTER `description`;\n\n";
$dbh->exec("ALTER TABLE `tbl_routers` ADD `enabled` tinyint(1) NOT NULL DEFAULT '1' COMMENT '0 disabled' AFTER `description`;");
echo "ALTER TABLE `tbl_routers` CHANGE `description` `description` VARCHAR(256) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL;";
$dbh->exec("ALTER TABLE `tbl_routers` CHANGE `description` `description` VARCHAR(256) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL;");
echo "ALTER TABLE `tbl_user_recharges` CHANGE `method` `method` VARCHAR(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '';\n\n";
$dbh->exec("ALTER TABLE `tbl_user_recharges` CHANGE `method` `method` VARCHAR(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '';");
echo "ALTER TABLE `tbl_transactions` CHANGE `method` `method` VARCHAR(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL;\n\n";
$dbh->exec("ALTER TABLE `tbl_transactions` CHANGE `method` `method` VARCHAR(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL;");
echo "Success update database for new system <a href='/admin/'>Back To Home</a>";
}catch(PDOException $ex){
echo "Error Failed to connect to database: ".$ex->getMessage()."\n";
}
?></pre>
</div>
</div>
<div class="footer">Copyright &copy; 2021 PHPNuxBill. All Rights Reserved<br /><br /></div>
</body>
</html>

View File

@ -1,31 +0,0 @@
<center><strong style="font-size:38px">{$_c['CompanyName']}</strong></center>
<table width="100%" border="1" cellspacing="0" cellpadding="4" bordercolor="#757575">
<tbody>
<tr>
<td valign="top" align="left">Pendaftaran dan Informasi Billing buka <b>billing.ibnux.net</b></td>
</tr>
<tr>
<td valign="top" align="left">Wireless Hotspot:
<table width="100%" border="0" cellspacing="0" cellpadding="2">
<tr>
<td>iBNuXnet</td>
<td>iBNuXnet-P</td>
<td>iBNuXnet-Q</td>
</tr>
<tr>
<td>CitraGadingBlokP 3/4</td>
<td>CitraGadingBlokQ 2/3/4/5/6</td>
<td>iBNuXnet 5Ghz</td>
</tr>
</table>
</td>
</tr>
<tr>
<td valign="top" align="left">Voucher yang sudah dibeli tidak dapat dikembalikan</td>
</tr>
<tr>
<td valign="top" align="center"><b>hotspot.ibnux.net</b></td>
</tr>
</tbody>
</table>

View File

@ -1 +1,3 @@
Pengumuman!!<br>Besok libur<br><br>Announcement!!<br>Tomorrow holiday<br>
Pengumuman!!<br>Besok libur<br><br>Announcement!!<br>Tomorrow holiday<br><br>
<br>
This Announcement is for Login Page.

View File

@ -0,0 +1,8 @@
Pengumuman Pelanggan!!<br>
Besok libur<br>
<br>
Customer Announcement!!<br>
Tomorrow holiday<br>
<br>
<br>
This Announcement is for Customer Dashboard

View File

@ -0,0 +1,62 @@
<h1>Privacy Policy for PHPNuxBill</h1>
<p>At PHPNuxBill, accessible from https://github.com/hotspotbilling/phpnuxbill, one of our main priorities is the
privacy of our visitors. This Privacy Policy document contains types of information that is collected and recorded
by PHPNuxBill and how we use it.</p>
<p>If you have additional questions or require more information about our Privacy Policy, do not hesitate to contact us.
</p>
<h2>Log Files</h2>
<p>PHPNuxBill follows a standard procedure of using log files. These files log visitors when they visit websites. All
hosting companies do this and a part of hosting services' analytics. The information collected by log files include
internet protocol (IP) addresses, browser type, Internet Service Provider (ISP), date and time stamp, referring/exit
pages, and possibly the number of clicks. These are not linked to any information that is personally identifiable.
The purpose of the information is for analyzing trends, administering the site, tracking users' movement on the
website, and gathering demographic information. Our Privacy Policy was created with the help of the <a
href="https://www.privacypolicyonline.com/privacy-policy-generator/">Privacy Policy Generator</a>.</p>
<h2>Privacy Policies</h2>
<P>You may consult this list to find the Privacy Policy for each of the advertising partners of PHPNuxBill.</p>
<p>Third-party ad servers or ad networks uses technologies like cookies, JavaScript, or Web Beacons that are used in
their respective advertisements and links that appear on PHPNuxBill, which are sent directly to users' browser. They
automatically receive your IP address when this occurs. These technologies are used to measure the effectiveness of
their advertising campaigns and/or to personalize the advertising content that you see on websites that you visit.
</p>
<p>Note that PHPNuxBill has no access to or control over these cookies that are used by third-party advertisers.</p>
<h2>Third Party Privacy Policies</h2>
<p>PHPNuxBill's Privacy Policy does not apply to other advertisers or websites. Thus, we are advising you to consult the
respective Privacy Policies of these third-party ad servers for more detailed information. It may include their
practices and instructions about how to opt-out of certain options. </p>
<p>You can choose to disable cookies through your individual browser options. To know more detailed information about
cookie management with specific web browsers, it can be found at the browsers' respective websites. What Are
Cookies?</p>
<h2>Children's Information</h2>
<p>Another part of our priority is adding protection for children while using the internet. We encourage parents and
guardians to observe, participate in, and/or monitor and guide their online activity.</p>
<p>PHPNuxBill does not knowingly collect any Personal Identifiable Information from children under the age of 13. If you
think that your child provided this kind of information on our website, we strongly encourage you to contact us
immediately and we will do our best efforts to promptly remove such information from our records.</p>
<h2>Online Privacy Policy Only</h2>
<p>This Privacy Policy applies only to our online activities and is valid for visitors to our website with regards to
the information that they shared and/or collect in PHPNuxBill. This policy is not applicable to any information
collected offline or via channels other than this website.</p>
<h2>Consent</h2>
<p>By using our website, you hereby consent to our Privacy Policy and agree to its Terms and Conditions.</p>

View File

@ -0,0 +1,119 @@
<h2><strong>Terms and Conditions</strong></h2>
<p>Welcome to PHPNuxBill!</p>
<p>These terms and conditions outline the rules and regulations for the use of PHPNuxBill's Website, located at https://github.com/hotspotbilling/phpnuxbill.</p>
<p>By accessing this website we assume you accept these terms and conditions. Do not continue to use PHPNuxBill if you do not agree to take all of the terms and conditions stated on this page.</p>
<p>The following terminology applies to these Terms and Conditions, Privacy Statement and Disclaimer Notice and all Agreements: "Client", "You" and "Your" refers to you, the person log on this website and compliant to the Companys terms and conditions. "The Company", "Ourselves", "We", "Our" and "Us", refers to our Company. "Party", "Parties", or "Us", refers to both the Client and ourselves. All terms refer to the offer, acceptance and consideration of payment necessary to undertake the process of our assistance to the Client in the most appropriate manner for the express purpose of meeting the Clients needs in respect of provision of the Companys stated services, in accordance with and subject to, prevailing law of Netherlands. Any use of the above terminology or other words in the singular, plural, capitalization and/or he/she or they, are taken as interchangeable and therefore as referring to same. Our Terms and Conditions were created with the help of the <a href="https://www.privacypolicyonline.com/terms-conditions-generator/">Terms & Conditions Generator</a>.</p>
<h3><strong>Cookies</strong></h3>
<p>We employ the use of cookies. By accessing PHPNuxBill, you agreed to use cookies in agreement with the PHPNuxBill's Privacy Policy.</p>
<p>Most interactive websites use cookies to let us retrieve the user's details for each visit. Cookies are used by our website to enable the functionality of certain areas to make it easier for people visiting our website. Some of our affiliate/advertising partners may also use cookies.</p>
<h3><strong>License</strong></h3>
<p>Unless otherwise stated, PHPNuxBill and/or its licensors own the intellectual property rights for all material on PHPNuxBill. All intellectual property rights are reserved. You may access this from PHPNuxBill for your own personal use subjected to restrictions set in these terms and conditions.</p>
<p>You must not:</p>
<ul>
<li>Republish material from PHPNuxBill</li>
<li>Sell, rent or sub-license material from PHPNuxBill</li>
<li>Reproduce, duplicate or copy material from PHPNuxBill</li>
<li>Redistribute content from PHPNuxBill</li>
</ul>
<p>This Agreement shall begin on the date hereof.</p>
<p>Parts of this website offer an opportunity for users to post and exchange opinions and information in certain areas of the website. PHPNuxBill does not filter, edit, publish or review Comments prior to their presence on the website. Comments do not reflect the views and opinions of PHPNuxBill,its agents and/or affiliates. Comments reflect the views and opinions of the person who post their views and opinions. To the extent permitted by applicable laws, PHPNuxBill shall not be liable for the Comments or for any liability, damages or expenses caused and/or suffered as a result of any use of and/or posting of and/or appearance of the Comments on this website.</p>
<p>PHPNuxBill reserves the right to monitor all Comments and to remove any Comments which can be considered inappropriate, offensive or causes breach of these Terms and Conditions.</p>
<p>You warrant and represent that:</p>
<ul>
<li>You are entitled to post the Comments on our website and have all necessary licenses and consents to do so;</li>
<li>The Comments do not invade any intellectual property right, including without limitation copyright, patent or trademark of any third party;</li>
<li>The Comments do not contain any defamatory, libelous, offensive, indecent or otherwise unlawful material which is an invasion of privacy</li>
<li>The Comments will not be used to solicit or promote business or custom or present commercial activities or unlawful activity.</li>
</ul>
<p>You hereby grant PHPNuxBill a non-exclusive license to use, reproduce, edit and authorize others to use, reproduce and edit any of your Comments in any and all forms, formats or media.</p>
<h3><strong>Hyperlinking to our Content</strong></h3>
<p>The following organizations may link to our Website without prior written approval:</p>
<ul>
<li>Government agencies;</li>
<li>Search engines;</li>
<li>News organizations;</li>
<li>Online directory distributors may link to our Website in the same manner as they hyperlink to the Websites of other listed businesses; and</li>
<li>System wide Accredited Businesses except soliciting non-profit organizations, charity shopping malls, and charity fundraising groups which may not hyperlink to our Web site.</li>
</ul>
<p>These organizations may link to our home page, to publications or to other Website information so long as the link: (a) is not in any way deceptive; (b) does not falsely imply sponsorship, endorsement or approval of the linking party and its products and/or services; and (c) fits within the context of the linking party's site.</p>
<p>We may consider and approve other link requests from the following types of organizations:</p>
<ul>
<li>commonly-known consumer and/or business information sources;</li>
<li>dot.com community sites;</li>
<li>associations or other groups representing charities;</li>
<li>online directory distributors;</li>
<li>internet portals;</li>
<li>accounting, law and consulting firms; and</li>
<li>educational institutions and trade associations.</li>
</ul>
<p>We will approve link requests from these organizations if we decide that: (a) the link would not make us look unfavorably to ourselves or to our accredited businesses; (b) the organization does not have any negative records with us; (c) the benefit to us from the visibility of the hyperlink compensates the absence of PHPNuxBill; and (d) the link is in the context of general resource information.</p>
<p>These organizations may link to our home page so long as the link: (a) is not in any way deceptive; (b) does not falsely imply sponsorship, endorsement or approval of the linking party and its products or services; and (c) fits within the context of the linking party's site.</p>
<p>If you are one of the organizations listed in paragraph 2 above and are interested in linking to our website, you must inform us by sending an e-mail to PHPNuxBill. Please include your name, your organization name, contact information as well as the URL of your site, a list of any URLs from which you intend to link to our Website, and a list of the URLs on our site to which you would like to link. Wait 2-3 weeks for a response.</p>
<p>Approved organizations may hyperlink to our Website as follows:</p>
<ul>
<li>By use of our corporate name; or</li>
<li>By use of the uniform resource locator being linked to; or</li>
<li>By use of any other description of our Website being linked to that makes sense within the context and format of content on the linking party's site.</li>
</ul>
<p>No use of PHPNuxBill's logo or other artwork will be allowed for linking absent a trademark license agreement.</p>
<h3><strong>iFrames</strong></h3>
<p>Without prior approval and written permission, you may not create frames around our Webpages that alter in any way the visual presentation or appearance of our Website.</p>
<h3><strong>Content Liability</strong></h3>
<p>We shall not be hold responsible for any content that appears on your Website. You agree to protect and defend us against all claims that is rising on your Website. No link(s) should appear on any Website that may be interpreted as libelous, obscene or criminal, or which infringes, otherwise violates, or advocates the infringement or other violation of, any third party rights.</p>
<h3><strong>Reservation of Rights</strong></h3>
<p>We reserve the right to request that you remove all links or any particular link to our Website. You approve to immediately remove all links to our Website upon request. We also reserve the right to amen these terms and conditions and it's linking policy at any time. By continuously linking to our Website, you agree to be bound to and follow these linking terms and conditions.</p>
<h3><strong>Removal of links from our website</strong></h3>
<p>If you find any link on our Website that is offensive for any reason, you are free to contact and inform us any moment. We will consider requests to remove links but we are not obligated to or so or to respond to you directly.</p>
<p>We do not ensure that the information on this website is correct, we do not warrant its completeness or accuracy; nor do we promise to ensure that the website remains available or that the material on the website is kept up to date.</p>
<h3><strong>Disclaimer</strong></h3>
<p>To the maximum extent permitted by applicable law, we exclude all representations, warranties and conditions relating to our website and the use of this website. Nothing in this disclaimer will:</p>
<ul>
<li>limit or exclude our or your liability for death or personal injury;</li>
<li>limit or exclude our or your liability for fraud or fraudulent misrepresentation;</li>
<li>limit any of our or your liabilities in any way that is not permitted under applicable law; or</li>
<li>exclude any of our or your liabilities that may not be excluded under applicable law.</li>
</ul>
<p>The limitations and prohibitions of liability set in this Section and elsewhere in this disclaimer: (a) are subject to the preceding paragraph; and (b) govern all liabilities arising under the disclaimer, including liabilities arising in contract, in tort and for breach of statutory duty.</p>
<p>As long as the website and the information and services on the website are provided free of charge, we will not be liable for any loss or damage of any nature.</p>

View File

@ -0,0 +1,27 @@
<table border="0" cellspacing="0" cellpadding="2">
<tr>
<td valign="middle">
<center><strong style="font-size:38px">[[company_name]]</strong></center>
<table width="100%" border="1" cellspacing="0" cellpadding="1" bordercolor="#757575">
<tbody>
<tr>
<td rowspan="4" width="1">[[qrcode]]
</td>
</tr>
<tr>
<td valign="middle" align="center" style="font-size:25px">
[[price]]</td>
</tr>
<tr>
<td valign="middle" align="center" style="font-size:20px">
[[voucher_code]]</td>
</tr>
<tr>
<td valign="middle" align="center" style="font-size:15px">
[[plan]]</td>
</tr>
</tbody>
</table>
</td>
</tr>
</table>

View File

@ -4,14 +4,13 @@
*
* Config file, feel free to modify
*/
define('QR_CACHEABLE', true); // use cache - more disk reads but less CPU power, masks and format templates are stored there
define('QR_CACHE_DIR', dirname(__FILE__).DIRECTORY_SEPARATOR.'cache'.DIRECTORY_SEPARATOR); // used when QR_CACHEABLE === true
define('QR_LOG_DIR', dirname(__FILE__).DIRECTORY_SEPARATOR); // default error logs dir
//define('QR_LOG_DIR', dirname(__FILE__).DIRECTORY_SEPARATOR); // default error logs dir
define('QR_FIND_BEST_MASK', true); // if true, estimates best mask (spec. default, but extremally slow; set to false to significant performance boost but (propably) worst quality code
define('QR_FIND_FROM_RANDOM', false); // if false, checks all masks available, otherwise value tells count of masks need to be checked, mask id are got randomly
define('QR_DEFAULT_MASK', 2); // when QR_FIND_BEST_MASK === false
define('QR_PNG_MAXIMUM_SIZE', 1024); // maximum allowed png image width (in pixels), tune to make sure GD and PHP can handle such big images

19
system/.htaccess Normal file
View File

@ -0,0 +1,19 @@
<Files *.php>
Order Deny,Allow
Deny from all
</Files>
<Files cron.php>
Order Allow,Deny
Allow from all
</Files>
<Files api.php>
Order Allow,Deny
Allow from all
</Files>
<Files cron_reminder.php>
Order Allow,Deny
Allow from all
</Files>

127
system/api.php Normal file
View File

@ -0,0 +1,127 @@
<?php
/**
* PHP Mikrotik Billing (https://github.com/hotspotbilling/phpnuxbill/)
* by https://t.me/ibnux
*
* This File is for API Access
**/
if ($_SERVER['REQUEST_METHOD'] === "OPTIONS" || $_SERVER['REQUEST_METHOD'] === "HEAD") {
header('Access-Control-Allow-Origin: *');
header("Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept, Access-Control-Request-Method, Access-Control-Request-Headers, Authorization");
header("HTTP/1.1 200 OK");
die();
}
$isApi = true;
include "../init.php";
// Dummy Class
$ui = new class($key)
{
var $assign = [];
function display($key)
{
global $req;
showResult(true, $req, $this->getAll());
}
function assign($key, $value)
{
$this->assign[$key] = $value;
}
function get($key)
{
if (isset($this->assign[$key])) {
return $this->assign[$key];
}
return '';
}
function getTemplateVars($key)
{
if (isset($this->assign[$key])) {
return $this->assign[$key];
}
return '';
}
function getAll()
{
return $this->assign;
}
};
$req = _get('r');
# a/c.id.time.md5
# md5(a/c.id.time.$api_secret)
$token = _req('token');
$routes = explode('/', $req);
$handler = $routes[0];
if (!empty($token)) {
if ($token == $config['api_key']) {
$admin = ORM::for_table('tbl_users')->where('user_type', 'SuperAdmin')->find_one($id);
if (empty($admin)) {
$admin = ORM::for_table('tbl_users')->where('user_type', 'Admin')->find_one($id);
if (empty($admin)) {
showResult(false, Lang::T("Token is invalid"));
}
}
} else {
# validate token
list($tipe, $uid, $time, $sha1) = explode('.', $token);
if (trim($sha1) != sha1($uid . '.' . $time . '.' . $api_secret)) {
showResult(false, Lang::T("Token is invalid"));
}
#cek token expiration
// 3 bulan
if ($time != 0 && time() - $time > 7776000) {
die("$time != " . (time() - $time));
showResult(false, Lang::T("Token Expired"), [], ['login' => true]);
}
if ($tipe == 'a') {
$_SESSION['aid'] = $uid;
$admin = Admin::_info();
} else if ($tipe == 'c') {
$_SESSION['uid'] = $uid;
} else {
showResult(false, Lang::T("Unknown Token"), [], ['login' => true]);
}
}
if (!isset($handler) || empty($handler)) {
showResult(true, Lang::T("Token is valid"));
}
if ($handler == 'isValid') {
showResult(true, Lang::T("Token is valid"));
}
if ($handler == 'me') {
$admin = Admin::_info();
if (!empty($admin['id'])) {
showResult(true, "", $admin);
} else {
showResult(false, Lang::T("Token is invalid"));
}
}
}else{
unset($_COOKIE);
unset($_SESSION);
}
try {
$sys_render = File::pathFixer($root_path . 'system/controllers/' . $handler . '.php');
if (file_exists($sys_render)) {
include($sys_render);
showResult(true, $req, $ui->getAll());
} else {
showResult(false, Lang::T('Command not found'));
}
} catch (Exception $e) {
showResult(false, $e->getMessage());
}

View File

@ -1,17 +1,61 @@
<?php
/**
* PHP Mikrotik Billing (https://ibnux.github.io/phpmixbill/)
* PHP Mikrotik Billing (https://github.com/hotspotbilling/phpnuxbill/)
* by https://t.me/ibnux
**/
* @copyright Copyright (C) 2014-2015 PHP Mikrotik Billing
* @license GNU General Public License version 2 or later; see LICENSE.txt
class Admin
{
**/
Class Admin{
public static function _info(){
$id = $_SESSION['aid'];
$d = ORM::for_table('tbl_users')->find_one($id);
return $d;
public static function getID()
{
global $db_password;
if (isset($_SESSION['aid'])) {
return $_SESSION['aid'];
} else if (isset($_COOKIE['aid'])) {
// id.time.sha1
$tmp = explode('.', $_COOKIE['aid']);
if (sha1($tmp[0] . '.' . $tmp[1] . '.' . $db_password) == $tmp[2]) {
if (time() - $tmp[1] < 86400 * 7) {
$_SESSION['aid'] = $tmp[0];
return $tmp[0];
}
}
}
return 0;
}
}
public static function setCookie($aid)
{
global $db_password;
if (isset($aid)) {
$time = time();
$token = $aid . '.' . $time . '.' . sha1($aid . '.' . $time . '.' . $db_password);
setcookie('aid', $token, time() + 86400 * 7);
return $token;
}
return '';
}
public static function removeCookie()
{
if (isset($_COOKIE['aid'])) {
setcookie('aid', '', time() - 86400);
}
}
public static function _info($id = 0)
{
if (empty($id) && $id == 0) {
$id = Admin::getID();
}
if ($id) {
return ORM::for_table('tbl_users')->find_one($id);
} else {
return null;
}
}
}

View File

@ -1,16 +1,29 @@
<?php
/**
* PHP Mikrotik Billing (https://ibnux.github.io/phpmixbill/)
* PHP Mikrotik Billing (https://github.com/hotspotbilling/phpnuxbill/)
* by https://t.me/ibnux
**/
* @copyright Copyright (C) 2014-2015 PHP Mikrotik Billing
* @license GNU General Public License version 2 or later; see LICENSE.txt
**/
Class App{
class App{
public static function _run(){
return true;
}
public static function getToken(){
return md5(microtime());
}
public static function setToken($token, $value){
$_SESSION[$token] = $value;
}
public static function getTokenValue($key){
if(isset($_SESSION[$key])){
return $_SESSION[$key];
}else{
return "";
}
}
}

View File

@ -0,0 +1,64 @@
<?php
/**
* PHP Mikrotik Billing (https://github.com/hotspotbilling/phpnuxbill/)
* by https://t.me/ibnux
**/
/**
* This script is for managing user balance
**/
class Balance
{
public static function plus($id_customer, $amount)
{
$c = ORM::for_table('tbl_customers')->where('id', $id_customer)->find_one();
$c->balance = $amount + $c['balance'];
$c->save();
}
public static function transfer($id_customer, $phoneTarget, $amount)
{
global $config;
if (Balance::min($id_customer, $amount)) {
return Balance::plusByPhone($phoneTarget, $amount);
} else {
return false;
}
}
public static function min($id_customer, $amount)
{
$c = ORM::for_table('tbl_customers')->where('id', $id_customer)->find_one();
if ($c && $c['balance'] >= $amount) {
$c->balance = $c['balance'] - $amount;
$c->save();
return true;
} else {
return false;
}
}
public static function plusByPhone($phone_customer, $amount)
{
$c = ORM::for_table('tbl_customers')->where('username', $phone_customer)->find_one();
if ($c) {
$c->balance = $amount + $c['balance'];
$c->save();
return true;
}
return false;
}
public static function minByPhone($phone_customer, $amount)
{
$c = ORM::for_table('tbl_customers')->where('username', $phone_customer)->find_one();
if ($c && $c['balance'] >= $amount) {
$c->balance = $c['balance'] - $amount;
$c->save();
return true;
} else {
return false;
}
}
}

108
system/autoload/File.php Normal file
View File

@ -0,0 +1,108 @@
<?php
/**
* PHP Mikrotik Billing (https://github.com/hotspotbilling/phpnuxbill/)
* by https://t.me/ibnux
**/
class File
{
public static function copyFolder($from, $to, $exclude = [])
{
$files = scandir($from);
foreach ($files as $file) {
if (is_file($from . $file) && !in_array($file, $exclude)) {
if (file_exists($to . $file)) unlink($to . $file);
rename($from . $file, $to . $file);
} else if (is_dir($from . $file) && !in_array($file, ['.', '..'])) {
if (!file_exists($to . $file)) {
mkdir($to . $file);
}
File::copyFolder($from . $file . DIRECTORY_SEPARATOR, $to . $file . DIRECTORY_SEPARATOR, $exclude);
}
}
}
public static function deleteFolder($path)
{
$files = scandir($path);
foreach ($files as $file) {
if (is_file($path . $file)) {
unlink($path . $file);
} else if (is_dir($path . $file) && !in_array($file, ['.', '..'])) {
File::deleteFolder($path . $file . DIRECTORY_SEPARATOR);
rmdir($path . $file);
}
}
rmdir($path);
}
public static function resizeCropImage($source_file, $dst_dir, $max_width, $max_height, $quality = 80)
{
$imgsize = getimagesize($source_file);
$width = $imgsize[0];
$height = $imgsize[1];
$mime = $imgsize['mime'];
switch ($mime) {
case 'image/gif':
$image_create = "imagecreatefromgif";
$image = "imagegif";
break;
case 'image/png':
$image_create = "imagecreatefrompng";
$image = "imagepng";
$quality = 7;
break;
case 'image/jpeg':
$image_create = "imagecreatefromjpeg";
$image = "imagejpeg";
$quality = 80;
break;
default:
return false;
break;
}
if ($max_width == 0) {
$max_width = $width;
}
if ($max_height == 0) {
$max_height = $height;
}
$widthRatio = $max_width / $width;
$heightRatio = $max_height / $height;
$ratio = min($widthRatio, $heightRatio);
$nwidth = (int)$width * $ratio;
$nheight = (int)$height * $ratio;
$dst_img = imagecreatetruecolor($nwidth, $nheight);
$white = imagecolorallocate($dst_img, 255, 255, 255);
imagefill($dst_img, 0, 0, $white);
$src_img = $image_create($source_file);
imagecopyresampled($dst_img, $src_img, 0, 0, 0, 0, $nwidth, $nheight, $width, $height);
$image($dst_img, $dst_dir, $quality);
if ($dst_img) imagedestroy($dst_img);
if ($src_img) imagedestroy($src_img);
return file_exists($dst_dir);
}
/**
* file path fixer
*
* @access public
* @param string $path
* @return string
*/
public static function pathFixer($path)
{
return str_replace("/", DIRECTORY_SEPARATOR, $path);
}
}

View File

@ -0,0 +1,57 @@
<?php
/**
* PHP Mikrotik Billing (https://github.com/hotspotbilling/phpnuxbill/)
* by https://t.me/ibnux
**/
$menu_registered = array();
/**
* Register for global menu
* @param string name Name of the menu
* @param bool admin true if for admin and false for customer
* @param string function function to run after menu clicks
* @param string position position of menu, use AFTER_ for root menu |
* Admin/Sales menu: AFTER_DASHBOARD, CUSTOMERS, PREPAID, SERVICES, REPORTS, VOUCHER, AFTER_ORDER, NETWORK, SETTINGS, AFTER_PAYMENTGATEWAY
* | Customer menu: AFTER_DASHBOARD, ORDER, HISTORY, ACCOUNTS
* @param string icon from ion icon, ion-person, only for AFTER_
* @param string label for showing label or number of notification or update
* @param string color Label color
* @param string auth authorization ['SuperAdmin', 'Admin', 'Report', 'Agent', 'Sales'] will only show in this user, empty array for all users
*/
function register_menu($name, $admin, $function, $position, $icon = '', $label = '', $color = 'success', $auth = [])
{
global $menu_registered;
$menu_registered[] = [
"name" => $name,
"admin" => $admin,
"position" => $position,
"icon" => $icon,
"function" => $function,
"label" => $label,
"color" => $color,
"auth" => $auth
];
}
$hook_registered = array();
function register_hook($action, $function){
global $hook_registered;
$hook_registered[] = [
'action' => $action,
'function' => $function
];
}
function run_hook($action){
global $hook_registered;
foreach($hook_registered as $hook){
if($hook['action'] == $action){
if(function_exists($hook['function'])){
call_user_func($hook['function']);
}
}
}
}

117
system/autoload/Http.php Normal file
View File

@ -0,0 +1,117 @@
<?php
/**
* PHP Mikrotik Billing (https://github.com/hotspotbilling/phpnuxbill/)
* by https://t.me/ibnux
**/
/**
* using proxy, add this variable in config.php
* $http_proxy = '127.0.0.1:3128';
* if proxy using authentication, use this parameter
* $http_proxyauth = 'user:password';
**/
class Http
{
public static function getData($url, $headers = [])
{
global $http_proxy, $http_proxyauth, $admin;
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, 0);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 15);
curl_setopt($ch, CURLOPT_TIMEOUT, 15);
if(is_array($headers) && count($headers)>0){
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
}
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
if (!empty($http_proxy)) {
curl_setopt($ch, CURLOPT_PROXY, $http_proxy);
if (!empty($http_proxyauth)) {
curl_setopt($ch, CURLOPT_PROXYUSERPWD, $http_proxyauth);
}
}
$server_output = curl_exec($ch);
if (curl_errno($ch)) {
$error_msg = curl_error($ch);
}
curl_close($ch);
if($admin && $error_msg){
r2(U . 'dashboard', 'd', $error_msg);
}
return ($server_output) ? $server_output : $error_msg;
}
public static function postJsonData($url, $array_post, $headers = [], $basic = null)
{
global $http_proxy, $http_proxyauth, $admin;
$headers[] = 'Content-Type: application/json';
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 15);
curl_setopt($ch, CURLOPT_TIMEOUT, 15);
curl_setopt($ch, CURLOPT_VERBOSE, false);
curl_setopt($ch, CURLINFO_HEADER_OUT, false);
if (!empty($http_proxy)) {
curl_setopt($ch, CURLOPT_PROXY, $http_proxy);
if (!empty($http_proxyauth)) {
curl_setopt($ch, CURLOPT_PROXYUSERPWD, $http_proxyauth);
}
}
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($array_post));
if(is_array($headers) && count($headers)>0){
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
}
if (!empty($basic)) {
curl_setopt($ch, CURLOPT_USERPWD, $basic);
}
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$server_output = curl_exec($ch);
if (curl_errno($ch)) {
$error_msg = curl_error($ch);
}
curl_close($ch);
if($admin && $error_msg){
r2(U . 'dashboard', 'd', $error_msg);
}
return ($server_output) ? $server_output : $error_msg;
}
public static function postData($url, $array_post, $headers = [], $basic = null)
{
global $http_proxy, $http_proxyauth, $admin;
$headers[] = 'Content-Type: application/x-www-form-urlencoded';
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 15);
curl_setopt($ch, CURLOPT_TIMEOUT, 15);
curl_setopt($ch, CURLOPT_VERBOSE, false);
curl_setopt($ch, CURLINFO_HEADER_OUT, false);
if (!empty($http_proxy)) {
curl_setopt($ch, CURLOPT_PROXY, $http_proxy);
if (!empty($http_proxyauth)) {
curl_setopt($ch, CURLOPT_PROXYUSERPWD, $http_proxyauth);
}
}
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($array_post));
if(is_array($headers) && count($headers)>0){
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
}
if (!empty($basic)) {
curl_setopt($ch, CURLOPT_USERPWD, $basic);
}
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$server_output = curl_exec($ch);
if (curl_errno($ch)) {
$error_msg = curl_error($ch);
}
curl_close($ch);
if($admin && $error_msg){
r2(U . 'dashboard', 'd', $error_msg);
}
return ($server_output) ? $server_output : $error_msg;
}
}

248
system/autoload/Lang.php Normal file
View File

@ -0,0 +1,248 @@
<?php
/**
* PHP Mikrotik Billing (https://github.com/hotspotbilling/phpnuxbill/)
* by https://t.me/ibnux
**/
class Lang
{
public static function T($key)
{
global $_L, $lan_file, $config;
if(is_array($_SESSION['Lang'])){
$_L = array_merge($_L, $_SESSION['Lang']);
}
$key = preg_replace('/\s+/', ' ', $key);
if (!empty($_L[$key])) {
return $_L[$key];
}
$val = $key;
$key = Lang::sanitize($key);
if (isset($_L[$key])) {
return $_L[$key];
} else if (isset($_L[$key])) {
return $_L[$key];
} else {
$iso = Lang::getIsoLang()[$config['language']];
if (empty($iso)) {
return $val;
}
if (!empty($iso) && !empty($val)) {
$temp = Lang::translate($val, $iso);
if (!empty($temp)) {
$val = $temp;
}
}
$_L[$key] = $val;
$_SESSION['Lang'][$key] = $val;
file_put_contents($lan_file, json_encode($_SESSION['Lang'], JSON_PRETTY_PRINT));
return $val;
}
}
public static function sanitize($str)
{
return preg_replace("/[^A-Za-z0-9]/", '_', $str);;
}
public static function getIsoLang()
{
global $isolang;
if (empty($isolang) || count($isolang) == 0) {
$isolang = json_decode(file_get_contents(File::pathFixer("system/lan/country.json")), true);
}
return $isolang;
}
public static function htmlspecialchars($var)
{
return htmlspecialchars($var);
}
public static function moneyFormat($var)
{
global $config;
return $config['currency_code'] . ' ' . number_format($var, 0, $config['dec_point'], $config['thousands_sep']);
}
public static function phoneFormat($phone)
{
global $config;
if (Validator::UnsignedNumber($phone) && !empty($config['country_code_phone'])) {
return preg_replace('/^0/', $config['country_code_phone'], $phone);
} else {
return $phone;
}
}
public static function dateFormat($date)
{
global $config;
return date($config['date_format'], strtotime($date));
}
public static function dateTimeFormat($date)
{
global $config;
if (strtotime($date) < strtotime("2000-01-01 00:00:00")) {
return "";
} else {
return date($config['date_format'] . ' H:i', strtotime($date));
}
}
public static function dateAndTimeFormat($date, $time)
{
global $config;
return date($config['date_format'] . ' H:i', strtotime("$date $time"));
}
public static function timeElapsed($datetime, $full = false)
{
$now = new DateTime;
$ago = new DateTime($datetime);
$diff = $now->diff($ago);
$diff->w = floor($diff->d / 7);
$diff->d -= $diff->w * 7;
$string = array(
'y' => Lang::T('year'),
'm' => Lang::T('month'),
'w' => Lang::T('week'),
'd' => Lang::T('day'),
'h' => Lang::T('hour'),
'i' => Lang::T('minute'),
's' => Lang::T('second'),
);
foreach ($string as $k => &$v) {
if ($diff->$k) {
$v = $diff->$k . ' ' . $v . ($diff->$k > 1 ? 's' : '');
} else {
unset($string[$k]);
}
}
if (!$full)
$string = array_slice($string, 0, 1);
return $string ? implode(', ', $string) . ' ago' : 'just now';
}
public static function nl2br($text)
{
return nl2br($text);
}
public static function arrayCount($arr)
{
if (is_array($arr)) {
return count($arr);
} else if (is_object($arr)) {
return count($arr);
} else {
return 0;
}
}
public static function getNotifText($key)
{
global $_notifmsg, $_notifmsg_default;
if (isset($_notifmsg[$key])) {
return $_notifmsg[$key];
} else {
return $_notifmsg_default[$key];
}
}
public static function ucWords($text)
{
return ucwords(str_replace('_', ' ', $text));
}
public static function randomUpLowCase($text)
{
$jml = strlen($text);
$result = '';
for ($i = 0; $i < $jml; $i++) {
if (rand(0, 99) % 2) {
$result .= strtolower(substr($text, $i, 1));
} else {
$result .= substr($text, $i, 1);
}
}
return $result;
}
/**
* $pad_type
* 0 Left
* 1 right
* 2 center
* */
public static function pad($text, $pad_string = ' ', $pad_type = 0)
{
global $config;
$cols = 37;
if ($config['printer_cols']) {
$cols = $config['printer_cols'];
}
$text = trim($text);
$texts = explode("\n", $text);
if (count($texts) > 1) {
$text = '';
foreach ($texts as $t) {
$text .= self::pad(trim($t), $pad_string, $pad_type) . "\n";
}
return $text;
} else {
return str_pad(trim($text), $cols, $pad_string, $pad_type);
}
}
public static function pads($textLeft, $textRight, $pad_string = ' ')
{
global $config;
$cols = 37;
if ($config['printer_cols']) {
$cols = $config['printer_cols'];
}
return $textLeft . str_pad($textRight, $cols - strlen($textLeft), $pad_string, 0);
}
public static function translate($txt, $to = 'id')
{
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "https://translate.google.com/m?hl=en&sl=en&tl=$to&ie=UTF-8&prev=_m&q=" . urlencode($txt));
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($ch, CURLOPT_USERAGENT, "Mozilla/5.0 (iPhone; CPU OS 13_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) FxiOS/28.1 Mobile/15E148 Safari/605.1.15");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 2);
curl_setopt($ch, CURLOPT_TIMEOUT, 5);
curl_setopt($ch, CURLOPT_HEADER, 0);
$hasil = curl_exec($ch);
curl_close($ch);
$temp = explode('<div class="result-container">', $hasil);
if (count($temp) > 0) {
$temp = explode("</div", $temp[1]);
if (!empty($temp[0])) {
return $temp[0];
}
}
return $txt;
}
public static function maskText($text){
$len = strlen($text);
if($len < 3){
return "***";
}else if($len<5){
return substr($text,0,1)."***".substr($text,-1,1);
}else if($len<8){
return substr($text,0,2)."***".substr($text,-2,2);
}else{
return substr($text,0,4)."******".substr($text,-3,3);
}
}
}

32
system/autoload/Log.php Normal file
View File

@ -0,0 +1,32 @@
<?php
/**
* PHP Mikrotik Billing (https://github.com/hotspotbilling/phpnuxbill/)
* by https://t.me/ibnux
**/
class Log{
public static function put($type, $description, $userid = '', $username = '')
{
$d = ORM::for_table('tbl_logs')->create();
$d->date = date('Y-m-d H:i:s');
$d->type = $type;
$d->description = $description;
$d->userid = $userid;
$d->ip = (empty($username)) ? $_SERVER["REMOTE_ADDR"] : $username;
$d->save();
}
public static function arrayToText($array, $start = '', $result = '')
{
foreach ($array as $k => $v) {
if (is_array($v)) {
$result = Log::arrayToText($v, "$start$k.", $result);
} else {
$result .= $start.$k ." : ". strval($v) ."\n";
}
}
return $result;
}
}

212
system/autoload/Message.php Normal file
View File

@ -0,0 +1,212 @@
<?php
/**
* PHP Mikrotik Billing (https://github.com/hotspotbilling/phpnuxbill/)
* by https://t.me/ibnux
**/
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\Exception;
use PHPMailer\PHPMailer\SMTP;
require $root_path . 'system/autoload/mail/Exception.php';
require $root_path . 'system/autoload/mail/PHPMailer.php';
require $root_path . 'system/autoload/mail/SMTP.php';
class Message
{
public static function sendTelegram($txt)
{
global $config;
run_hook('send_telegram'); #HOOK
if (!empty($config['telegram_bot']) && !empty($config['telegram_target_id'])) {
return Http::getData('https://api.telegram.org/bot' . $config['telegram_bot'] . '/sendMessage?chat_id=' . $config['telegram_target_id'] . '&text=' . urlencode($txt));
}
}
public static function sendSMS($phone, $txt)
{
global $config;
if(empty($txt)){
return "";
}
run_hook('send_sms'); #HOOK
if (!empty($config['sms_url'])) {
if (strlen($config['sms_url']) > 4 && substr($config['sms_url'], 0, 4) != "http") {
if (strlen($txt) > 160) {
$txts = str_split($txt, 160);
try {
$mikrotik = Mikrotik::info($config['sms_url']);
$client = Mikrotik::getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']);
foreach ($txts as $txt) {
Mikrotik::sendSMS($client, $phone, $txt);
}
} catch (Exception $e) {
// ignore, add to logs
_log("Failed to send SMS using Mikrotik.\n" . $e->getMessage(), 'SMS', 0);
}
} else {
try {
$mikrotik = Mikrotik::info($config['sms_url']);
$client = Mikrotik::getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']);
Mikrotik::sendSMS($client, $phone, $txt);
} catch (Exception $e) {
// ignore, add to logs
_log("Failed to send SMS using Mikrotik.\n" . $e->getMessage(), 'SMS', 0);
}
}
} else {
$smsurl = str_replace('[number]', urlencode($phone), $config['sms_url']);
$smsurl = str_replace('[text]', urlencode($txt), $smsurl);
return Http::getData($smsurl);
}
}
}
public static function sendWhatsapp($phone, $txt)
{
global $config;
if(empty($txt)){
return "";
}
run_hook('send_whatsapp'); #HOOK
if (!empty($config['wa_url'])) {
$waurl = str_replace('[number]', urlencode(Lang::phoneFormat($phone)), $config['wa_url']);
$waurl = str_replace('[text]', urlencode($txt), $waurl);
return Http::getData($waurl);
}
}
public static function sendEmail($to, $subject, $body)
{
global $config;
if(empty($body)){
return "";
}
run_hook('send_email'); #HOOK
if (empty($config['smtp_host'])) {
$attr = "";
if (!empty($config['mail_from'])) {
$attr .= "From: " . $config['mail_from'] . "\r\n";
}
if (!empty($config['mail_reply_to'])) {
$attr .= "Reply-To: " . $config['mail_reply_to'] . "\r\n";
}
mail($to, $subject, $body, $attr);
} else {
$mail = new PHPMailer();
$mail->isSMTP();
$mail->SMTPDebug = SMTP::DEBUG_SERVER;
$mail->Host = $config['smtp_host'];
$mail->SMTPAuth = true;
$mail->Username = $config['smtp_user'];
$mail->Password = $config['smtp_pass'];
$mail->SMTPSecure = $config['smtp_ssltls'];
$mail->Port = $config['smtp_port'];
if (!empty($config['mail_from'])) {
$mail->setFrom($config['mail_from']);
}
if (!empty($config['mail_reply_to'])) {
$mail->addReplyTo($config['mail_reply_to']);
}
$mail->isHTML(false);
$mail->addAddress($to);
$mail->Subject = $subject;
$mail->Body = $body;
$mail->send();
}
}
public static function sendPackageNotification($customer, $package, $price, $message, $via)
{
global $ds;
if(empty($message)){
return "";
}
$msg = str_replace('[[name]]', $customer['fullname'], $message);
$msg = str_replace('[[username]]', $customer['username'], $msg);
$msg = str_replace('[[plan]]', $package, $msg);
$msg = str_replace('[[package]]', $package, $msg);
$msg = str_replace('[[price]]', Lang::moneyFormat($price), $msg);
list($bills, $add_cost) = User::getBills($customer['id']);
if($add_cost>0){
$note = "";
foreach ($bills as $k => $v) {
$note .= $k . " : " . Lang::moneyFormat($v) . "\n";
}
$note .= "Total : " . Lang::moneyFormat($add_cost+$price) . "\n";
$msg = str_replace('[[bills]]', $note, $msg);
}else{
$msg = str_replace('[[bills]]', '', $msg);
}
if ($ds) {
$msg = str_replace('[[expired_date]]', Lang::dateAndTimeFormat($ds['expiration'], $ds['time']), $msg);
}else{
$msg = str_replace('[[expired_date]]', "", $msg);
}
if (
!empty($customer['phonenumber']) && strlen($customer['phonenumber']) > 5
&& !empty($message) && in_array($via, ['sms', 'wa'])
) {
if ($via == 'sms') {
echo Message::sendSMS($customer['phonenumber'], $msg);
} else if ($via == 'wa') {
echo Message::sendWhatsapp($customer['phonenumber'], $msg);
}
}
return "$via: $msg";
}
public static function sendBalanceNotification($phone, $name, $balance, $balance_now, $message, $via)
{
$msg = str_replace('[[name]]', $name, $message);
$msg = str_replace('[[current_balance]]', Lang::moneyFormat($balance_now), $msg);
$msg = str_replace('[[balance]]', Lang::moneyFormat($balance), $msg);
if (
!empty($phone) && strlen($phone) > 5
&& !empty($message) && in_array($via, ['sms', 'wa'])
) {
if ($via == 'sms') {
Message::sendSMS($phone, $msg);
} else if ($via == 'wa') {
Message::sendWhatsapp($phone, $msg);
}
}
return "$via: $msg";
}
public static function sendInvoice($cust, $trx)
{
global $config;
$textInvoice = Lang::getNotifText('invoice_paid');
$textInvoice = str_replace('[[company_name]]', $config['CompanyName'], $textInvoice);
$textInvoice = str_replace('[[address]]', $config['address'], $textInvoice);
$textInvoice = str_replace('[[phone]]', $config['phone'], $textInvoice);
$textInvoice = str_replace('[[invoice]]', $trx['invoice'], $textInvoice);
$textInvoice = str_replace('[[date]]', Lang::dateAndTimeFormat($trx['recharged_on'], $trx['recharged_time']), $textInvoice);
if (!empty($trx['note'])) {
$textInvoice = str_replace('[[note]]', $trx['note'], $textInvoice);
}
$gc = explode("-", $trx['method']);
$textInvoice = str_replace('[[payment_gateway]]', trim($gc[0]), $textInvoice);
$textInvoice = str_replace('[[payment_channel]]', trim($gc[1]), $textInvoice);
$textInvoice = str_replace('[[type]]', $trx['type'], $textInvoice);
$textInvoice = str_replace('[[plan_name]]', $trx['plan_name'], $textInvoice);
$textInvoice = str_replace('[[plan_price]]', Lang::moneyFormat($trx['price']), $textInvoice);
$textInvoice = str_replace('[[name]]', $cust['fullname'], $textInvoice);
$textInvoice = str_replace('[[note]]', $cust['note'], $textInvoice);
$textInvoice = str_replace('[[user_name]]', $trx['username'], $textInvoice);
$textInvoice = str_replace('[[user_password]]', $cust['password'], $textInvoice);
$textInvoice = str_replace('[[username]]', $trx['username'], $textInvoice);
$textInvoice = str_replace('[[password]]', $cust['password'], $textInvoice);
$textInvoice = str_replace('[[expired_date]]', Lang::dateAndTimeFormat($trx['expiration'], $trx['time']), $textInvoice);
$textInvoice = str_replace('[[footer]]', $config['note'], $textInvoice);
if ($config['user_notification_payment'] == 'sms') {
Message::sendSMS($cust['phonenumber'], $textInvoice);
} else if ($config['user_notification_payment'] == 'wa') {
Message::sendWhatsapp($cust['phonenumber'], $textInvoice);
}
}
}

View File

@ -0,0 +1,562 @@
<?php
/**
* PHP Mikrotik Billing (https://github.com/hotspotbilling/phpnuxbill/)
* by https://t.me/ibnux
**/
use PEAR2\Net\RouterOS;
class Mikrotik
{
public static function info($name)
{
return ORM::for_table('tbl_routers')->where('name', $name)->find_one();
}
public static 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);
}
public static function isUserLogin($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('.id');
}
public static function logMeIn($client, $user, $pass, $ip, $mac)
{
global $_app_stage;
if ($_app_stage == 'demo') {
return null;
}
$addRequest = new RouterOS\Request('/ip/hotspot/active/login');
$client->sendSync(
$addRequest
->setArgument('user', $user)
->setArgument('password', $pass)
->setArgument('ip', $ip)
->setArgument('mac-address', $mac)
);
}
public static function logMeOut($client, $user)
{
global $_app_stage;
if ($_app_stage == 'demo') {
return null;
}
$printRequest = new RouterOS\Request(
'/ip hotspot active print',
RouterOS\Query::where('user', $user)
);
$id = $client->sendSync($printRequest)->getProperty('.id');
$removeRequest = new RouterOS\Request('/ip/hotspot/active/remove');
$client->sendSync(
$removeRequest
->setArgument('numbers', $id)
);
}
public static function addHotspotPlan($client, $name, $sharedusers, $rate)
{
global $_app_stage;
if ($_app_stage == 'demo') {
return null;
}
$addRequest = new RouterOS\Request('/ip/hotspot/user/profile/add');
$client->sendSync(
$addRequest
->setArgument('name', $name)
->setArgument('shared-users', $sharedusers)
->setArgument('rate-limit', $rate)
);
}
public static function setHotspotPlan($client, $name, $sharedusers, $rate)
{
global $_app_stage;
if ($_app_stage == 'demo') {
return null;
}
$printRequest = new RouterOS\Request(
'/ip hotspot user profile print .proplist=.id',
RouterOS\Query::where('name', $name)
);
$profileID = $client->sendSync($printRequest)->getProperty('.id');
if (empty($profileID)) {
Mikrotik::addHotspotPlan($client, $name, $sharedusers, $rate);
} else {
$setRequest = new RouterOS\Request('/ip/hotspot/user/profile/set');
$client->sendSync(
$setRequest
->setArgument('numbers', $profileID)
->setArgument('shared-users', $sharedusers)
->setArgument('rate-limit', $rate)
);
}
}
public static function setHotspotExpiredPlan($client, $name, $pool)
{
global $_app_stage;
if ($_app_stage == 'demo') {
return null;
}
$printRequest = new RouterOS\Request(
'/ip hotspot user profile print .proplist=.id',
RouterOS\Query::where('name', $name)
);
$profileID = $client->sendSync($printRequest)->getProperty('.id');
if (empty($profileID)) {
$addRequest = new RouterOS\Request('/ip/hotspot/user/profile/add');
$client->sendSync(
$addRequest
->setArgument('name', $name)
->setArgument('shared-users', 3)
->setArgument('address-pool', $pool)
->setArgument('rate-limit', '512K/512K')
);
} else {
$setRequest = new RouterOS\Request('/ip/hotspot/user/profile/set');
$client->sendSync(
$setRequest
->setArgument('numbers', $profileID)
->setArgument('shared-users', 3)
->setArgument('address-pool', $pool)
->setArgument('rate-limit', '512K/512K')
);
}
}
public static function removeHotspotPlan($client, $name)
{
global $_app_stage;
if ($_app_stage == 'demo') {
return null;
}
$printRequest = new RouterOS\Request(
'/ip hotspot user profile print .proplist=.id',
RouterOS\Query::where('name', $name)
);
$profileID = $client->sendSync($printRequest)->getProperty('.id');
$removeRequest = new RouterOS\Request('/ip/hotspot/user/profile/remove');
$client->sendSync(
$removeRequest
->setArgument('numbers', $profileID)
);
}
public static function removeHotspotUser($client, $username)
{
global $_app_stage;
if ($_app_stage == 'demo') {
return null;
}
$printRequest = new RouterOS\Request(
'/ip hotspot user print .proplist=.id',
RouterOS\Query::where('name', $username)
);
$userID = $client->sendSync($printRequest)->getProperty('.id');
$removeRequest = new RouterOS\Request('/ip/hotspot/user/remove');
$client->sendSync(
$removeRequest
->setArgument('numbers', $userID)
);
}
public static function addHotspotUser($client, $plan, $customer)
{
global $_app_stage;
if ($_app_stage == 'demo') {
return null;
}
$addRequest = new RouterOS\Request('/ip/hotspot/user/add');
if ($plan['typebp'] == "Limited") {
if ($plan['limit_type'] == "Time_Limit") {
if ($plan['time_unit'] == 'Hrs')
$timelimit = $plan['time_limit'] . ":00:00";
else
$timelimit = "00:" . $plan['time_limit'] . ":00";
$client->sendSync(
$addRequest
->setArgument('name', $customer['username'])
->setArgument('profile', $plan['name_plan'])
->setArgument('password', $customer['password'])
->setArgument('comment', $customer['fullname'])
->setArgument('email', $customer['email'])
->setArgument('limit-uptime', $timelimit)
);
} else if ($plan['limit_type'] == "Data_Limit") {
if ($plan['data_unit'] == 'GB')
$datalimit = $plan['data_limit'] . "000000000";
else
$datalimit = $plan['data_limit'] . "000000";
$client->sendSync(
$addRequest
->setArgument('name', $customer['username'])
->setArgument('profile', $plan['name_plan'])
->setArgument('password', $customer['password'])
->setArgument('comment', $customer['fullname'])
->setArgument('email', $customer['email'])
->setArgument('limit-bytes-total', $datalimit)
);
} else if ($plan['limit_type'] == "Both_Limit") {
if ($plan['time_unit'] == 'Hrs')
$timelimit = $plan['time_limit'] . ":00:00";
else
$timelimit = "00:" . $plan['time_limit'] . ":00";
if ($plan['data_unit'] == 'GB')
$datalimit = $plan['data_limit'] . "000000000";
else
$datalimit = $plan['data_limit'] . "000000";
$client->sendSync(
$addRequest
->setArgument('name', $customer['username'])
->setArgument('profile', $plan['name_plan'])
->setArgument('password', $customer['password'])
->setArgument('comment', $customer['fullname'])
->setArgument('email', $customer['email'])
->setArgument('limit-uptime', $timelimit)
->setArgument('limit-bytes-total', $datalimit)
);
}
} else {
$client->sendSync(
$addRequest
->setArgument('name', $customer['username'])
->setArgument('profile', $plan['name_plan'])
->setArgument('comment', $customer['fullname'])
->setArgument('email', $customer['email'])
->setArgument('password', $customer['password'])
);
}
}
public static function setHotspotUser($client, $user, $pass)
{
global $_app_stage;
if ($_app_stage == 'demo') {
return null;
}
$printRequest = new RouterOS\Request('/ip/hotspot/user/print');
$printRequest->setArgument('.proplist', '.id');
$printRequest->setQuery(RouterOS\Query::where('name', $user));
$id = $client->sendSync($printRequest)->getProperty('.id');
$setRequest = new RouterOS\Request('/ip/hotspot/user/set');
$setRequest->setArgument('numbers', $id);
$setRequest->setArgument('password', $pass);
$client->sendSync($setRequest);
}
public static function setHotspotUserPackage($client, $user, $plan)
{
global $_app_stage;
if ($_app_stage == 'demo') {
return null;
}
$printRequest = new RouterOS\Request('/ip/hotspot/user/print');
$printRequest->setArgument('.proplist', '.id');
$printRequest->setQuery(RouterOS\Query::where('name', $user));
$id = $client->sendSync($printRequest)->getProperty('.id');
$setRequest = new RouterOS\Request('/ip/hotspot/user/set');
$setRequest->setArgument('numbers', $id);
$setRequest->setArgument('profile', $plan);
$client->sendSync($setRequest);
}
public static function removeHotspotActiveUser($client, $username)
{
global $_app_stage;
if ($_app_stage == 'demo') {
return null;
}
$onlineRequest = new RouterOS\Request('/ip/hotspot/active/print');
$onlineRequest->setArgument('.proplist', '.id');
$onlineRequest->setQuery(RouterOS\Query::where('user', $username));
$id = $client->sendSync($onlineRequest)->getProperty('.id');
$removeRequest = new RouterOS\Request('/ip/hotspot/active/remove');
$removeRequest->setArgument('numbers', $id);
$client->sendSync($removeRequest);
}
public static 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);
}
public static function addPpoeUser($client, $plan, $customer)
{
global $_app_stage;
if ($_app_stage == 'demo') {
return null;
}
$addRequest = new RouterOS\Request('/ppp/secret/add');
if (!empty($customer['pppoe_password'])) {
$pass = $customer['pppoe_password'];
} else {
$pass = $customer['password'];
}
$client->sendSync(
$addRequest
->setArgument('name', $customer['username'])
->setArgument('service', 'pppoe')
->setArgument('profile', $plan['name_plan'])
->setArgument('comment', $customer['fullname'] . ' | ' . $customer['email'])
->setArgument('password', $pass)
);
}
public static function setPpoeUser($client, $user, $pass)
{
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('password', $pass);
$client->sendSync($setRequest);
}
public static 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);
}
public static 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);
}
public static function removePool($client, $name)
{
global $_app_stage;
if ($_app_stage == 'demo') {
return null;
}
$printRequest = new RouterOS\Request(
'/ip pool print .proplist=.id',
RouterOS\Query::where('name', $name)
);
$poolID = $client->sendSync($printRequest)->getProperty('.id');
$removeRequest = new RouterOS\Request('/ip/pool/remove');
$client->sendSync(
$removeRequest
->setArgument('numbers', $poolID)
);
}
public static function addPool($client, $name, $ip_address)
{
global $_app_stage;
if ($_app_stage == 'demo') {
return null;
}
$addRequest = new RouterOS\Request('/ip/pool/add');
$client->sendSync(
$addRequest
->setArgument('name', $name)
->setArgument('ranges', $ip_address)
);
}
public static function setPool($client, $name, $ip_address)
{
global $_app_stage;
if ($_app_stage == 'demo') {
return null;
}
$printRequest = new RouterOS\Request(
'/ip pool print .proplist=.id',
RouterOS\Query::where('name', $name)
);
$poolID = $client->sendSync($printRequest)->getProperty('.id');
if (empty($poolID)) {
self::addPool($client, $name, $ip_address);
} else {
$setRequest = new RouterOS\Request('/ip/pool/set');
$client->sendSync(
$setRequest
->setArgument('numbers', $poolID)
->setArgument('ranges', $ip_address)
);
}
}
public static function addPpoePlan($client, $name, $pool, $rate)
{
global $_app_stage;
if ($_app_stage == 'demo') {
return null;
}
$addRequest = new RouterOS\Request('/ppp/profile/add');
$client->sendSync(
$addRequest
->setArgument('name', $name)
->setArgument('local-address', $pool)
->setArgument('remote-address', $pool)
->setArgument('rate-limit', $rate)
);
}
public static function setPpoePlan($client, $name, $pool, $rate)
{
global $_app_stage;
if ($_app_stage == 'demo') {
return null;
}
$printRequest = new RouterOS\Request(
'/ppp profile print .proplist=.id',
RouterOS\Query::where('name', $name)
);
$profileID = $client->sendSync($printRequest)->getProperty('.id');
if (empty($profileID)) {
self::addPpoePlan($client, $name, $pool, $rate);
} else {
$setRequest = new RouterOS\Request('/ppp/profile/set');
$client->sendSync(
$setRequest
->setArgument('numbers', $profileID)
->setArgument('local-address', $pool)
->setArgument('remote-address', $pool)
->setArgument('rate-limit', $rate)
);
}
}
public static function removePpoePlan($client, $name)
{
global $_app_stage;
if ($_app_stage == 'demo') {
return null;
}
$printRequest = new RouterOS\Request(
'/ppp profile print .proplist=.id',
RouterOS\Query::where('name', $name)
);
$profileID = $client->sendSync($printRequest)->getProperty('.id');
$removeRequest = new RouterOS\Request('/ppp/profile/remove');
$client->sendSync(
$removeRequest
->setArgument('numbers', $profileID)
);
}
public static function sendSMS($client, $to, $message)
{
global $_app_stage;
if ($_app_stage == 'demo') {
return null;
}
$smsRequest = new RouterOS\Request('/tool sms send');
$smsRequest
->setArgument('phone-number', $to)
->setArgument('message', $message);
$client->sendSync($smsRequest);
}
public static function getIpHotspotUser($client, $username){
global $_app_stage;
if ($_app_stage == 'demo') {
return null;
}
$printRequest = new RouterOS\Request(
'/ip hotspot active print',
RouterOS\Query::where('user', $username)
);
return $client->sendSync($printRequest)->getProperty('address');
}
public static function addIpToAddressList($client, $ip, $listName, $comment = '')
{
global $_app_stage;
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)
);
}
public static 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)
);
}
}

View File

@ -1,22 +1,87 @@
<?php
/**
* Standard Autoloader for PEAR2
*
* PEAR2_Autoload is the standard method of class loading for development and
* low-volume web sites using PEAR2 packages.
*
* PHP version 5
*
* @category PEAR2
* @package PEAR2_Autoload
* @author Gregory Beaver <cellog@php.net>
* @author Brett Bieber <saltybeagle@php.net>
* @license http://www.opensource.org/licenses/bsd-license.php New BSD License
* @version 0.3.0
* @link http://pear2.php.net/PEAR2_Autoload
*/
namespace PEAR2;
if (!class_exists('\PEAR2\Autoload', false)) {
/**
* Standard Autoloader for PEAR2
*
* PEAR2_Autoload is the standard method of class loading for development
* and low-volume web sites using PEAR2 packages.
*
* PHP version 5
*
* @category PEAR2
* @package PEAR2_Autoload
* @author Gregory Beaver <cellog@php.net>
* @author Brett Bieber <saltybeagle@php.net>
* @license http://www.opensource.org/licenses/bsd-license.php BSD
* New BSDLicense
* @link http://pear2.php.net/PEAR2_Autoload
*/
class Autoload
{
/**
* Used at {@link initialize()} to specify that the load function, path
* and map should be appended to the respective lists.
*/
const APPEND = 0;
/**
* Used at {@link initialize()} to specify that the load function should
* be prepended on the autoload stack, instead of being appended.
*/
const PREPEND_LOAD = 1;
/**
* Used at {@link initialize()} to specify that the path should be
* prepended on the list of paths, instead of being appended.
*/
const PREPEND_PATH = 2;
/**
* Used at {@link initialize()} to specify that the map should be
* prepended on the list of maps, instead of being appended.
*/
const PREPEND_MAP = 4;
/**
* Used at {@link initialize()} to specify that the load function, path
* and map should be prepended on their respective lists, instead of
* being appended.
*/
const PREPEND = 7;
/**
* Whether the autoload class has been spl_autoload_register-ed
*
*
* @var bool
*/
protected static $registered = false;
/**
* Array of PEAR2 autoload paths registered
*
*
* @var array
*/
protected static $paths = array();
/**
* Array of classname-to-file mapping
*
@ -45,86 +110,124 @@ if (!class_exists('\PEAR2\Autoload', false)) {
*/
protected static $unmapped = array();
/**
* Array of functions to be checked in exception traces.
*
* @var array
*/
protected static $checkFunctions = array(
'class_exists', 'interface_exists'
);
/**
* Initialize the PEAR2 autoloader
*
* @param string $path Directory path to register
*
*
* @param string $path Directory path(s) to register.
* @param string $mapfile Path to a mapping file to register.
* @param int $flags A bitmaks with options for the autoloader.
* See the PREPEND(_*) constants for details.
*
* @return void
*/
static function initialize($path, $mapfile = null)
{
self::register();
self::addPath($path);
self::addMap($mapfile);
public static function initialize(
$path,
$mapfile = null,
$flags = self::APPEND
) {
self::register(0 !== $flags & self::PREPEND_LOAD);
self::addPath($path, 0 !== ($flags & self::PREPEND_PATH));
self::addMap($mapfile, 0 !== ($flags & self::PREPEND_MAP));
}
/**
* Register the PEAR2 autoload class with spl_autoload_register
*
*
* @param bool $prepend Whether to prepend the load function to the
* autoload stack instead of appending it.
*
* @return void
*/
protected static function register()
protected static function register($prepend = false)
{
if (!self::$registered) {
// set up __autoload
$autoload = spl_autoload_functions();
spl_autoload_register('PEAR2\Autoload::load');
spl_autoload_register('PEAR2\Autoload::load', true, $prepend);
if (function_exists('__autoload') && ($autoload === false)) {
// __autoload() was being used, but now would be ignored, add
// it to the autoload stack
// __autoload() was being used, but now would be ignored,
// add it to the autoload stack
spl_autoload_register('__autoload');
}
if (function_exists('trait_exists')) {
self::$checkFunctions[] = 'trait_exists';
}
self::$registered = true;
}
self::$registered = true;
}
/**
* Add a path
*
* @param string $path The directory to add to the set of PEAR2 paths
*
*
* @param string $paths The folder(s) to add to the set of paths.
* @param bool $prepend Whether to prepend the path to the list of
* paths instead of appending it.
*
* @return void
*/
protected static function addPath($path)
protected static function addPath($paths, $prepend = false)
{
if (!in_array($path, self::$paths)) {
self::$paths[] = $path;
foreach (explode(PATH_SEPARATOR, $paths) as $path) {
if (!in_array($path, self::$paths)) {
if ($prepend) {
self::$paths = array_merge(array($path), self::$paths);
} else {
self::$paths[] = $path;
}
}
}
}
/**
* Add a classname-to-file map
*
* @param string $mapfile The filename of the classmap
* @param string $mapfile The filename of the classmap.
* @param bool $prepend Whether to prepend the map to the list of maps
* instead of appending it.
*
* @return void
*/
protected static function addMap($mapfile)
protected static function addMap($mapfile, $prepend = false)
{
if (! in_array($mapfile, self::$maps)) {
if (!in_array($mapfile, self::$maps)) {
// keep track of specific map file loaded in this
// instance so we can update it if necessary
// instance so we can update it if necessary
self::$mapfile = $mapfile;
if (file_exists($mapfile)) {
if (is_file($mapfile)) {
$map = include $mapfile;
if (is_array($map)) {
// mapfile contains a valid map, so we'll keep it
self::$maps[] = $mapfile;
self::$map = array_merge(self::$map, $map);
if ($prepend) {
self::$maps = array_merge(
array($mapfile),
self::$maps
);
self::$map = array_merge($map, self::$map);
} else {
self::$maps[] = $mapfile;
self::$map = array_merge(self::$map, $map);
}
}
}
}
}
/**
* Check if the class is already defined in a classmap
*
*
* @param string $class The class to look for
*
*
* @return bool
*/
protected static function isMapped($class)
@ -141,18 +244,18 @@ if (!class_exists('\PEAR2\Autoload', false)) {
/**
* Load a PEAR2 class
*
*
* @param string $class The class to load
*
*
* @return bool
*/
static function load($class)
public static function load($class)
{
// need to check if there's a current map file specified ALSO.
// this could be the first time writing it.
$mapped = self::isMapped($class);
if ($mapped) {
require self::$map[$class];
if ($mapped && is_file(self::$map[$class])) {
include self::$map[$class];
if (!self::loadSuccessful($class)) {
// record this failure & keep going, we may still find it
self::$unmapped[] = $class;
@ -161,34 +264,59 @@ if (!class_exists('\PEAR2\Autoload', false)) {
}
}
$file = str_replace(array('_', '\\'), DIRECTORY_SEPARATOR, $class) . '.php';
$file = '';
$className = $class;
if (false !== $lastNsPos = strrpos($class, '\\')) {
$namespace = substr($class, 0, $lastNsPos);
$className = substr($class, $lastNsPos + 1);
$file = str_replace(
'\\',
DIRECTORY_SEPARATOR,
$namespace
) . DIRECTORY_SEPARATOR;
}
$file .= str_replace('_', DIRECTORY_SEPARATOR, $className) . '.php';
foreach (self::$paths as $path) {
if (file_exists($path . DIRECTORY_SEPARATOR . $file)) {
require $path . DIRECTORY_SEPARATOR . $file;
if (is_file($path . DIRECTORY_SEPARATOR . $file)) {
include $path . DIRECTORY_SEPARATOR . $file;
if (!self::loadSuccessful($class)) {
throw new \Exception('Class ' . $class . ' was not present in ' .
if (count(spl_autoload_functions()) > 1) {
return false;
}
throw new \Exception(
'Class ' . $class . ' was not present in ' .
$path . DIRECTORY_SEPARATOR . $file .
'") [PEAR2_Autoload-0.2.4]');
'") [PEAR2_Autoload-@PACKAGE_VERSION@]'
);
}
if (in_array($class, self::$unmapped)) {
self::updateMap($class, $path . DIRECTORY_SEPARATOR . $file);
self::updateMap(
$class,
$path . DIRECTORY_SEPARATOR . $file
);
}
return true;
}
}
$e = new \Exception('Class ' . $class . ' could not be loaded from ' .
$file . ', file does not exist (registered paths="' .
implode(PATH_SEPARATOR, self::$paths) .
'") [PEAR2_Autoload-0.2.4]');
$trace = $e->getTrace();
if (isset($trace[2]) && isset($trace[2]['function']) &&
in_array($trace[2]['function'], array('class_exists', 'interface_exists'))) {
if (count(spl_autoload_functions()) > 1) {
return false;
}
if (isset($trace[1]) && isset($trace[1]['function']) &&
in_array($trace[1]['function'], array('class_exists', 'interface_exists'))) {
$e = new \Exception(
'Class ' . $class . ' could not be loaded from ' .
$file . ', file does not exist (registered paths="' .
implode(PATH_SEPARATOR, self::$paths) .
'") [PEAR2_Autoload-@PACKAGE_VERSION@]'
);
$trace = $e->getTrace();
if (isset($trace[2]) && isset($trace[2]['function'])
&& in_array($trace[2]['function'], self::$checkFunctions)
) {
return false;
}
if (isset($trace[1]) && isset($trace[1]['function'])
&& in_array($trace[1]['function'], self::$checkFunctions)
) {
return false;
}
throw $e;
@ -196,31 +324,36 @@ if (!class_exists('\PEAR2\Autoload', false)) {
/**
* Check if the requested class was loaded from the specified path
*
*
* @param string $class The name of the class to check.
*
* @return bool
*/
protected static function loadSuccessful($class)
{
if (!class_exists($class, false) && !interface_exists($class, false)) {
return false;
}
return true;
return class_exists($class, false)
|| interface_exists($class, false)
|| (in_array('trait_exists', self::$checkFunctions, true)
&& trait_exists($class, false));
}
/**
* If possible, update the classmap file with newly-discovered
* If possible, update the classmap file with newly-discovered
* mapping.
*
* @param string $class Class name discovered
*
*
* @param string $class Class name discovered
* @param string $origin File where class was found
*
*
* @return void
*/
protected static function updateMap($class, $origin)
{
if (is_writable(self::$mapfile) || is_writable(dirname(self::$mapfile))) {
if (is_writable(self::$mapfile)
|| is_writable(dirname(self::$mapfile))
) {
self::$map[$class] = $origin;
file_put_contents(self::$mapfile,
file_put_contents(
self::$mapfile,
'<'."?php\n"
. "// PEAR2\Autoload auto-generated classmap\n"
. "return " . var_export(self::$map, true) . ';',
@ -228,16 +361,16 @@ if (!class_exists('\PEAR2\Autoload', false)) {
);
}
}
/**
* return the array of paths PEAR2 autoload has registered
*
* Return the array of paths PEAR2 autoload has registered
*
* @return array
*/
static function getPaths()
public static function getPaths()
{
return self::$paths;
}
}
}
Autoload::initialize(dirname(__DIR__));
Autoload::initialize(dirname(__DIR__));

View File

@ -1,18 +1,19 @@
<?php
/**
* ~~summary~~
*
* ~~description~~
*
* Wrapper for shared memory and locking functionality across different extensions.
*
* Allows you to share data across requests as long as the PHP process is running. One of APC or WinCache is required to accomplish this, with other extensions being potentially pluggable as adapters.
*
* PHP version 5
*
*
* @category Caching
* @package PEAR2_Cache_SHM
* @author Vasil Rangelov <boen.robot@gmail.com>
* @copyright 2011 Vasil Rangelov
* @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
* @version 0.1.3
* @version 0.2.0
* @link http://pear2.php.net/PEAR2_Cache_SHM
*/
@ -38,9 +39,9 @@ use PEAR2\Cache\SHM\InvalidArgumentException;
/**
* Main class for this package.
*
*
* Automatically chooses an adapter based on the available extensions.
*
*
* @category Caching
* @package PEAR2_Cache_SHM
* @author Vasil Rangelov <boen.robot@gmail.com>
@ -50,18 +51,20 @@ use PEAR2\Cache\SHM\InvalidArgumentException;
abstract class SHM implements IteratorAggregate
{
/**
* @var array An array of adapter names that meet their requirements.
* An array of adapter names that meet their requirements.
*
* @var array
*/
private static $_adapters = array();
/**
* Creates a new shared memory storage.
*
* Estabilishes a separate persistent storage. Adapter is automatically
*
* Establishes a separate persistent storage. Adapter is automatically
* chosen based on the available extensions.
*
*
* @param string $persistentId The ID for the storage.
*
*
* @return static|SHM A new instance of an SHM adapter (child of this
* class).
*/
@ -79,28 +82,28 @@ abstract class SHM implements IteratorAggregate
1
);
}
/**
* Checks if the adapter meets its requirements.
*
*
* @return bool TRUE on success, FALSE on failure.
*/
public static function isMeetingRequirements()
{
return true;
}
/**
* Registers an adapter.
*
*
* Registers an SHM adapter, allowing you to call it with {@link factory()}.
*
*
* @param string $adapter FQCN of adapter. A valid adapter is one that
* extends this class. The class will be autoloaded if not already
* present.
* @param bool $prepend Whether to prepend this adapter into the list of
* possible adapters, instead of appending to it.
*
*
* @return bool TRUE on success, FALSE on failure.
*/
final public static function registerAdapter($adapter, $prepend = false)
@ -121,244 +124,244 @@ abstract class SHM implements IteratorAggregate
}
return false;
}
/**
* Adds a value to the shared memory storage.
*
*
* Adds a value to the storage if it doesn't exist, or fails if it does.
*
*
* @param string $key Name of key to associate the value with.
* @param mixed $value Value for the specified key.
* @param int $ttl Seconds to store the value. If set to 0 indicates no
* time limit.
*
*
* @return bool TRUE on success, FALSE on failure.
*/
public function __invoke($key, $value, $ttl = 0)
{
return $this->add($key, $value, $ttl);
}
/**
* Gets a value from the shared memory storage.
*
*
* This is a magic method, thanks to which any property you attempt to get
* the value of will be fetched from the adapter, treating the property name
* as the key of the value to get.
*
*
* @param string $key Name of key to get.
*
*
* @return mixed The current value of the specified key.
*/
public function __get($key)
{
return $this->get($key);
}
/**
* Sets a value in the shared memory storage.
*
*
* This is a magic method, thanks to which any property you attempt to set
* the value of will be set by the adapter, treating the property name as
* the key of the value to set. The value is set without a TTL.
*
*
* @param string $key Name of key to associate the value with.
* @param mixed $value Value for the specified key.
*
*
* @return bool TRUE on success, FALSE on failure.
*/
public function __set($key, $value)
{
return $this->set($key, $value);
}
/**
* Checks if a specified key is in the storage.
*
*
* This is a magic method, thanks to which any property you call isset() on
* will be checked by the adapter, treating the property name as the key
* of the value to check.
*
*
* @param string $key Name of key to check.
*
* @return bool TRUE if the key is in the storage, FALSE otherwise.
*
* @return bool TRUE if the key is in the storage, FALSE otherwise.
*/
public function __isset($key)
{
return $this->exists($key);
}
/**
* Deletes a value from the shared memory storage.
*
*
* This is a magic method, thanks to which any property you attempt to unset
* the value of will be unset by the adapter, treating the property name as
* the key of the value to delete.
*
*
* @param string $key Name of key to delete.
*
*
* @return bool TRUE on success, FALSE on failure.
*/
public function __unset($key)
{
return $this->delete($key);
}
/**
* Creates a new shared memory storage.
*
* Estabilishes a separate persistent storage.
*
*
* Establishes a separate persistent storage.
*
* @param string $persistentId The ID for the storage. The storage will be
* reused if it exists, or created if it doesn't exist. Data and locks
* are namespaced by this ID.
*/
abstract public function __construct($persistentId);
/**
* Obtains a named lock.
*
*
* @param string $key Name of the key to obtain. Note that $key may
* repeat for each distinct $persistentId.
* @param double $timeout If the lock can't be immediatly obtained, the
* @param double $timeout If the lock can't be immediately obtained, the
* script will block for at most the specified amount of seconds.
* Setting this to 0 makes lock obtaining non blocking, and setting it
* to NULL makes it block without a time limit.
*
*
* @return bool TRUE on success, FALSE on failure.
*/
abstract public function lock($key, $timeout = null);
/**
* Releases a named lock.
*
*
* @param string $key Name of the key to release. Note that $key may
* repeat for each distinct $persistentId.
*
*
* @return bool TRUE on success, FALSE on failure.
*/
abstract public function unlock($key);
/**
* Checks if a specified key is in the storage.
*
*
* @param string $key Name of key to check.
*
* @return bool TRUE if the key is in the storage, FALSE otherwise.
*
* @return bool TRUE if the key is in the storage, FALSE otherwise.
*/
abstract public function exists($key);
/**
* Adds a value to the shared memory storage.
*
*
* Adds a value to the storage if it doesn't exist, or fails if it does.
*
*
* @param string $key Name of key to associate the value with.
* @param mixed $value Value for the specified key.
* @param int $ttl Seconds to store the value. If set to 0 indicates no
* time limit.
*
*
* @return bool TRUE on success, FALSE on failure.
*/
abstract public function add($key, $value, $ttl = 0);
/**
* Sets a value in the shared memory storage.
*
*
* Adds a value to the storage if it doesn't exist, overwrites it otherwise.
*
*
* @param string $key Name of key to associate the value with.
* @param mixed $value Value for the specified key.
* @param int $ttl Seconds to store the value. If set to 0 indicates no
* time limit.
*
*
* @return bool TRUE on success, FALSE on failure.
*/
abstract public function set($key, $value, $ttl = 0);
/**
* Gets a value from the shared memory storage.
*
*
* Gets the current value, or throws an exception if it's not stored.
*
*
* @param string $key Name of key to get the value of.
*
*
* @return mixed The current value of the specified key.
*/
abstract public function get($key);
/**
* Deletes a value from the shared memory storage.
*
*
* @param string $key Name of key to delete.
*
*
* @return bool TRUE on success, FALSE on failure.
*/
abstract public function delete($key);
/**
* Increases a value from the shared memory storage.
*
*
* Increases a value from the shared memory storage. Unlike a plain
* set($key, get($key)+$step) combination, this function also implicitly
* performs locking.
*
*
* @param string $key Name of key to increase.
* @param int $step Value to increase the key by.
*
*
* @return int The new value.
*/
abstract public function inc($key, $step = 1);
/**
* Decreases a value from the shared memory storage.
*
*
* Decreases a value from the shared memory storage. Unlike a plain
* set($key, get($key)-$step) combination, this function also implicitly
* performs locking.
*
*
* @param string $key Name of key to decrease.
* @param int $step Value to decrease the key by.
*
*
* @return int The new value.
*/
abstract public function dec($key, $step = 1);
/**
* Sets a new value if a key has a certain value.
*
*
* Sets a new value if a key has a certain value. This function only works
* when $old and $new are longs.
*
*
* @param string $key Key of the value to compare and set.
* @param int $old The value to compare the key against.
* @param int $new The value to set the key to.
*
* @return bool TRUE on success, FALSE on failure.
*
* @return bool TRUE on success, FALSE on failure.
*/
abstract public function cas($key, $old, $new);
/**
* Clears the persistent storage.
*
*
* Clears the persistent storage, i.e. removes all keys. Locks are left
* intact.
*
*
* @return void
*/
abstract public function clear();
/**
* Retrieve an external iterator
*
*
* Returns an external iterator.
*
*
* @param string|null $filter A PCRE regular expression.
* Only matching keys will be iterated over.
* Setting this to NULL matches all keys of this instance.
* @param bool $keysOnly Whether to return only the keys,
* or return both the keys and values.
*
*
* @return \Traversable An array with all matching keys as array keys,
* and values as array values. If $keysOnly is TRUE, the array keys are
* numeric, and the array values are key names.
@ -368,4 +371,5 @@ abstract class SHM implements IteratorAggregate
SHM::registerAdapter('\\' . __NAMESPACE__ . '\SHM\Adapter\Placebo');
SHM::registerAdapter('\\' . __NAMESPACE__ . '\SHM\Adapter\Wincache');
SHM::registerAdapter('\\' . __NAMESPACE__ . '\SHM\Adapter\APCu');
SHM::registerAdapter('\\' . __NAMESPACE__ . '\SHM\Adapter\APC');

View File

@ -1,18 +1,19 @@
<?php
/**
* ~~summary~~
*
* ~~description~~
*
* Wrapper for shared memory and locking functionality across different extensions.
*
* Allows you to share data across requests as long as the PHP process is running. One of APC or WinCache is required to accomplish this, with other extensions being potentially pluggable as adapters.
*
* PHP version 5
*
*
* @category Caching
* @package PEAR2_Cache_SHM
* @author Vasil Rangelov <boen.robot@gmail.com>
* @copyright 2011 Vasil Rangelov
* @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
* @version 0.1.3
* @version 0.2.0
* @link http://pear2.php.net/PEAR2_Cache_SHM
*/
/**
@ -32,7 +33,7 @@ use ArrayObject;
/**
* Shared memory adapter for the APC extension.
*
*
* @category Caching
* @package PEAR2_Cache_SHM
* @author Vasil Rangelov <boen.robot@gmail.com>
@ -42,32 +43,39 @@ use ArrayObject;
class APC extends SHM
{
/**
* @var string ID of the current storage.
* ID of the current storage.
*
* @var string
*/
protected $persistentId;
/**
* List of persistent IDs.
*
*
* A list of persistent IDs within the current request (as keys) with an int
* (as a value) specifying the number of instances in the current request.
* Used as an attempt to ensure implicit lock releases even on errors in the
* critical sections, since APC doesn't have an actual locking function.
* @var array
*
* @var array
*/
protected static $requestInstances = array();
/**
* @var array Array of lock names (as values) for each persistent ID (as
* key) obtained during the current request.
* Array of lock names for each persistent ID.
*
* Array of lock names (as values) for each persistent ID (as key) obtained
* during the current request.
*
* @var array
*/
protected static $locksBackup = array();
/**
* Creates a new shared memory storage.
*
* Estabilishes a separate persistent storage.
*
*
* Establishes a separate persistent storage.
*
* @param string $persistentId The ID for the storage. The storage will be
* reused if it exists, or created if it doesn't exist. Data and locks
* are namespaced by this ID.
@ -87,35 +95,36 @@ class APC extends SHM
true
);
}
/**
* Checks if the adapter meets its requirements.
*
*
* @return bool TRUE on success, FALSE on failure.
*/
public static function isMeetingRequirements()
{
return extension_loaded('apc')
&& version_compare(phpversion('apc'), '3.0.13', '>=')
&& version_compare(phpversion('apc'), '3.1.1', '>=')
&& ini_get('apc.enabled')
&& ('cli' !== PHP_SAPI || ini_get('apc.enable_cli'));
}
/**
* Releases all locks in a storage.
*
*
* This function is not meant to be used directly. It is implicitly called
* by the the destructor and as a shutdown function when the request ends.
* One of these calls ends up releasing any unreleased locks obtained
* during the request. A lock is also implicitly released as soon as there
* are no objects left in the current request using the same persistent ID.
*
*
* @param string $internalPersistentId The internal persistent ID, the locks
* of which are being released.
* @param bool $isAtShutdown Whether the function was executed at
* shutdown.
*
*
* @return void
*
* @internal
*/
public static function releaseLocks($internalPersistentId, $isAtShutdown)
@ -127,7 +136,7 @@ class APC extends SHM
}
}
}
/**
* Releases any locks obtained by this instance as soon as there are no more
* references to the object's persistent ID.
@ -137,18 +146,18 @@ class APC extends SHM
static::$requestInstances[$this->persistentId]--;
static::releaseLocks($this->persistentId, false);
}
/**
* Obtains a named lock.
*
*
* @param string $key Name of the key to obtain. Note that $key may
* repeat for each distinct $persistentId.
* @param double $timeout If the lock can't be immediatly obtained, the
* @param double $timeout If the lock can't be immediately obtained, the
* script will block for at most the specified amount of seconds.
* Setting this to 0 makes lock obtaining non blocking, and setting it
* to NULL makes it block without a time limit.
*
*
* @return bool TRUE on success, FALSE on failure.
*/
public function lock($key, $timeout = null)
@ -164,13 +173,13 @@ class APC extends SHM
static::$locksBackup[$this->persistentId] = $key;
return true;
}
/**
* Releases a named lock.
*
*
* @param string $key Name of the key to release. Note that $key may
* repeat for each distinct $persistentId.
*
*
* @return bool TRUE on success, FALSE on failure.
*/
public function unlock($key)
@ -178,69 +187,71 @@ class APC extends SHM
$lock = $this->persistentId . 'l ' . $key;
$success = apc_delete($lock);
if ($success) {
unset(static::$locksBackup[$this->persistentId][array_search(
$key,
static::$locksBackup[$this->persistentId],
true
)]);
unset(
static::$locksBackup[$this->persistentId][array_search(
$key,
static::$locksBackup[$this->persistentId],
true
)]
);
return true;
}
return false;
}
/**
* Checks if a specified key is in the storage.
*
*
* @param string $key Name of key to check.
*
* @return bool TRUE if the key is in the storage, FALSE otherwise.
*
* @return bool TRUE if the key is in the storage, FALSE otherwise.
*/
public function exists($key)
{
return apc_exists($this->persistentId . 'd ' . $key);
}
/**
* Adds a value to the shared memory storage.
*
*
* Adds a value to the storage if it doesn't exist, or fails if it does.
*
*
* @param string $key Name of key to associate the value with.
* @param mixed $value Value for the specified key.
* @param int $ttl Seconds to store the value. If set to 0 indicates no
* time limit.
*
*
* @return bool TRUE on success, FALSE on failure.
*/
public function add($key, $value, $ttl = 0)
{
return apc_add($this->persistentId . 'd ' . $key, $value, $ttl);
}
/**
* Sets a value in the shared memory storage.
*
*
* Adds a value to the storage if it doesn't exist, overwrites it otherwise.
*
*
* @param string $key Name of key to associate the value with.
* @param mixed $value Value for the specified key.
* @param int $ttl Seconds to store the value. If set to 0 indicates no
* time limit.
*
*
* @return bool TRUE on success, FALSE on failure.
*/
public function set($key, $value, $ttl = 0)
{
return apc_store($this->persistentId . 'd ' . $key, $value, $ttl);
}
/**
* Gets a value from the shared memory storage.
*
*
* Gets the current value, or throws an exception if it's not stored.
*
*
* @param string $key Name of key to get the value of.
*
*
* @return mixed The current value of the specified key.
*/
public function get($key)
@ -260,29 +271,29 @@ class APC extends SHM
}
throw new SHM\InvalidArgumentException('No such key in cache', 101);
}
/**
* Deletes a value from the shared memory storage.
*
*
* @param string $key Name of key to delete.
*
*
* @return bool TRUE on success, FALSE on failure.
*/
public function delete($key)
{
return apc_delete($this->persistentId . 'd ' . $key);
}
/**
* Increases a value from the shared memory storage.
*
*
* Increases a value from the shared memory storage. Unlike a plain
* set($key, get($key)+$step) combination, this function also implicitly
* performs locking.
*
*
* @param string $key Name of key to increase.
* @param int $step Value to increase the key by.
*
*
* @return int The new value.
*/
public function inc($key, $step = 1)
@ -300,17 +311,17 @@ class APC extends SHM
}
return $newValue;
}
/**
* Decreases a value from the shared memory storage.
*
*
* Decreases a value from the shared memory storage. Unlike a plain
* set($key, get($key)-$step) combination, this function also implicitly
* performs locking.
*
*
* @param string $key Name of key to decrease.
* @param int $step Value to decrease the key by.
*
*
* @return int The new value.
*/
public function dec($key, $step = 1)
@ -331,27 +342,27 @@ class APC extends SHM
/**
* Sets a new value if a key has a certain value.
*
*
* Sets a new value if a key has a certain value. This function only works
* when $old and $new are longs.
*
*
* @param string $key Key of the value to compare and set.
* @param int $old The value to compare the key against.
* @param int $new The value to set the key to.
*
* @return bool TRUE on success, FALSE on failure.
*
* @return bool TRUE on success, FALSE on failure.
*/
public function cas($key, $old, $new)
{
return apc_cas($this->persistentId . 'd ' . $key, $old, $new);
}
/**
* Clears the persistent storage.
*
*
* Clears the persistent storage, i.e. removes all keys. Locks are left
* intact.
*
*
* @return void
*/
public function clear()
@ -366,18 +377,18 @@ class APC extends SHM
apc_delete($key);
}
}
/**
* Retrieve an external iterator
*
*
* Returns an external iterator.
*
*
* @param string|null $filter A PCRE regular expression.
* Only matching keys will be iterated over.
* Setting this to NULL matches all keys of this instance.
* @param bool $keysOnly Whether to return only the keys,
* or return both the keys and values.
*
*
* @return ArrayObject An array with all matching keys as array keys,
* and values as array values. If $keysOnly is TRUE, the array keys are
* numeric, and the array values are key names.

View File

@ -0,0 +1,416 @@
<?php
/**
* Wrapper for shared memory and locking functionality across different extensions.
*
* Allows you to share data across requests as long as the PHP process is running. One of APC or WinCache is required to accomplish this, with other extensions being potentially pluggable as adapters.
*
* PHP version 5
*
* @category Caching
* @package PEAR2_Cache_SHM
* @author Vasil Rangelov <boen.robot@gmail.com>
* @copyright 2011 Vasil Rangelov
* @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
* @version 0.2.0
* @link http://pear2.php.net/PEAR2_Cache_SHM
*/
/**
* The namespace declaration.
*/
namespace PEAR2\Cache\SHM\Adapter;
/**
* Throws exceptions from this namespace, and extends from this class.
*/
use PEAR2\Cache\SHM;
/**
* {@link APC::getIterator()} returns this object.
*/
use ArrayObject;
/**
* Shared memory adapter for the APC extension.
*
* @category Caching
* @package PEAR2_Cache_SHM
* @author Vasil Rangelov <boen.robot@gmail.com>
* @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
* @link http://pear2.php.net/PEAR2_Cache_SHM
*/
class APCu extends SHM
{
/**
* ID of the current storage.
*
* @var string
*/
protected $persistentId;
/**
* List of persistent IDs.
*
* A list of persistent IDs within the current request (as keys) with an int
* (as a value) specifying the number of instances in the current request.
* Used as an attempt to ensure implicit lock releases even on errors in the
* critical sections, since APC doesn't have an actual locking function.
*
* @var array
*/
protected static $requestInstances = array();
/**
* Array of lock names for each persistent ID.
*
* Array of lock names (as values) for each persistent ID (as key) obtained
* during the current request.
*
* @var array
*/
protected static $locksBackup = array();
/**
* Creates a new shared memory storage.
*
* Establishes a separate persistent storage.
*
* @param string $persistentId The ID for the storage. The storage will be
* reused if it exists, or created if it doesn't exist. Data and locks
* are namespaced by this ID.
*/
public function __construct($persistentId)
{
$this->persistentId = __CLASS__ . ' ' . $persistentId;
if (isset(static::$requestInstances[$this->persistentId])) {
static::$requestInstances[$this->persistentId]++;
} else {
static::$requestInstances[$this->persistentId] = 1;
static::$locksBackup[$this->persistentId] = array();
}
register_shutdown_function(
get_called_class() . '::releaseLocks',
$this->persistentId,
true
);
}
/**
* Checks if the adapter meets its requirements.
*
* @return bool TRUE on success, FALSE on failure.
*/
public static function isMeetingRequirements()
{
return extension_loaded('apcu')
&& version_compare(phpversion('apcu'), '5.0.0', '>=')
&& ini_get('apc.enabled')
&& ('cli' !== PHP_SAPI || ini_get('apc.enable_cli'));
}
/**
* Releases all locks in a storage.
*
* This function is not meant to be used directly. It is implicitly called
* by the the destructor and as a shutdown function when the request ends.
* One of these calls ends up releasing any unreleased locks obtained
* during the request. A lock is also implicitly released as soon as there
* are no objects left in the current request using the same persistent ID.
*
* @param string $internalPersistentId The internal persistent ID, the locks
* of which are being released.
* @param bool $isAtShutdown Whether the function was executed at
* shutdown.
*
* @return void
*
* @internal
*/
public static function releaseLocks($internalPersistentId, $isAtShutdown)
{
$hasInstances = 0 !== static::$requestInstances[$internalPersistentId];
if ($isAtShutdown === $hasInstances) {
foreach (static::$locksBackup[$internalPersistentId] as $key) {
apcu_delete($internalPersistentId . 'l ' . $key);
}
}
}
/**
* Releases any locks obtained by this instance as soon as there are no more
* references to the object's persistent ID.
*/
public function __destruct()
{
static::$requestInstances[$this->persistentId]--;
static::releaseLocks($this->persistentId, false);
}
/**
* Obtains a named lock.
*
* @param string $key Name of the key to obtain. Note that $key may
* repeat for each distinct $persistentId.
* @param double $timeout If the lock can't be immediately obtained, the
* script will block for at most the specified amount of seconds.
* Setting this to 0 makes lock obtaining non blocking, and setting it
* to NULL makes it block without a time limit.
*
* @return bool TRUE on success, FALSE on failure.
*/
public function lock($key, $timeout = null)
{
$lock = $this->persistentId . 'l ' . $key;
$hasTimeout = $timeout !== null;
$start = microtime(true);
while (!apcu_add($lock, 1)) {
if ($hasTimeout && (microtime(true) - $start) > $timeout) {
return false;
}
}
static::$locksBackup[$this->persistentId] = $key;
return true;
}
/**
* Releases a named lock.
*
* @param string $key Name of the key to release. Note that $key may
* repeat for each distinct $persistentId.
*
* @return bool TRUE on success, FALSE on failure.
*/
public function unlock($key)
{
$lock = $this->persistentId . 'l ' . $key;
$success = apcu_delete($lock);
if ($success) {
unset(
static::$locksBackup[$this->persistentId][array_search(
$key,
static::$locksBackup[$this->persistentId],
true
)]
);
return true;
}
return false;
}
/**
* Checks if a specified key is in the storage.
*
* @param string $key Name of key to check.
*
* @return bool TRUE if the key is in the storage, FALSE otherwise.
*/
public function exists($key)
{
return apcu_exists($this->persistentId . 'd ' . $key);
}
/**
* Adds a value to the shared memory storage.
*
* Adds a value to the storage if it doesn't exist, or fails if it does.
*
* @param string $key Name of key to associate the value with.
* @param mixed $value Value for the specified key.
* @param int $ttl Seconds to store the value. If set to 0 indicates no
* time limit.
*
* @return bool TRUE on success, FALSE on failure.
*/
public function add($key, $value, $ttl = 0)
{
return apcu_add($this->persistentId . 'd ' . $key, $value, $ttl);
}
/**
* Sets a value in the shared memory storage.
*
* Adds a value to the storage if it doesn't exist, overwrites it otherwise.
*
* @param string $key Name of key to associate the value with.
* @param mixed $value Value for the specified key.
* @param int $ttl Seconds to store the value. If set to 0 indicates no
* time limit.
*
* @return bool TRUE on success, FALSE on failure.
*/
public function set($key, $value, $ttl = 0)
{
return apcu_store($this->persistentId . 'd ' . $key, $value, $ttl);
}
/**
* Gets a value from the shared memory storage.
*
* Gets the current value, or throws an exception if it's not stored.
*
* @param string $key Name of key to get the value of.
*
* @return mixed The current value of the specified key.
*/
public function get($key)
{
$fullKey = $this->persistentId . 'd ' . $key;
if (apcu_exists($fullKey)) {
$value = apcu_fetch($fullKey, $success);
if (!$success) {
throw new SHM\InvalidArgumentException(
'Unable to fetch key. ' .
'Key has either just now expired or (if no TTL was set) ' .
'is possibly in a race condition with another request.',
100
);
}
return $value;
}
throw new SHM\InvalidArgumentException('No such key in cache', 101);
}
/**
* Deletes a value from the shared memory storage.
*
* @param string $key Name of key to delete.
*
* @return bool TRUE on success, FALSE on failure.
*/
public function delete($key)
{
return apcu_delete($this->persistentId . 'd ' . $key);
}
/**
* Increases a value from the shared memory storage.
*
* Increases a value from the shared memory storage. Unlike a plain
* set($key, get($key)+$step) combination, this function also implicitly
* performs locking.
*
* @param string $key Name of key to increase.
* @param int $step Value to increase the key by.
*
* @return int The new value.
*/
public function inc($key, $step = 1)
{
$newValue = apcu_inc(
$this->persistentId . 'd ' . $key,
(int) $step,
$success
);
if (!$success) {
throw new SHM\InvalidArgumentException(
'Unable to increase the value. Are you sure the value is int?',
102
);
}
return $newValue;
}
/**
* Decreases a value from the shared memory storage.
*
* Decreases a value from the shared memory storage. Unlike a plain
* set($key, get($key)-$step) combination, this function also implicitly
* performs locking.
*
* @param string $key Name of key to decrease.
* @param int $step Value to decrease the key by.
*
* @return int The new value.
*/
public function dec($key, $step = 1)
{
$newValue = apcu_dec(
$this->persistentId . 'd ' . $key,
(int) $step,
$success
);
if (!$success) {
throw new SHM\InvalidArgumentException(
'Unable to decrease the value. Are you sure the value is int?',
103
);
}
return $newValue;
}
/**
* Sets a new value if a key has a certain value.
*
* Sets a new value if a key has a certain value. This function only works
* when $old and $new are longs.
*
* @param string $key Key of the value to compare and set.
* @param int $old The value to compare the key against.
* @param int $new The value to set the key to.
*
* @return bool TRUE on success, FALSE on failure.
*/
public function cas($key, $old, $new)
{
return apcu_cas($this->persistentId . 'd ' . $key, $old, $new);
}
/**
* Clears the persistent storage.
*
* Clears the persistent storage, i.e. removes all keys. Locks are left
* intact.
*
* @return void
*/
public function clear()
{
foreach (new APCIterator(
'user',
'/^' . preg_quote($this->persistentId, '/') . 'd /',
APC_ITER_KEY,
100,
APC_LIST_ACTIVE
) as $key) {
apcu_delete($key);
}
}
/**
* Retrieve an external iterator
*
* Returns an external iterator.
*
* @param string|null $filter A PCRE regular expression.
* Only matching keys will be iterated over.
* Setting this to NULL matches all keys of this instance.
* @param bool $keysOnly Whether to return only the keys,
* or return both the keys and values.
*
* @return ArrayObject An array with all matching keys as array keys,
* and values as array values. If $keysOnly is TRUE, the array keys are
* numeric, and the array values are key names.
*/
public function getIterator($filter = null, $keysOnly = false)
{
$result = array();
foreach (new APCUIterator(
'/^' . preg_quote($this->persistentId, '/') . 'd /',
APC_ITER_KEY,
100,
APC_LIST_ACTIVE
) as $key) {
$localKey = strstr($key, $this->persistentId . 'd ');
if (null === $filter || preg_match($filter, $localKey)) {
if ($keysOnly) {
$result[] = $localKey;
} else {
$result[$localKey] = apcu_fetch($key);
}
}
}
return new ArrayObject($result);
}
}

View File

@ -1,18 +1,19 @@
<?php
/**
* ~~summary~~
*
* ~~description~~
*
* Wrapper for shared memory and locking functionality across different extensions.
*
* Allows you to share data across requests as long as the PHP process is running. One of APC or WinCache is required to accomplish this, with other extensions being potentially pluggable as adapters.
*
* PHP version 5
*
*
* @category Caching
* @package PEAR2_Cache_SHM
* @author Vasil Rangelov <boen.robot@gmail.com>
* @copyright 2011 Vasil Rangelov
* @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
* @version 0.1.3
* @version 0.2.0
* @link http://pear2.php.net/PEAR2_Cache_SHM
*/
/**
@ -31,10 +32,10 @@ use PEAR2\Cache\SHM;
use ArrayObject;
/**
* This adapter is not truly persistent. It is intended to emulate persistency
* This adapter is not truly persistent. It is intended to emulate persistence
* in non persistent environments, so that upper level applications can use a
* single code path for persistent and non persistent code.
*
*
* @category Caching
* @package PEAR2_Cache_SHM
* @author Vasil Rangelov <boen.robot@gmail.com>
@ -44,42 +45,50 @@ use ArrayObject;
class Placebo extends SHM
{
/**
* @var string ID of the current storage.
* ID of the current storage.
*
* @var string
*/
protected $persistentId;
/**
* List of persistent IDs.
*
*
* A list of persistent IDs within the current request (as keys) with an int
* (as a value) specifying the number of instances in the current request.
* Used as an attempt to ensure implicit lock releases on destruction.
* @var array
*
* @var array
*/
protected static $requestInstances = array();
/**
* @var array Array of lock names (as values) for each persistent ID (as
* Array of lock names for each persistent ID.
*
* Array of lock names (as values) for each persistent ID (as
* key) obtained during the current request.
*
* @var array
*/
protected static $locksBackup = array();
/**
* The data storage.
*
*
* Each persistent ID is a key, and the value is an array.
* Each such array has data keys as its keys, and an array as a value.
* Each such array has as its elements the value, the timeout and the time
* the data was set.
* @var array
*
* @var array
*/
protected static $data = array();
/**
* Creates a new shared memory storage.
*
* Estabilishes a separate persistent storage.
*
*
* Establishes a separate persistent storage.
*
* @param string $persistentId The ID for the storage. The storage will be
* reused if it exists, or created if it doesn't exist. Data and locks
* are namespaced by this ID.
@ -95,9 +104,9 @@ class Placebo extends SHM
}
$this->persistentId = $persistentId;
}
/**
* Releases any unreleased locks.
* Releases any unreleased locks.
*/
public function __destruct()
{
@ -105,23 +114,23 @@ class Placebo extends SHM
static::$locksBackup[$this->persistentId] = array();
}
}
/**
* Checks if the adapter meets its requirements.
*
*
* @return bool TRUE on success, FALSE on failure.
*/
public static function isMeetingRequirements()
{
return 'cli' === PHP_SAPI;
}
/**
* Pretends to obtain a lock.
*
*
* @param string $key Ignored.
* @param double $timeout Ignored.
*
*
* @return bool TRUE on success, FALSE on failure.
*/
public function lock($key, $timeout = null)
@ -133,12 +142,12 @@ class Placebo extends SHM
static::$locksBackup[$this->persistentId][] = $key;
return true;
}
/**
* Pretends to release a lock.
*
*
* @param string $key Ignored
*
*
* @return bool TRUE on success, FALSE on failure.
*/
public function unlock($key)
@ -147,36 +156,38 @@ class Placebo extends SHM
if (!in_array($key, static::$locksBackup[$this->persistentId], true)) {
return false;
}
unset(static::$locksBackup[$this->persistentId][array_search(
$key,
static::$locksBackup[$this->persistentId],
true
)]);
unset(
static::$locksBackup[$this->persistentId][array_search(
$key,
static::$locksBackup[$this->persistentId],
true
)]
);
return true;
}
/**
* Checks if a specified key is in the storage.
*
*
* @param string $key Name of key to check.
*
* @return bool TRUE if the key is in the storage, FALSE otherwise.
*
* @return bool TRUE if the key is in the storage, FALSE otherwise.
*/
public function exists($key)
{
return array_key_exists($key, static::$data[$this->persistentId]);
}
/**
* Adds a value to the shared memory storage.
*
*
* Adds a value to the storage if it doesn't exist, or fails if it does.
*
*
* @param string $key Name of key to associate the value with.
* @param mixed $value Value for the specified key.
* @param int $ttl Because "true" adapters purge the cache at the next
* request, this setting is ignored.
*
*
* @return bool TRUE on success, FALSE on failure.
*/
public function add($key, $value, $ttl = 0)
@ -186,17 +197,17 @@ class Placebo extends SHM
}
return $this->set($key, $value, $ttl);
}
/**
* Sets a value in the shared memory storage.
*
*
* Adds a value to the storage if it doesn't exist, overwrites it otherwise.
*
*
* @param string $key Name of key to associate the value with.
* @param mixed $value Value for the specified key.
* @param int $ttl Because "true" adapters purge the cache at the next
* request, this setting is ignored.
*
*
* @return bool TRUE on success, FALSE on failure.
*/
public function set($key, $value, $ttl = 0)
@ -204,14 +215,14 @@ class Placebo extends SHM
static::$data[$this->persistentId][$key] = $value;
return true;
}
/**
* Gets a value from the shared memory storage.
*
*
* Gets the current value, or throws an exception if it's not stored.
*
*
* @param string $key Name of key to get the value of.
*
*
* @return mixed The current value of the specified key.
*/
public function get($key)
@ -224,12 +235,12 @@ class Placebo extends SHM
200
);
}
/**
* Deletes a value from the shared memory storage.
*
*
* @param string $key Name of key to delete.
*
*
* @return bool TRUE on success, FALSE on failure.
*/
public function delete($key)
@ -240,17 +251,17 @@ class Placebo extends SHM
}
return false;
}
/**
* Increases a value from the shared memory storage.
*
*
* Increases a value from the shared memory storage. Unlike a plain
* set($key, get($key)+$step) combination, this function also implicitly
* performs locking.
*
*
* @param string $key Name of key to increase.
* @param int $step Value to increase the key by.
*
*
* @return int The new value.
*/
public function inc($key, $step = 1)
@ -265,17 +276,17 @@ class Placebo extends SHM
}
return $this->get($key);
}
/**
* Decreases a value from the shared memory storage.
*
*
* Decreases a value from the shared memory storage. Unlike a plain
* set($key, get($key)-$step) combination, this function also implicitly
* performs locking.
*
*
* @param string $key Name of key to decrease.
* @param int $step Value to decrease the key by.
*
*
* @return int The new value.
*/
public function dec($key, $step = 1)
@ -293,46 +304,46 @@ class Placebo extends SHM
/**
* Sets a new value if a key has a certain value.
*
*
* Sets a new value if a key has a certain value. This function only works
* when $old and $new are longs.
*
*
* @param string $key Key of the value to compare and set.
* @param int $old The value to compare the key against.
* @param int $new The value to set the key to.
*
* @return bool TRUE on success, FALSE on failure.
*
* @return bool TRUE on success, FALSE on failure.
*/
public function cas($key, $old, $new)
{
return $this->exists($key) && ($this->get($key) === $old)
&& is_int($new) && $this->set($key, $new);
}
/**
* Clears the persistent storage.
*
*
* Clears the persistent storage, i.e. removes all keys. Locks are left
* intact.
*
*
* @return void
*/
public function clear()
{
static::$data[$this->persistentId] = array();
}
/**
* Retrieve an external iterator
*
*
* Returns an external iterator.
*
*
* @param string|null $filter A PCRE regular expression.
* Only matching keys will be iterated over.
* Setting this to NULL matches all keys of this instance.
* @param bool $keysOnly Whether to return only the keys,
* or return both the keys and values.
*
*
* @return ArrayObject An array with all matching keys as array keys,
* and values as array values. If $keysOnly is TRUE, the array keys are
* numeric, and the array values are key names.
@ -346,7 +357,7 @@ class Placebo extends SHM
: static::$data[$this->persistentId]
);
}
$result = array();
foreach (static::$data[$this->persistentId] as $key => $value) {
if (preg_match($filter, $key)) {

View File

@ -1,18 +1,19 @@
<?php
/**
* ~~summary~~
*
* ~~description~~
*
* Wrapper for shared memory and locking functionality across different extensions.
*
* Allows you to share data across requests as long as the PHP process is running. One of APC or WinCache is required to accomplish this, with other extensions being potentially pluggable as adapters.
*
* PHP version 5
*
*
* @category Caching
* @package PEAR2_Cache_SHM
* @author Vasil Rangelov <boen.robot@gmail.com>
* @copyright 2011 Vasil Rangelov
* @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
* @version 0.1.3
* @version 0.2.0
* @link http://pear2.php.net/PEAR2_Cache_SHM
*/
/**
@ -32,7 +33,7 @@ use ArrayObject;
/**
* Shared memory adapter for the WinCache extension.
*
*
* @category Caching
* @package PEAR2_Cache_SHM
* @author Vasil Rangelov <boen.robot@gmail.com>
@ -42,30 +43,35 @@ use ArrayObject;
class Wincache extends SHM
{
/**
* @var string ID of the current storage.
* ID of the current storage.
*
* @var string
*/
protected $persistentId;
/**
* List of persistent IDs.
*
*
* A list of persistent IDs within the current request (as keys) with an int
* (as a value) specifying the number of instances in the current request.
* Used as an attempt to ensure implicit lock releases on destruction.
* @var array
*
* @var array
*/
protected static $requestInstances = array();
/**
* @var array Array of lock names obtained during the current request.
* Array of lock names obtained during the current request.
*
* @var array
*/
protected static $locksBackup = array();
/**
* Creates a new shared memory storage.
*
* Estabilishes a separate persistent storage.
*
*
* Establishes a separate persistent storage.
*
* @param string $persistentId The ID for the storage. The storage will be
* reused if it exists, or created if it doesn't exist. Data and locks
* are namespaced by this ID.
@ -81,28 +87,29 @@ class Wincache extends SHM
static::$locksBackup[$this->persistentId] = array();
}
}
/**
* Encodes a lock name
*
*
* Encodes a lock name, so that it can be properly obtained. The scheme used
* is a subset of URL encoding, with only the "%" and "\" characters being
* escaped. The encoding itself is necessary, since lock names can't contain
* the "\" character.
*
*
* @param string $name The lock name to encode.
*
*
* @return string The encoded name.
*
* @link http://msdn.microsoft.com/en-us/library/ms682411(VS.85).aspx
*/
protected static function encodeLockName($name)
{
return str_replace(array('%', '\\'), array('%25', '%5C'), $name);
}
/**
* Checks if the adapter meets its requirements.
*
*
* @return bool TRUE on success, FALSE on failure.
*/
public static function isMeetingRequirements()
@ -112,7 +119,7 @@ class Wincache extends SHM
&& ini_get('wincache.ucenabled')
&& ('cli' !== PHP_SAPI || ini_get('wincache.enablecli'));
}
/**
* Releases any locks obtained by this instance as soon as there are no more
* references to the object's persistent ID.
@ -128,15 +135,15 @@ class Wincache extends SHM
}
}
/**
* Obtains a named lock.
*
*
* @param string $key Name of the key to obtain. Note that $key may
* repeat for each distinct $persistentId.
* @param double $timeout Ignored with WinCache. Script will always block if
* the lock can't be immediatly obtained.
*
* the lock can't be immediately obtained.
*
* @return bool TRUE on success, FALSE on failure.
*/
public function lock($key, $timeout = null)
@ -149,13 +156,13 @@ class Wincache extends SHM
}
return $result;
}
/**
* Releases a named lock.
*
*
* @param string $key Name of the key to release. Note that $key may
* repeat for each distinct $persistentId.
*
*
* @return bool TRUE on success, FALSE on failure.
*/
public function unlock($key)
@ -164,68 +171,70 @@ class Wincache extends SHM
$this->persistentId . static::encodeLockName($key)
);
if ($result) {
unset(static::$locksBackup[$this->persistentId][array_search(
$key,
static::$locksBackup[$this->persistentId],
true
)]);
unset(
static::$locksBackup[$this->persistentId][array_search(
$key,
static::$locksBackup[$this->persistentId],
true
)]
);
}
return $result;
}
/**
* Checks if a specified key is in the storage.
*
*
* @param string $key Name of key to check.
*
* @return bool TRUE if the key is in the storage, FALSE otherwise.
*
* @return bool TRUE if the key is in the storage, FALSE otherwise.
*/
public function exists($key)
{
return wincache_ucache_exists($this->persistentId . $key);
}
/**
* Adds a value to the shared memory storage.
*
*
* Sets a value to the storage if it doesn't exist, or fails if it does.
*
*
* @param string $key Name of key to associate the value with.
* @param mixed $value Value for the specified key.
* @param int $ttl Seconds to store the value. If set to 0 indicates no
* time limit.
*
*
* @return bool TRUE on success, FALSE on failure.
*/
public function add($key, $value, $ttl = 0)
{
return wincache_ucache_add($this->persistentId . $key, $value, $ttl);
}
/**
* Sets a value in the shared memory storage.
*
*
* Adds a value to the storage if it doesn't exist, overwrites it otherwise.
*
*
* @param string $key Name of key to associate the value with.
* @param mixed $value Value for the specified key.
* @param int $ttl Seconds to store the value. If set to 0 indicates no
* time limit.
*
*
* @return bool TRUE on success, FALSE on failure.
*/
public function set($key, $value, $ttl = 0)
{
return wincache_ucache_set($this->persistentId . $key, $value, $ttl);
}
/**
* Gets a value from the shared memory storage.
*
*
* Gets the current value, or throws an exception if it's not stored.
*
*
* @param string $key Name of key to get the value of.
*
*
* @return mixed The current value of the specified key.
*/
public function get($key)
@ -239,29 +248,29 @@ class Wincache extends SHM
}
return $value;
}
/**
* Deletes a value from the shared memory storage.
*
*
* @param string $key Name of key to delete.
*
*
* @return bool TRUE on success, FALSE on failure.
*/
public function delete($key)
{
return wincache_ucache_delete($this->persistentId . $key);
}
/**
* Increases a value from the shared memory storage.
*
*
* Increases a value from the shared memory storage. Unlike a plain
* set($key, get($key)+$step) combination, this function also implicitly
* performs locking.
*
*
* @param string $key Name of key to increase.
* @param int $step Value to increase the key by.
*
*
* @return int The new value.
*/
public function inc($key, $step = 1)
@ -279,17 +288,17 @@ class Wincache extends SHM
}
return $newValue;
}
/**
* Decreases a value from the shared memory storage.
*
*
* Decreases a value from the shared memory storage. Unlike a plain
* set($key, get($key)-$step) combination, this function also implicitly
* performs locking.
*
*
* @param string $key Name of key to decrease.
* @param int $step Value to decrease the key by.
*
*
* @return int The new value.
*/
public function dec($key, $step = 1)
@ -310,27 +319,27 @@ class Wincache extends SHM
/**
* Sets a new value if a key has a certain value.
*
*
* Sets a new value if a key has a certain value. This function only works
* when $old and $new are longs.
*
*
* @param string $key Key of the value to compare and set.
* @param int $old The value to compare the key against.
* @param int $new The value to set the key to.
*
* @return bool TRUE on success, FALSE on failure.
*
* @return bool TRUE on success, FALSE on failure.
*/
public function cas($key, $old, $new)
{
return wincache_ucache_cas($this->persistentId . $key, $old, $new);
}
/**
* Clears the persistent storage.
*
*
* Clears the persistent storage, i.e. removes all keys. Locks are left
* intact.
*
*
* @return void
*/
public function clear()
@ -344,18 +353,18 @@ class Wincache extends SHM
}
}
}
/**
* Retrieve an external iterator
*
*
* Returns an external iterator.
*
*
* @param string|null $filter A PCRE regular expression.
* Only matching keys will be iterated over.
* Setting this to NULL matches all keys of this instance.
* @param bool $keysOnly Whether to return only the keys,
* or return both the keys and values.
*
*
* @return ArrayObject An array with all matching keys as array keys,
* and values as array values. If $keysOnly is TRUE, the array keys are
* numeric, and the array values are key names.

View File

@ -1,9 +1,10 @@
<?php
/**
* ~~summary~~
* Wrapper for shared memory and locking functionality across different extensions.
*
* ~~description~~
* Allows you to share data across requests as long as the PHP process is running. One of APC or WinCache is required to accomplish this, with other extensions being potentially pluggable as adapters.
*
* PHP version 5
*
@ -12,7 +13,7 @@
* @author Vasil Rangelov <boen.robot@gmail.com>
* @copyright 2011 Vasil Rangelov
* @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
* @version 0.1.3
* @version 0.2.0
* @link http://pear2.php.net/PEAR2_Cache_SHM
*/
/**

View File

@ -1,9 +1,10 @@
<?php
/**
* ~~summary~~
* Wrapper for shared memory and locking functionality across different extensions.
*
* ~~description~~
* Allows you to share data across requests as long as the PHP process is running. One of APC or WinCache is required to accomplish this, with other extensions being potentially pluggable as adapters.
*
* PHP version 5
*
@ -12,7 +13,7 @@
* @author Vasil Rangelov <boen.robot@gmail.com>
* @copyright 2011 Vasil Rangelov
* @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
* @version 0.1.3
* @version 0.2.0
* @link http://pear2.php.net/PEAR2_Cache_SHM
*/
/**

View File

@ -59,6 +59,7 @@ class CommandLine
* Error messages.
*
* @var array $errors Error messages
*
* @todo move this to PEAR2\Console\CommandLine\MessageProvider
*/
public static $errors = array(
@ -130,7 +131,7 @@ class CommandLine
/**
* The command line parser renderer instance.
*
* @var object that implements PEAR2\Console\CommandLine\Renderer interface
* @var PEAR2\Console\CommandLine\Renderer a renderer
*/
public $renderer = false;
@ -144,7 +145,7 @@ class CommandLine
/**
* The command line message provider instance.
*
* @var PEAR2\Console\CommandLine\MessageProvider A message provider instance
* @var PEAR2\Console\CommandLine\MessageProvider A message provider
*/
public $message_provider = false;
@ -191,6 +192,7 @@ class CommandLine
* convenience.
*
* @var PEAR2\Console\CommandLine The parent instance
*
* @todo move CommandLine::parent to CommandLine\Command
*/
public $parent = false;
@ -272,7 +274,7 @@ class CommandLine
* </code>
*
* @var array
* @see PEAR2\Console\CommandLine\MessageProvider_Default
* @see PEAR2\Console\CommandLine\MessageProvider\DefaultProvider
*/
public $messages = array();
@ -286,6 +288,9 @@ class CommandLine
*/
private $_dispatchLater = array();
private $_lastopt = false;
private $_stopflag = false;
// }}}
// __construct() {{{
@ -345,7 +350,7 @@ class CommandLine
// set default instances
$this->renderer = new CommandLine\Renderer_Default($this);
$this->outputter = new CommandLine\Outputter_Default();
$this->message_provider = new CommandLine\MessageProvider_Default();
$this->message_provider = new CommandLine\MessageProvider\DefaultProvider();
}
// }}}
@ -481,6 +486,7 @@ class CommandLine
* @param array $params An array containing the argument attributes
*
* @return PEAR2\Console\CommandLine\Argument the added argument
*
* @see PEAR2\Console\CommandLine\Argument
*/
public function addArgument($name, $params = array())
@ -842,6 +848,7 @@ class CommandLine
* @param array $params An array of search=>replaces entries
*
* @return void
*
* @todo remove Console::triggerError() and use exceptions only
*/
public static function triggerError($msgId, $level, $params=array())
@ -912,7 +919,7 @@ class CommandLine
// Check if an invalid subcommand was specified. If there are
// subcommands and no arguments, but an argument was provided, it is
// an invalid subcommand.
if ( count($this->commands) > 0
if (count($this->commands) > 0
&& count($this->args) === 0
&& count($args) > 0
) {
@ -925,7 +932,7 @@ class CommandLine
}
// if subcommand_required is set to true we must check that we have a
// subcommand.
if ( count($this->commands)
if (count($this->commands)
&& $this->subcommand_required
&& !$result->command_name
) {
@ -989,23 +996,21 @@ class CommandLine
*/
protected function parseToken($token, $result, &$args, $argc)
{
static $lastopt = false;
static $stopflag = false;
$last = $argc === 0;
if (!$stopflag && $lastopt) {
if (!$this->_stopflag && $this->_lastopt) {
if (substr($token, 0, 1) == '-') {
if ($lastopt->argument_optional) {
$this->_dispatchAction($lastopt, '', $result);
if ($lastopt->action != 'StoreArray') {
$lastopt = false;
if ($this->_lastopt->argument_optional) {
$this->_dispatchAction($this->_lastopt, '', $result);
if ($this->_lastopt->action != 'StoreArray') {
$this->_lastopt = false;
}
} else if (isset($result->options[$lastopt->name])) {
} else if (isset($result->options[$this->_lastopt->name])) {
// case of an option that expect a list of args
$lastopt = false;
$this->_lastopt = false;
} else {
throw CommandLine\Exception::factory(
'OPTION_VALUE_REQUIRED',
array('name' => $lastopt->name),
array('name' => $this->_lastopt->name),
$this,
$this->messages
);
@ -1015,8 +1020,8 @@ class CommandLine
// is to consider that if there's already an element in the
// array, and the commandline expects one or more args, we
// leave last tokens to arguments
if ($lastopt->action == 'StoreArray'
&& !empty($result->options[$lastopt->name])
if ($this->_lastopt->action == 'StoreArray'
&& !empty($result->options[$this->_lastopt->name])
&& count($this->args) > ($argc + count($args))
) {
if (!is_null($token)) {
@ -1024,22 +1029,22 @@ class CommandLine
}
return;
}
if (!is_null($token) || $lastopt->action == 'Password') {
$this->_dispatchAction($lastopt, $token, $result);
if (!is_null($token) || $this->_lastopt->action == 'Password') {
$this->_dispatchAction($this->_lastopt, $token, $result);
}
if ($lastopt->action != 'StoreArray') {
$lastopt = false;
if ($this->_lastopt->action != 'StoreArray') {
$this->_lastopt = false;
}
return;
}
}
if (!$stopflag && substr($token, 0, 2) == '--') {
if (!$this->_stopflag && substr($token, 0, 2) == '--') {
// a long option
$optkv = explode('=', $token, 2);
if (trim($optkv[0]) == '--') {
// the special argument "--" forces in all cases the end of
// option scanning.
$stopflag = true;
$this->_stopflag = true;
return;
}
$opt = $this->findOption($optkv[0]);
@ -1072,14 +1077,14 @@ class CommandLine
);
}
// we will have a value next time
$lastopt = $opt;
$this->_lastopt = $opt;
return;
}
if ($opt->action == 'StoreArray') {
$lastopt = $opt;
$this->_lastopt = $opt;
}
$this->_dispatchAction($opt, $value, $result);
} else if (!$stopflag && substr($token, 0, 1) == '-') {
} else if (!$this->_stopflag && substr($token, 0, 1) == '-') {
// a short option
$optname = substr($token, 0, 2);
if ($optname == '-') {
@ -1100,7 +1105,7 @@ class CommandLine
// in short: handle -f<value> and -f <value>
$next = substr($token, 2, 1);
// check if we must wait for a value
if ($next === false) {
if (!$next) {
if ($opt->expectsArgument()) {
if ($last && !$opt->argument_optional) {
throw CommandLine\Exception::factory(
@ -1111,7 +1116,7 @@ class CommandLine
);
}
// we will have a value next time
$lastopt = $opt;
$this->_lastopt = $opt;
return;
}
$value = false;
@ -1136,7 +1141,7 @@ class CommandLine
}
}
if ($opt->action == 'StoreArray') {
$lastopt = $opt;
$this->_lastopt = $opt;
}
$value = substr($token, 2);
}
@ -1145,8 +1150,8 @@ class CommandLine
// We have an argument.
// if we are in POSIX compliant mode, we must set the stop flag to
// true in order to stop option parsing.
if (!$stopflag && $this->force_posix) {
$stopflag = true;
if (!$this->_stopflag && $this->force_posix) {
$this->_stopflag = true;
}
if (!is_null($token)) {
$args[] = $token;

View File

@ -11,14 +11,15 @@
* through the world-wide-web at the following URI:
* http://opensource.org/licenses/mit-license.php
*
* @category Console
* @category Console
* @package PEAR2\Console\CommandLine
* @author David JEAN LOUIS <izimobil@gmail.com>
* @copyright 2007-2009 David JEAN LOUIS
* @license http://opensource.org/licenses/mit-license.php MIT License
* @version 0.2.1
* @license http://opensource.org/licenses/mit-license.php MIT License
* @version 0.2.3
* @link http://pear2.php.net/PEAR2_Console_CommandLine
* @since File available since release 0.1.0
*
* @filesource
*/
namespace PEAR2\Console\CommandLine;

View File

@ -11,14 +11,15 @@
* through the world-wide-web at the following URI:
* http://opensource.org/licenses/mit-license.php
*
* @category Console
* @category Console
* @package PEAR2\Console\CommandLine
* @author David JEAN LOUIS <izimobil@gmail.com>
* @copyright 2007-2009 David JEAN LOUIS
* @license http://opensource.org/licenses/mit-license.php MIT License
* @version 0.2.1
* @license http://opensource.org/licenses/mit-license.php MIT License
* @version 0.2.3
* @link http://pear2.php.net/PEAR2_Console_CommandLine
* @since File available since release 0.1.0
*
* @filesource
*/
namespace PEAR2\Console\CommandLine\Action;

View File

@ -11,14 +11,15 @@
* through the world-wide-web at the following URI:
* http://opensource.org/licenses/mit-license.php
*
* @category Console
* @category Console
* @package PEAR2\Console\CommandLine
* @author David JEAN LOUIS <izimobil@gmail.com>
* @copyright 2007-2009 David JEAN LOUIS
* @license http://opensource.org/licenses/mit-license.php MIT License
* @version 0.2.1
* @license http://opensource.org/licenses/mit-license.php MIT License
* @version 0.2.3
* @link http://pear2.php.net/PEAR2_Console_CommandLine
* @since File available since release 0.1.0
*
* @filesource
*/
@ -46,7 +47,7 @@ use PEAR2\Console\CommandLine;
* <code>
* $ script.php -v -v -v
* </code>
* or:
* or:
* <code>
* $ script.php -vvv
* </code>

View File

@ -11,14 +11,15 @@
* through the world-wide-web at the following URI:
* http://opensource.org/licenses/mit-license.php
*
* @category Console
* @category Console
* @package PEAR2\Console\CommandLine
* @author David JEAN LOUIS <izimobil@gmail.com>
* @copyright 2007-2009 David JEAN LOUIS
* @license http://opensource.org/licenses/mit-license.php MIT License
* @version 0.2.1
* @license http://opensource.org/licenses/mit-license.php MIT License
* @version 0.2.3
* @link http://pear2.php.net/PEAR2_Console_CommandLine
* @since File available since release 0.1.0
*
* @filesource
*/

View File

@ -11,21 +11,22 @@
* through the world-wide-web at the following URI:
* http://opensource.org/licenses/mit-license.php
*
* @category Console
* @category Console
* @package PEAR2\Console\CommandLine
* @author David JEAN LOUIS <izimobil@gmail.com>
* @copyright 2007-2009 David JEAN LOUIS
* @license http://opensource.org/licenses/mit-license.php MIT License
* @license http://opensource.org/licenses/mit-license.php MIT License
* @version CVS: $Id: List.php,v 1.2 2009/02/27 08:03:17 izi Exp $
* @link http://pear2.php.net/PEAR2_Console_CommandLine
* @since File available since release 0.1.0
*
* @filesource
*/
namespace PEAR2\Console\CommandLine;
/**
* Class that represent the List action, a special action that simply output an
* Class that represent the List action, a special action that simply output an
* array as a list.
*
* @category Console
@ -43,10 +44,10 @@ class Action_List extends Action
/**
* Executes the action with the value entered by the user.
* Possible parameters are:
* - message: an alternative message to display instead of the default
* - message: an alternative message to display instead of the default
* message,
* - delimiter: an alternative delimiter instead of the comma,
* - post: a string to append after the message (default is the new line
* - post: a string to append after the message (default is the new line
* char).
*
* @param mixed $value The option value
@ -57,8 +58,8 @@ class Action_List extends Action
public function execute($value = false, $params = array())
{
$list = isset($params['list']) ? $params['list'] : array();
$msg = isset($params['message'])
? $params['message']
$msg = isset($params['message'])
? $params['message']
: $this->parser->message_provider->get('LIST_DISPLAYED_MESSAGE');
$del = isset($params['delimiter']) ? $params['delimiter'] : ', ';
$post = isset($params['post']) ? $params['post'] : "\n";

View File

@ -11,14 +11,15 @@
* through the world-wide-web at the following URI:
* http://opensource.org/licenses/mit-license.php
*
* @category Console
* @category Console
* @package PEAR2\Console\CommandLine
* @author David JEAN LOUIS <izimobil@gmail.com>
* @copyright 2007-2009 David JEAN LOUIS
* @license http://opensource.org/licenses/mit-license.php MIT License
* @version 0.2.1
* @license http://opensource.org/licenses/mit-license.php MIT License
* @version 0.2.3
* @link http://pear2.php.net/PEAR2_Console_CommandLine
* @since File available since release 0.1.0
*
* @filesource
*/
@ -27,8 +28,8 @@ namespace PEAR2\Console\CommandLine\Action;
use PEAR2\Console\CommandLine;
/**
* Class that represent the Password action, a special action that allow the
* user to specify the password on the commandline or to be prompted for
* Class that represent the Password action, a special action that allow the
* user to specify the password on the commandline or to be prompted for
* entering it.
*
* @category Console
@ -62,7 +63,8 @@ class Password extends CommandLine\Action
* Prompts the password to the user without echoing it.
*
* @return string
* @todo not echo-ing the password does not work on windows is there a way
*
* @todo not echo-ing the password does not work on windows is there a way
* to make this work ?
*/
private function _promptPassword()

View File

@ -11,14 +11,15 @@
* through the world-wide-web at the following URI:
* http://opensource.org/licenses/mit-license.php
*
* @category Console
* @category Console
* @package PEAR2\Console\CommandLine
* @author David JEAN LOUIS <izimobil@gmail.com>
* @copyright 2007-2009 David JEAN LOUIS
* @license http://opensource.org/licenses/mit-license.php MIT License
* @version 0.2.1
* @license http://opensource.org/licenses/mit-license.php MIT License
* @version 0.2.3
* @link http://pear2.php.net/PEAR2_Console_CommandLine
* @since File available since release 0.1.0
*
* @filesource
*/
@ -29,7 +30,7 @@ use PEAR2\Console\CommandLine;
/**
* Class that represent the StoreArray action.
*
* The execute method appends the value of the option entered by the user to
* The execute method appends the value of the option entered by the user to
* the result option array entry.
*
* @category Console

View File

@ -11,14 +11,15 @@
* through the world-wide-web at the following URI:
* http://opensource.org/licenses/mit-license.php
*
* @category Console
* @category Console
* @package PEAR2\Console\CommandLine
* @author David JEAN LOUIS <izimobil@gmail.com>
* @copyright 2007-2009 David JEAN LOUIS
* @license http://opensource.org/licenses/mit-license.php MIT License
* @version 0.2.1
* @license http://opensource.org/licenses/mit-license.php MIT License
* @version 0.2.3
* @link http://pear2.php.net/PEAR2_Console_CommandLine
* @since File available since release 0.1.0
*
* @filesource
*/
@ -30,7 +31,7 @@ use PEAR2\Console\CommandLine;
* Class that represent the StoreFalse action.
*
* The execute method store the boolean 'false' in the corrsponding result
* option array entry (the value is true if the option is not present in the
* option array entry (the value is true if the option is not present in the
* command line entered by the user).
*
* @category Console

View File

@ -11,14 +11,15 @@
* through the world-wide-web at the following URI:
* http://opensource.org/licenses/mit-license.php
*
* @category Console
* @category Console
* @package PEAR2\Console\CommandLine
* @author David JEAN LOUIS <izimobil@gmail.com>
* @copyright 2007-2009 David JEAN LOUIS
* @license http://opensource.org/licenses/mit-license.php MIT License
* @version 0.2.1
* @license http://opensource.org/licenses/mit-license.php MIT License
* @version 0.2.3
* @link http://pear2.php.net/PEAR2_Console_CommandLine
* @since File available since release 0.1.0
*
* @filesource
*/

View File

@ -11,14 +11,15 @@
* through the world-wide-web at the following URI:
* http://opensource.org/licenses/mit-license.php
*
* @category Console
* @category Console
* @package PEAR2\Console\CommandLine
* @author David JEAN LOUIS <izimobil@gmail.com>
* @copyright 2007-2009 David JEAN LOUIS
* @license http://opensource.org/licenses/mit-license.php MIT License
* @version 0.2.1
* @license http://opensource.org/licenses/mit-license.php MIT License
* @version 0.2.3
* @link http://pear2.php.net/PEAR2_Console_CommandLine
* @since File available since release 0.1.0
*
* @filesource
*/
@ -30,7 +31,7 @@ use PEAR2\Console\CommandLine;
* Class that represent the StoreInt action.
*
* The execute method store the value of the option entered by the user as an
* integer in the result option array entry, if the value passed is not an
* integer in the result option array entry, if the value passed is not an
* integer an Exception is raised.
*
* @category Console

View File

@ -11,14 +11,15 @@
* through the world-wide-web at the following URI:
* http://opensource.org/licenses/mit-license.php
*
* @category Console
* @category Console
* @package PEAR2\Console\CommandLine
* @author David JEAN LOUIS <izimobil@gmail.com>
* @copyright 2007-2009 David JEAN LOUIS
* @license http://opensource.org/licenses/mit-license.php MIT License
* @version 0.2.1
* @license http://opensource.org/licenses/mit-license.php MIT License
* @version 0.2.3
* @link http://pear2.php.net/PEAR2_Console_CommandLine
* @since File available since release 0.1.0
*
* @filesource
*/
@ -29,7 +30,7 @@ use PEAR2\Console\CommandLine;
/**
* Class that represent the StoreString action.
*
* The execute method store the value of the option entered by the user as a
* The execute method store the value of the option entered by the user as a
* string in the result option array entry.
*
* @category Console

View File

@ -11,14 +11,15 @@
* through the world-wide-web at the following URI:
* http://opensource.org/licenses/mit-license.php
*
* @category Console
* @category Console
* @package PEAR2\Console\CommandLine
* @author David JEAN LOUIS <izimobil@gmail.com>
* @copyright 2007-2009 David JEAN LOUIS
* @license http://opensource.org/licenses/mit-license.php MIT License
* @version 0.2.1
* @license http://opensource.org/licenses/mit-license.php MIT License
* @version 0.2.3
* @link http://pear2.php.net/PEAR2_Console_CommandLine
* @since File available since release 0.1.0
*
* @filesource
*/
@ -30,7 +31,7 @@ use PEAR2\Console\CommandLine;
* Class that represent the StoreTrue action.
*
* The execute method store the boolean 'true' in the corrsponding result
* option array entry (the value is false if the option is not present in the
* option array entry (the value is false if the option is not present in the
* command line entered by the user).
*
* @category Console

View File

@ -11,14 +11,15 @@
* through the world-wide-web at the following URI:
* http://opensource.org/licenses/mit-license.php
*
* @category Console
* @category Console
* @package PEAR2\Console\CommandLine
* @author David JEAN LOUIS <izimobil@gmail.com>
* @copyright 2007-2009 David JEAN LOUIS
* @license http://opensource.org/licenses/mit-license.php MIT License
* @version 0.2.1
* @license http://opensource.org/licenses/mit-license.php MIT License
* @version 0.2.3
* @link http://pear2.php.net/PEAR2_Console_CommandLine
* @since File available since release 0.1.0
*
* @filesource
*/

View File

@ -16,9 +16,10 @@
* @author David JEAN LOUIS <izimobil@gmail.com>
* @copyright 2007-2009 David JEAN LOUIS
* @license http://opensource.org/licenses/mit-license.php MIT License
* @version 0.2.1
* @version 0.2.3
* @link http://pear2.php.net/PEAR2_Console_CommandLine
* @since File available since release 0.1.0
*
* @filesource
*/
@ -65,6 +66,7 @@ class Argument extends Element
*
* @return void
* @throws PEAR2\Console\CommandLine\Exception
*
* @todo use exceptions
*/
public function validate()

View File

@ -11,14 +11,15 @@
* through the world-wide-web at the following URI:
* http://opensource.org/licenses/mit-license.php
*
* @category Console
* @category Console
* @package PEAR2\Console\CommandLine
* @author David JEAN LOUIS <izimobil@gmail.com>
* @copyright 2007-2009 David JEAN LOUIS
* @license http://opensource.org/licenses/mit-license.php MIT License
* @version 0.2.1
* @license http://opensource.org/licenses/mit-license.php MIT License
* @version 0.2.3
* @link http://pear2.php.net/PEAR2_Console_CommandLine
* @since File available since release 0.1.0
*
* @filesource
*/
@ -27,7 +28,7 @@ namespace PEAR2\Console\CommandLine;
/**
* Class that represent a command with option and arguments.
*
* This class exist just to clarify the interface but at the moment it is
* This class exist just to clarify the interface but at the moment it is
* strictly identical to PEAR2\Console\CommandLine class, it could change in the
* future though.
*
@ -60,7 +61,7 @@ class Command extends \PEAR2\Console\CommandLine
*
* @return void
*/
public function __construct($params = array())
public function __construct($params = array())
{
if (isset($params['aliases'])) {
$this->aliases = $params['aliases'];

View File

@ -20,6 +20,7 @@
* @version CVS: $Id: CustomMessageProvider.php 282427 2009-06-19 10:22:48Z izi $
* @link http://pear2.php.net/PEAR2_Console_CommandLine
* @since File available since release 1.1.0
*
* @filesource
*/
@ -56,8 +57,9 @@ interface CustomMessageProvider
* indexes are message codes.
*
* @return string
*
* @see PEAR2\Console\CommandLine_MessageProvider
* @see PEAR2\Console\CommandLine_MessageProvider_Default
* @see PEAR2\Console\CommandLine_MessageProvider\DefaultProvider
*/
public function getWithCustomMessages(
$code, $vars = array(), $messages = array()

View File

@ -16,9 +16,10 @@
* @author David JEAN LOUIS <izimobil@gmail.com>
* @copyright 2007-2009 David JEAN LOUIS
* @license http://opensource.org/licenses/mit-license.php MIT License
* @version 0.2.1
* @version 0.2.3
* @link http://pear2.php.net/PEAR2_Console_CommandLine
* @since File available since release 0.1.0
*
* @filesource
*/
@ -92,7 +93,7 @@ abstract class Element
* </code>
*
* @var array
* @see PEAR2\Console\CommandLine_MessageProvider_Default
* @see PEAR2\Console\CommandLine_MessageProvider\DefaultProvider
*/
public $messages = array();
@ -124,6 +125,7 @@ abstract class Element
* Returns the string representation of the element.
*
* @return string The string representation of the element
*
* @todo use __toString() instead
*/
public function toString()

View File

@ -11,14 +11,15 @@
* through the world-wide-web at the following URI:
* http://opensource.org/licenses/mit-license.php
*
* @category Console
* @category Console
* @package PEAR2\Console\CommandLine
* @author David JEAN LOUIS <izimobil@gmail.com>
* @copyright 2007-2009 David JEAN LOUIS
* @license http://opensource.org/licenses/mit-license.php MIT License
* @version 0.2.1
* @license http://opensource.org/licenses/mit-license.php MIT License
* @version 0.2.3
* @link http://pear2.php.net/PEAR2_Console_CommandLine
* @since File available since release 0.1.0
*
* @filesource
*/

View File

@ -11,14 +11,15 @@
* through the world-wide-web at the following URI:
* http://opensource.org/licenses/mit-license.php
*
* @category Console
* @category Console
* @package PEAR2\Console\CommandLine
* @author David JEAN LOUIS <izimobil@gmail.com>
* @copyright 2007-2009 David JEAN LOUIS
* @license http://opensource.org/licenses/mit-license.php MIT License
* @version 0.2.1
* @license http://opensource.org/licenses/mit-license.php MIT License
* @version 0.2.3
* @link http://pear2.php.net/PEAR2_Console_CommandLine
* @since File available since release 0.1.0
*
* @filesource
*/
@ -42,14 +43,15 @@ interface MessageProvider
/**
* Retrieves the given string identifier corresponding message.
* For a list of identifiers please see the provided default message
* For a list of identifiers please see the provided default message
* provider.
*
* @param string $code The string identifier of the message
* @param array $vars An array of template variables
*
* @return string
* @see PEAR2\Console\CommandLine_MessageProvider_Default
*
* @see PEAR2\Console\CommandLine\MessageProvider\DefaultProvider
*/
public function get($code, $vars=array());

View File

@ -16,13 +16,17 @@
* @author David JEAN LOUIS <izimobil@gmail.com>
* @copyright 2007-2009 David JEAN LOUIS
* @license http://opensource.org/licenses/mit-license.php MIT License
* @version 0.2.1
* @version 0.2.3
* @link http://pear2.php.net/PEAR2_Console_CommandLine
* @since File available since release 0.1.0
*
* @filesource
*/
namespace PEAR2\Console\CommandLine;
namespace PEAR2\Console\CommandLine\MessageProvider;
use PEAR2\Console\CommandLine\MessageProvider;
use PEAR2\Console\CommandLine\CustomMessageProvider;
/**
* Lightweight class that manages messages used by PEAR2\Console\CommandLine package,
@ -37,7 +41,7 @@ namespace PEAR2\Console\CommandLine;
* @link http://pear2.php.net/PEAR2_Console_CommandLine
* @since Class available since release 0.1.0
*/
class MessageProvider_Default
class DefaultProvider
implements MessageProvider,
CustomMessageProvider
{

View File

@ -16,9 +16,10 @@
* @author David JEAN LOUIS <izimobil@gmail.com>
* @copyright 2007-2009 David JEAN LOUIS
* @license http://opensource.org/licenses/mit-license.php MIT License
* @version 0.2.1
* @version 0.2.3
* @link http://pear2.php.net/PEAR2_Console_CommandLine
* @since File available since release 0.1.0
*
* @filesource
*/
@ -173,6 +174,7 @@ class Option extends Element
* @param string $delim Delimiter to use between short and long option
*
* @return string The string representation of the option
*
* @todo use __toString() instead
*/
public function toString($delim = ", ")
@ -269,6 +271,7 @@ class Option extends Element
*
* @return void
* @throws PEAR2\Console\CommandLine\Exception
*
* @todo use exceptions instead
*/
public function validate()

View File

@ -11,14 +11,15 @@
* through the world-wide-web at the following URI:
* http://opensource.org/licenses/mit-license.php
*
* @category Console
* @category Console
* @package PEAR2\Console\CommandLine
* @author David JEAN LOUIS <izimobil@gmail.com>
* @copyright 2007-2009 David JEAN LOUIS
* @license http://opensource.org/licenses/mit-license.php MIT License
* @version 0.2.1
* @license http://opensource.org/licenses/mit-license.php MIT License
* @version 0.2.3
* @link http://pear2.php.net/PEAR2_Console_CommandLine
* @since File available since release 0.1.0
*
* @filesource
*/

View File

@ -11,14 +11,15 @@
* through the world-wide-web at the following URI:
* http://opensource.org/licenses/mit-license.php
*
* @category Console
* @category Console
* @package PEAR2\Console\CommandLine
* @author David JEAN LOUIS <izimobil@gmail.com>
* @copyright 2007-2009 David JEAN LOUIS
* @license http://opensource.org/licenses/mit-license.php MIT License
* @version 0.2.1
* @license http://opensource.org/licenses/mit-license.php MIT License
* @version 0.2.3
* @link http://pear2.php.net/PEAR2_Console_CommandLine
* @since File available since release 0.1.0
*
* @filesource
*/

View File

@ -11,14 +11,15 @@
* through the world-wide-web at the following URI:
* http://opensource.org/licenses/mit-license.php
*
* @category Console
* @category Console
* @package PEAR2\Console\CommandLine
* @author David JEAN LOUIS <izimobil@gmail.com>
* @copyright 2007-2009 David JEAN LOUIS
* @license http://opensource.org/licenses/mit-license.php MIT License
* @version 0.2.1
* @license http://opensource.org/licenses/mit-license.php MIT License
* @version 0.2.3
* @link http://pear2.php.net/PEAR2_Console_CommandLine
* @since File available since release 0.1.0
*
* @filesource
*/

View File

@ -16,7 +16,7 @@
* @author David JEAN LOUIS <izimobil@gmail.com>
* @copyright 2007-2009 David JEAN LOUIS
* @license http://opensource.org/licenses/mit-license.php MIT License
* @version 0.2.1
* @version 0.2.3
* @link http://pear2.php.net/PEAR2_Console_CommandLine
* @since File available since release 0.1.0
*/

View File

@ -11,14 +11,15 @@
* through the world-wide-web at the following URI:
* http://opensource.org/licenses/mit-license.php
*
* @category Console
* @category Console
* @package PEAR2\Console\CommandLine
* @author David JEAN LOUIS <izimobil@gmail.com>
* @copyright 2007-2009 David JEAN LOUIS
* @license http://opensource.org/licenses/mit-license.php MIT License
* @version 0.2.1
* @license http://opensource.org/licenses/mit-license.php MIT License
* @version 0.2.3
* @link http://pear2.php.net/PEAR2_Console_CommandLine
* @since File available since release 0.1.0
*
* @filesource
*/

View File

@ -11,20 +11,24 @@
* through the world-wide-web at the following URI:
* http://opensource.org/licenses/mit-license.php
*
* @category Console
* @category Console
* @package PEAR2\Console\CommandLine
* @author David JEAN LOUIS <izimobil@gmail.com>
* @copyright 2007-2009 David JEAN LOUIS
* @license http://opensource.org/licenses/mit-license.php MIT License
* @version 0.2.1
* @license http://opensource.org/licenses/mit-license.php MIT License
* @version 0.2.3
* @link http://pear2.php.net/PEAR2_Console_CommandLine
* @since File available since release 0.1.0
*
* @filesource
*/
namespace PEAR2\Console\CommandLine;
use PEAR2\Console\CommandLine;
use DOMDocument;
use DOMNode;
use Phar;
/**
* Parser for command line xml definitions.
@ -49,7 +53,7 @@ class XmlParser
*
* @return PEAR2\Console\CommandLine A parser instance
*/
public static function parse($xmlfile)
public static function parse($xmlfile)
{
if (!is_readable($xmlfile)) {
CommandLine::triggerError(
@ -58,7 +62,7 @@ class XmlParser
array('{$file}' => $xmlfile)
);
}
$doc = new \DomDocument();
$doc = new DOMDocument();
$doc->load($xmlfile);
self::validate($doc);
$nodes = $doc->getElementsByTagName('command');
@ -77,9 +81,9 @@ class XmlParser
*
* @return PEAR2\Console\CommandLine A parser instance
*/
public static function parseString($xmlstr)
public static function parseString($xmlstr)
{
$doc = new \DomDocument();
$doc = new DOMDocument();
$doc->loadXml($xmlstr);
self::validate($doc);
$nodes = $doc->getElementsByTagName('command');
@ -93,27 +97,48 @@ class XmlParser
/**
* Validates the xml definition using Relax NG.
*
* @param DomDocument $doc The document to validate
* @param DOMDocument $doc The document to validate
*
* @return boolean Whether the xml data is valid or not.
* @throws PEAR2\Console\CommandLine\Exception
*
* @todo use exceptions only
*/
public static function validate($doc)
public static function validate(DOMDocument $doc)
{
$rngfile = __DIR__
. '/../../../../data/pear2.php.net/PEAR2_Console_CommandLine/xmlschema.rng';
if (!is_file($rngfile)) {
$rngfile = __DIR__ . '/../../../../data/xmlschema.rng';
$paths = array();
if (!class_exists('Phar', false) || !Phar::running()) {
// Pyrus
$paths[]
= 'D:\Vasko\WEB\PHP\_shared\PEAR2\data/pear2.php.net/PEAR2_Console_CommandLine/xmlschema.rng';
// PEAR
$pearDataDirEnv = getenv('PHP_PEAR_DATA_DIR');
if ($pearDataDirEnv) {
$paths[] = $pearDataDirEnv .
'/PEAR2_Console_CommandLine/xmlschema.rng';
}
$paths[] = 'D:\Vasko\WEB\PHP\_shared\PEAR2\data/PEAR2_Console_CommandLine/xmlschema.rng';
}
if (!is_readable($rngfile)) {
CommandLine::triggerError(
'invalid_xml_file',
E_USER_ERROR,
array('{$file}' => $rngfile)
);
$pkgData = __DIR__ . '/../../../../data/';
// PHAR dep
$paths[] = $pkgData .
'pear2.php.net/PEAR2_Console_CommandLine/xmlschema.rng';
$paths[] = $pkgData . 'PEAR2_Console_CommandLine/xmlschema.rng';
$paths[] = $pkgData . 'pear2/console_commandline/xmlschema.rng';
// Git/Composer
$paths[] = $pkgData . 'xmlschema.rng';
$paths[] = 'xmlschema.rng';
foreach ($paths as $path) {
if (is_readable($path)) {
return $doc->relaxNGValidate($path);
}
}
return $doc->relaxNGValidate($rngfile);
CommandLine::triggerError(
'invalid_xml_file',
E_USER_ERROR,
array('{$file}' => $path)
);
}
// }}}
@ -124,14 +149,15 @@ class XmlParser
* constructed PEAR2\Console\CommandLine or PEAR2\Console\CommandLine_Command
* instance.
*
* @param DomDocumentNode $node The node to parse
* @param bool $isRootNode Whether it is a root node or not
* @param DOMNode $node The node to parse
* @param bool $isRootNode Whether it is a root node or not
*
* @return mixed PEAR2\Console\CommandLine or PEAR2\Console\CommandLine_Command
* @return CommandLine|CommandLine\Command An instance of CommandLine for
* root node, CommandLine\Command otherwise.
*/
private static function _parseCommandNode($node, $isRootNode = false)
private static function _parseCommandNode(DOMNode $node, $isRootNode = false)
{
if ($isRootNode) {
if ($isRootNode) {
$obj = new CommandLine();
} else {
$obj = new CommandLine\Command();
@ -184,11 +210,11 @@ class XmlParser
* Parses an option node and returns the constructed
* PEAR2\Console\CommandLine_Option instance.
*
* @param DomDocumentNode $node The node to parse
* @param DOMNode $node The node to parse
*
* @return PEAR2\Console\CommandLine\Option The built option
*/
private static function _parseOptionNode($node)
private static function _parseOptionNode(DOMNode $node)
{
$obj = new CommandLine\Option($node->getAttribute('name'));
foreach ($node->childNodes as $cNode) {
@ -221,14 +247,14 @@ class XmlParser
// _parseArgumentNode() {{{
/**
* Parses an argument node and returns the constructed
* Parses an argument node and returns the constructed
* PEAR2\Console\CommandLine_Argument instance.
*
* @param DomDocumentNode $node The node to parse
* @param DOMNode $node The node to parse
*
* @return PEAR2\Console\CommandLine\Argument The built argument
*/
private static function _parseArgumentNode($node)
private static function _parseArgumentNode(DOMNode $node)
{
$obj = new CommandLine\Argument($node->getAttribute('name'));
foreach ($node->childNodes as $cNode) {
@ -260,7 +286,7 @@ class XmlParser
/**
* Returns a boolean according to true/false possible strings.
*
*
* @param string $str The string to process
*
* @return boolean

View File

@ -2,6 +2,7 @@
/**
* RouterOS API client implementation.
*
* RouterOS is the flag product of the company MikroTik and is a powerful router software. One of its many abilities is to allow control over it via an API. This package provides a client for that API, in turn allowing you to use PHP to control RouterOS hosts.
*
@ -12,27 +13,31 @@
* @author Vasil Rangelov <boen.robot@gmail.com>
* @copyright 2011 Vasil Rangelov
* @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
* @version 1.0.0b5
* @version 1.0.0b6
* @link http://pear2.php.net/PEAR2_Net_RouterOS
*/
/**
* The namespace declaration.
*/
namespace PEAR2\Net\RouterOS;
/**
* Refers to transmitter direction constants.
*/
use PEAR2\Net\Transmitter\Stream as S;
/**
* Refers to the cryptography constants.
*/
use PEAR2\Net\Transmitter\NetworkStream as N;
/**
* Catches arbitrary exceptions at some points.
*/
use Exception as E;
/**
@ -64,38 +69,55 @@ class Client
const FILTER_ALL = 3;
/**
* @var Communicator The communicator for this client.
* The communicator for this client.
*
* @var Communicator
*/
protected $com;
/**
* @var int The number of currently pending requests.
* The number of currently pending requests.
*
* @var int
*/
protected $pendingRequestsCount = 0;
/**
* @var array An array of responses that have not yet been extracted or
* passed to a callback. Key is the tag of the request, and the value
* is an array of associated responses.
* An array of responses that have not yet been extracted
* or passed to a callback.
*
* Key is the tag of the request, and the value is an array of
* associated responses.
*
* @var array<string,Response[]>
*/
protected $responseBuffer = array();
/**
* @var array An array of callbacks to be executed as responses come.
* Key is the tag of the request, and the value is the callback for it.
* An array of callbacks to be executed as responses come.
*
* Key is the tag of the request, and the value is the callback for it.
*
* @var array<string,callback>
*/
protected $callbacks = array();
/**
* @var Registry A registry for the operations. Particularly helpful at
* persistent connections.
* A registry for the operations.
*
* Particularly helpful at persistent connections.
*
* @var Registry
*/
protected $registry = null;
/**
* @var bool Whether to stream future responses.
* Stream response words that are above this many bytes.
* NULL to disable streaming completely.
*
* @var int|null
*/
private $_streamingResponses = false;
private $_streamingResponses = null;
/**
* Creates a new instance of a RouterOS API client.
@ -103,24 +125,25 @@ class Client
* Creates a new instance of a RouterOS API client with the specified
* settings.
*
* @param string $host Hostname (IP or domain) of the RouterOS server.
* @param string $username The RouterOS username.
* @param string $password The RouterOS password.
* @param int|null $port The port on which the RouterOS server provides
* the API service. You can also specify NULL, in which case the port
* will automatically be chosen between 8728 and 8729, depending on the
* value of $crypto.
* @param bool $persist Whether or not the connection should be a
* @param string $host Hostname (IP or domain) of RouterOS.
* @param string $username The RouterOS username.
* @param string $password The RouterOS password.
* @param int|null $port The port on which the RouterOS host
* provides the API service. You can also specify NULL, in which case
* the port will automatically be chosen between 8728 and 8729,
* depending on the value of $crypto.
* @param bool $persist Whether or not the connection should be a
* persistent one.
* @param float $timeout The timeout for the connection.
* @param string $crypto The encryption for this connection. Must be one
* of the PEAR2\Net\Transmitter\NetworkStream::CRYPTO_* constants. Off
* by default. RouterOS currently supports only TLS, but the setting is
* provided in this fashion for forward compatibility's sake. And for
* the sake of simplicity, if you specify an encryption, don't specify a
* context and your default context uses the value "DEFAULT" for
* ciphers, "ADH" will be automatically added to the list of ciphers.
* @param resource $context A context for the socket.
* @param double|null $timeout The timeout for the connection.
* @param string $crypto The encryption for this connection.
* Must be one of the PEAR2\Net\Transmitter\NetworkStream::CRYPTO_*
* constants. Off by default. RouterOS currently supports only TLS, but
* the setting is provided in this fashion for forward compatibility's
* sake. And for the sake of simplicity, if you specify an encryption,
* don't specify a context and your default context uses the value
* "DEFAULT" for ciphers, "ADH" will be automatically added to the list
* of ciphers.
* @param resource|null $context A context for the socket.
*
* @see sendSync()
* @see sendAsync()
@ -131,15 +154,10 @@ class Client
$password = '',
$port = 8728,
$persist = false,
$timeout = 10,
$timeout = null,
$crypto = N::CRYPTO_OFF,
$context = null
) {
if(strpos($host,":")>-1){
$part = explode(":",$host);
$host = $part[0];
$port = $part[1];
}
$this->com = new Communicator(
$host,
$port,
@ -154,7 +172,7 @@ class Client
: (int) $timeout;
//Login the user if necessary
if ((!$persist
|| !($old = $this->com->getTransmitter()->lock(S::DIRECTION_ALL)))
|| !($old = $this->com->getTransmitter()->lock(S::DIRECTION_ALL)))
&& $this->com->getTransmitter()->isFresh()
) {
if (!static::login($this->com, $username, $password, $timeout)) {
@ -183,7 +201,7 @@ class Client
* the class is invoked and its returned value is returned by this function.
*
* @param mixed $arg Value can be either a {@link Request} to send, which
* would be sent asynchoniously if it has a tag, and synchroniously if
* would be sent asynchronously if it has a tag, and synchronously if
* not, a number to loop with or NULL to complete all pending requests.
* Any other value is converted to string and treated as the tag of a
* request to complete.
@ -210,7 +228,7 @@ class Client
* @param string $username The RouterOS username.
* @param string $password The RouterOS password.
* @param int|null $timeout The time to wait for each response. NULL
* waits indefinetly.
* waits indefinitely.
*
* @return bool TRUE on success, FALSE on failure.
*/
@ -220,7 +238,8 @@ class Client
$password = '',
$timeout = null
) {
if (null !== ($remoteCharset = $com->getCharset($com::CHARSET_REMOTE))
if (
null !== ($remoteCharset = $com->getCharset($com::CHARSET_REMOTE))
&& null !== ($localCharset = $com->getCharset($com::CHARSET_LOCAL))
) {
$password = iconv(
@ -243,8 +262,8 @@ class Client
$com->getTransmitter()->lock($old, true);
}
throw ($e instanceof NotSupportedException
|| $e instanceof UnexpectedValueException
|| !$com->getTransmitter()->isDataAwaiting()) ? new SocketException(
|| $e instanceof UnexpectedValueException
|| !$com->getTransmitter()->isDataAwaiting()) ? new SocketException(
'This is not a compatible RouterOS service',
SocketException::CODE_SERVICE_INCOMPATIBLE,
$e
@ -263,7 +282,7 @@ class Client
* @param string $password The RouterOS password. Potentially parsed
* already by iconv.
* @param int|null $timeout The time to wait for each response. NULL
* waits indefinetly.
* waits indefinitely.
*
* @return bool TRUE on success, FALSE on failure.
*/
@ -274,15 +293,48 @@ class Client
$timeout = null
) {
$request = new Request('/login');
// Update Mikrotik Versi terbaru
// sayangnya ini ngga aman, bagusnya di setup ke port SSL
$request->setArgument('name', $username);
$request->setArgument('password', $password);
$request->send($com);
$oldCharset = $com->getCharset($com::CHARSET_ALL);
$com->setCharset(null, $com::CHARSET_ALL);
$request->verify($com)->send($com);
$com->setCharset($oldCharset, $com::CHARSET_ALL);
$response = new Response($com, false, $timeout);
return $response->getType() === Response::TYPE_FINAL;
null === $response->getProperty('ret');
}
if (
$response->getType() === Response::TYPE_FINAL
&& null === $response->getProperty('ret')
) {
// version >= 6.43
return null === $response->getProperty('message');
} elseif ($response->getType() === Response::TYPE_FINAL) {
// version < 6.43
$request->setArgument('password', '');
$request->setArgument(
'response',
'00' . md5(
chr(0) . $password
. pack(
'H*',
is_string($response->getProperty('ret'))
? $response->getProperty('ret')
: stream_get_contents($response->getProperty('ret'))
)
)
);
$request->verify($com)->send($com);
$response = new Response($com, false, $timeout);
if ($response->getType() === Response::TYPE_FINAL) {
return null === $response->getProperty('ret');
}
}
while (
$response->getType() !== Response::TYPE_FINAL
&& $response->getType() !== Response::TYPE_FATAL
) {
$response = new Response($com, false, $timeout);
}
return false;
}
/**
* Sets the charset(s) for this connection.
@ -293,7 +345,7 @@ class Client
* {@link Communicator::CHARSET_REMOTE}, and when receiving,
* {@link Communicator::CHARSET_REMOTE} is converted to
* {@link Communicator::CHARSET_LOCAL}. Setting NULL to either charset will
* disable charset convertion, and data will be both sent and received "as
* disable charset conversion, and data will be both sent and received "as
* is".
*
* @param mixed $charset The charset to set. If $charsetType is
@ -307,6 +359,7 @@ class Client
* @return string|array The old charset. If $charsetType is
* {@link Communicator::CHARSET_ALL}, the old values will be returned as
* an array with the types as keys, and charsets as values.
*
* @see Communicator::setDefaultCharset()
*/
public function setCharset(
@ -326,6 +379,7 @@ class Client
* @return string|array The current charset. If $charsetType is
* {@link Communicator::CHARSET_ALL}, the current values will be
* returned as an array with the types as keys, and charsets as values.
*
* @see setCharset()
*/
public function getCharset($charsetType)
@ -336,16 +390,18 @@ class Client
/**
* Sends a request and waits for responses.
*
* @param Request $request The request to send.
* @param callback $callback Optional. A function that is to be executed
* when new responses for this request are available. The callback takes
* two parameters. The {@link Response} object as the first, and the
* {@link Client} object as the second one. If the function returns
* TRUE, the request is canceled. Note that the callback may be executed
* one last time after that with a response that notifies about the
* canceling.
* @param Request $request The request to send.
* @param callback|null $callback Optional. A function that is to be
* executed when new responses for this request are available.
* The callback takes two parameters. The {@link Response} object as
* the first, and the {@link Client} object as the second one. If the
* callback returns TRUE, the request is canceled. Note that the
* callback may be executed at least two times after that. Once with a
* {@link Response::TYPE_ERROR} response that notifies about the
* canceling, plus the {@link Response::TYPE_FINAL} response.
*
* @return $this The client object.
*
* @see completeRequest()
* @see loop()
* @see cancelRequest()
@ -354,7 +410,7 @@ class Client
{
//Error checking
$tag = $request->getTag();
if ('' == $tag) {
if ('' === (string)$tag) {
throw new DataFlowException(
'Asynchonous commands must have a tag.',
DataFlowException::CODE_TAG_REQUIRED
@ -392,10 +448,11 @@ class Client
* pending request and/or has responses that are not yet extracted.
*
* @param string $tag The tag of the request to look for.
* @param int $filter One of the FILTER_* consntants. Limits the search
* @param int $filter One of the FILTER_* constants. Limits the search
* to the specified places.
*
* @return bool TRUE if the request is active, FALSE otherwise.
*
* @see getPendingRequestsCount()
* @see completeRequest()
*/
@ -417,6 +474,7 @@ class Client
* @param Request $request The request to send.
*
* @return ResponseCollection The received responses as a collection.
*
* @see sendAsync()
* @see close()
*/
@ -437,8 +495,8 @@ class Client
* Starts an event loop for the RouterOS callbacks and finishes when a
* specified request is completed.
*
* @param string $tag The tag of the request to complete. Setting NULL
* completes all requests.
* @param string|null $tag The tag of the request to complete.
* Setting NULL completes all requests.
*
* @return ResponseCollection A collection of {@link Response} objects that
* haven't been passed to a callback function or previously extracted
@ -452,7 +510,7 @@ class Client
$result = $hasNoTag ? array()
: $this->extractNewResponses($tag)->toArray();
while ((!$hasNoTag && $this->isRequestActive($tag))
|| ($hasNoTag && 0 !== $this->getPendingRequestsCount())
|| ($hasNoTag && 0 !== $this->getPendingRequestsCount())
) {
$newReply = $this->dispatchNextResponse(null);
if ($newReply->getTag() === $tag) {
@ -464,8 +522,8 @@ class Client
$result = array_merge(
$result,
$this->isRequestActive($tag)
? $this->extractNewResponses($tag)->toArray()
: array()
? $this->extractNewResponses($tag)->toArray()
: array()
);
}
break;
@ -481,11 +539,13 @@ class Client
* Gets all new responses for a request that haven't been passed to a
* callback and clears the buffer from them.
*
* @param string $tag The tag of the request to extract new responses for.
* @param string|null $tag The tag of the request to extract
* new responses for.
* Specifying NULL with extract new responses for all requests.
*
* @return ResponseCollection A collection of {@link Response} objects for
* the specified request.
*
* @see loop()
*/
public function extractNewResponses($tag = null)
@ -526,12 +586,13 @@ class Client
* are no more pending requests or when a specified timeout has passed
* (whichever comes first).
*
* @param int $sTimeout Timeout for the loop. If NULL, there is no time
* limit.
* @param int $usTimeout Microseconds to add to the time limit.
* @param int|null $sTimeout Timeout for the loop.
* If NULL, there is no time limit.
* @param int $usTimeout Microseconds to add to the time limit.
*
* @return bool TRUE when there are any more pending requests, FALSE
* otherwise.
*
* @see extractNewResponses()
* @see getPendingRequestsCount()
*/
@ -544,7 +605,8 @@ class Client
}
} else {
list($usStart, $sStart) = explode(' ', microtime());
while ($this->getPendingRequestsCount() !== 0
while (
$this->getPendingRequestsCount() !== 0
&& ($sTimeout >= 0 || $usTimeout >= 0)
) {
$this->dispatchNextResponse($sTimeout, $usTimeout);
@ -581,6 +643,7 @@ class Client
* Gets the number of pending requests.
*
* @return int The number of pending requests.
*
* @see isRequestActive()
*/
public function getPendingRequestsCount()
@ -592,22 +655,23 @@ class Client
* Cancels a request.
*
* Cancels an active request. Using this function in favor of a plain call
* to the "/cancel" command is highly reccomended, as it also updates the
* to the "/cancel" command is highly recommended, as it also updates the
* counter of pending requests properly. Note that canceling a request also
* removes any responses for it that were not previously extracted with
* {@link static::extractNewResponses()}.
*
* @param string $tag Tag of the request to cancel. Setting NULL will cancel
* all requests.
* @param string|null $tag Tag of the request to cancel.
* Setting NULL will cancel all requests.
*
* @return $this The client object.
*
* @see sendAsync()
* @see close()
*/
public function cancelRequest($tag = null)
{
$cancelRequest = new Request('/cancel');
$hasTag = !('' == $tag);
$hasTag = !('' === (string)$tag);
$hasReg = null !== $this->registry;
if ($hasReg && !$hasTag) {
$tags = array_merge(
@ -663,32 +727,39 @@ class Client
/**
* Sets response streaming setting.
*
* Sets whether future responses are streamed. If responses are streamed,
* the argument values are returned as streams instead of strings. This is
* particularly useful if you expect a response that may contain one or more
* very large words.
* Sets when future response words are streamed. If a word is streamed,
* the property value is returned a stream instead of a string, and
* unrecognized words are returned entirely as streams instead of strings.
* This is particularly useful if you expect a response that may contain
* one or more very large words.
*
* @param bool $streamingResponses Whether to stream future responses.
* @param int|null $threshold Threshold after which to stream
* a word. That is, a word less than this length will not be streamed.
* If set to 0, effectively all words are streamed.
* NULL to disable streaming altogether.
*
* @return bool The previous value of the setting.
* @see isStreamingResponses()
* @return $this The client object.
*
* @see getStreamingResponses()
*/
public function setStreamingResponses($streamingResponses)
public function setStreamingResponses($threshold)
{
$oldValue = $this->_streamingResponses;
$this->_streamingResponses = (bool) $streamingResponses;
return $oldValue;
$this->_streamingResponses = $threshold === null
? null
: (int) $threshold;
return $this;
}
/**
* Gets response streaming setting.
*
* Gets whether future responses are streamed.
* Gets when future response words are streamed.
*
* @return int|null The value of the setting.
*
* @return bool The value of the setting.
* @see setStreamingResponses()
*/
public function isStreamingResponses()
public function getStreamingResponses()
{
return $this->_streamingResponses;
}
@ -758,12 +829,13 @@ class Client
* @param Request $request The request to send.
*
* @return $this The client object.
*
* @see sendSync()
* @see sendAsync()
*/
protected function send(Request $request)
{
$request->send($this->com, $this->registry);
$request->verify($this->com)->send($this->com, $this->registry);
$this->pendingRequestsCount++;
return $this;
}
@ -774,12 +846,13 @@ class Client
* Dispatches the next response in queue, i.e. it executes the associated
* callback if there is one, or places the response in the response buffer.
*
* @param int $sTimeout If a response is not immediatly available, wait
* this many seconds. If NULL, wait indefinetly.
* @param int $usTimeout Microseconds to add to the waiting time.
* @param int|null $sTimeout If a response is not immediately available,
* wait this many seconds.
* If NULL, wait indefinitely.
* @param int $usTimeout Microseconds to add to the waiting time.
*
* @return Response The dispatched response.
* @throws SocketException When there's no response within the time limit.
* @return Response The dispatched response.
*/
protected function dispatchNextResponse($sTimeout = 0, $usTimeout = 0)
{
@ -802,10 +875,18 @@ class Client
$this->pendingRequestsCount--;
}
if ('' != $tag) {
if ('' !== (string)$tag) {
if ($this->isRequestActive($tag, self::FILTER_CALLBACK)) {
if ($this->callbacks[$tag]($response, $this)) {
$this->cancelRequest($tag);
try {
$this->cancelRequest($tag);
} catch (DataFlowException $e) {
if (
$e->getCode() !== $e::CODE_UNKNOWN_REQUEST
) {
throw $e;
}
}
} elseif ($isLastForRequest) {
unset($this->callbacks[$tag]);
}

View File

@ -2,17 +2,18 @@
/**
* RouterOS API client implementation.
*
*
* RouterOS is the flag product of the company MikroTik and is a powerful router software. One of its many abilities is to allow control over it via an API. This package provides a client for that API, in turn allowing you to use PHP to control RouterOS hosts.
*
*
* PHP version 5
*
*
* @category Net
* @package PEAR2_Net_RouterOS
* @author Vasil Rangelov <boen.robot@gmail.com>
* @copyright 2011 Vasil Rangelov
* @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
* @version 1.0.0b5
* @version 1.0.0b6
* @link http://pear2.php.net/PEAR2_Net_RouterOS
*/
/**
@ -27,13 +28,13 @@ use PEAR2\Net\Transmitter as T;
/**
* A RouterOS communicator.
*
*
* Implementation of the RouterOS API protocol. Unlike the other classes in this
* package, this class doesn't provide any conviniences beyond the low level
* package, this class doesn't provide any conveniences beyond the low level
* implementation details (automatic word length encoding/decoding, charset
* translation and data integrity), and because of that, its direct usage is
* strongly discouraged.
*
*
* @category Net
* @package PEAR2_Net_RouterOS
* @author Vasil Rangelov <boen.robot@gmail.com>
@ -47,67 +48,76 @@ class Communicator
* Used when getting/setting all (default) charsets.
*/
const CHARSET_ALL = -1;
/**
* Used when getting/setting the (default) remote charset.
*
*
* The remote charset is the charset in which RouterOS stores its data.
* If you want to keep compatibility with your Winbox, this charset should
* match the default charset from your Windows' regional settings.
*/
const CHARSET_REMOTE = 0;
/**
* Used when getting/setting the (default) local charset.
*
*
* The local charset is the charset in which the data from RouterOS will be
* returned as. This charset should match the charset of the place the data
* will eventually be written to.
*/
const CHARSET_LOCAL = 1;
/**
* @var array An array with the default charset types as keys, and the
* default charsets as values.
* An array with the default charset.
*
* Charset types as keys, and the default charsets as values.
*
* @var array<string,string|null>
*/
protected static $defaultCharsets = array(
self::CHARSET_REMOTE => null,
self::CHARSET_LOCAL => null
);
/**
* @var array An array with the current charset types as keys, and the
* current charsets as values.
* An array with the current charset.
*
* Charset types as keys, and the current charsets as values.
*
* @var array<string,string|null>
*/
protected $charsets = array();
/**
* @var T\TcpClient The transmitter for the connection.
* The transmitter for the connection.
*
* @var T\TcpClient
*/
protected $trans;
/**
* Creates a new connection with the specified options.
*
* @param string $host Hostname (IP or domain) of the RouterOS server.
* @param int|null $port The port on which the RouterOS server provides
* the API service. You can also specify NULL, in which case the port
* will automatically be chosen between 8728 and 8729, depending on the
* value of $crypto.
* @param bool $persist Whether or not the connection should be a
*
* @param string $host Hostname (IP or domain) of RouterOS.
* @param int|null $port The port on which the RouterOS host
* provides the API service. You can also specify NULL, in which case
* the port will automatically be chosen between 8728 and 8729,
* depending on the value of $crypto.
* @param bool $persist Whether or not the connection should be a
* persistent one.
* @param float $timeout The timeout for the connection.
* @param string $key A string that uniquely identifies the
* @param double|null $timeout The timeout for the connection.
* @param string $key A string that uniquely identifies the
* connection.
* @param string $crypto The encryption for this connection. Must be one
* of the PEAR2\Net\Transmitter\NetworkStream::CRYPTO_* constants. Off
* by default. RouterOS currently supports only TLS, but the setting is
* provided in this fashion for forward compatibility's sake. And for
* the sake of simplicity, if you specify an encryption, don't specify a
* context and your default context uses the value "DEFAULT" for
* ciphers, "ADH" will be automatically added to the list of ciphers.
* @param resource $context A context for the socket.
*
* @param string $crypto The encryption for this connection.
* Must be one of the PEAR2\Net\Transmitter\NetworkStream::CRYPTO_*
* constants. Off by default. RouterOS currently supports only TLS, but
* the setting is provided in this fashion for forward compatibility's
* sake. And for the sake of simplicity, if you specify an encryption,
* don't specify a context and your default context uses the value
* "DEFAULT" for ciphers, "ADH" will be automatically added to the list
* of ciphers.
* @param resource|null $context A context for the socket.
*
* @see sendWord()
*/
public function __construct(
@ -126,7 +136,16 @@ class Communicator
if (!isset($opts['ssl']['ciphers'])
|| 'DEFAULT' === $opts['ssl']['ciphers']
) {
stream_context_set_option($context, 'ssl', 'ciphers', 'ADH');
stream_context_set_option(
$context,
array(
'ssl' => array(
'ciphers' => 'ADH',
'verify_peer' => false,
'verify_peer_name' => false
)
)
);
}
}
// @codeCoverageIgnoreStart
@ -158,31 +177,31 @@ class Communicator
self::CHARSET_ALL
);
}
/**
* A shorthand gateway.
*
*
* This is a magic PHP method that allows you to call the object as a
* function. Depending on the argument given, one of the other functions in
* the class is invoked and its returned value is returned by this function.
*
* @param string $string A string of the word to send, or NULL to get the
* next word as a string.
*
*
* @param string|null $string A string of the word to send, or NULL to get
* the next word as a string.
*
* @return int|string If a string is provided, returns the number of bytes
* sent, otherwise retuns the next word as a string.
* sent, otherwise returns the next word as a string.
*/
public function __invoke($string = null)
{
return null === $string ? $this->getNextWord()
: $this->sendWord($string);
}
/**
* Checks whether a variable is a seekable stream resource.
*
*
* @param mixed $var The value to check.
*
*
* @return bool TRUE if $var is a seekable stream, FALSE otherwise.
*/
public static function isSeekableStream($var)
@ -193,16 +212,16 @@ class Communicator
}
return false;
}
/**
* Uses iconv to convert a stream from one charset to another.
*
*
* @param string $inCharset The charset of the stream.
* @param string $outCharset The desired resulting charset.
* @param resource $stream The stream to convert. The stream is assumed
* to be seekable, and is read from its current position to its end,
* after which, it is seeked back to its starting position.
*
*
* @return resource A new stream that uses the $out_charset. The stream is a
* subset from the original stream, from its current position to its
* end, seeked at its start.
@ -216,22 +235,25 @@ class Communicator
'convert.iconv.' . $inCharset . '.' . $outCharset,
STREAM_FILTER_WRITE
);
flock($stream, LOCK_SH);
while (!feof($stream)) {
$bytes += stream_copy_to_stream($stream, $result, 0xFFFFF);
$reader = new T\Stream($stream, false);
$writer = new T\Stream($result, false);
$chunkSize = $reader->getChunk(T\Stream::DIRECTION_RECEIVE);
while ($reader->isAvailable() && $reader->isDataAwaiting()) {
$bytes += $writer->send(fread($stream, $chunkSize));
}
fseek($stream, -$bytes, SEEK_CUR);
flock($stream, LOCK_UN);
stream_filter_remove($iconvFilter);
rewind($result);
return $result;
}
/**
* Sets the default charset(s) for new connections.
*
*
* @param mixed $charset The charset to set. If $charsetType is
* {@link self::CHARSET_ALL}, you can supply either a string to use for
* all charsets, or an array with the charset types as keys, and the
@ -239,10 +261,11 @@ class Communicator
* @param int $charsetType Which charset to set. Valid values are the
* CHARSET_* constants. Any other value is treated as
* {@link self::CHARSET_ALL}.
*
*
* @return string|array The old charset. If $charsetType is
* {@link self::CHARSET_ALL}, the old values will be returned as an
* array with the types as keys, and charsets as values.
*
* @see setCharset()
*/
public static function setDefaultCharset(
@ -263,17 +286,18 @@ class Communicator
return $oldCharsets;
}
}
/**
* Gets the default charset(s).
*
*
* @param int $charsetType Which charset to get. Valid values are the
* CHARSET_* constants. Any other value is treated as
* {@link self::CHARSET_ALL}.
*
*
* @return string|array The current charset. If $charsetType is
* {@link self::CHARSET_ALL}, the current values will be returned as an
* array with the types as keys, and charsets as values.
*
* @see setDefaultCharset()
*/
public static function getDefaultCharset($charsetType)
@ -284,12 +308,12 @@ class Communicator
/**
* Gets the length of a seekable stream.
*
*
* Gets the length of a seekable stream.
*
*
* @param resource $stream The stream to check. The stream is assumed to be
* seekable.
*
*
* @return double The number of bytes in the stream between its current
* position and its end.
*/
@ -302,17 +326,17 @@ class Communicator
fseek($stream, $streamPosition, SEEK_SET);
return $streamLength;
}
/**
* Sets the charset(s) for this connection.
*
*
* Sets the charset(s) for this connection. The specified charset(s) will be
* used for all future words. When sending, {@link self::CHARSET_LOCAL} is
* converted to {@link self::CHARSET_REMOTE}, and when receiving,
* {@link self::CHARSET_REMOTE} is converted to {@link self::CHARSET_LOCAL}.
* Setting NULL to either charset will disable charset convertion, and data
* Setting NULL to either charset will disable charset conversion, and data
* will be both sent and received "as is".
*
*
* @param mixed $charset The charset to set. If $charsetType is
* {@link self::CHARSET_ALL}, you can supply either a string to use for
* all charsets, or an array with the charset types as keys, and the
@ -320,10 +344,11 @@ class Communicator
* @param int $charsetType Which charset to set. Valid values are the
* CHARSET_* constants. Any other value is treated as
* {@link self::CHARSET_ALL}.
*
*
* @return string|array The old charset. If $charsetType is
* {@link self::CHARSET_ALL}, the old values will be returned as an
* array with the types as keys, and charsets as values.
*
* @see setDefaultCharset()
*/
public function setCharset($charset, $charsetType = self::CHARSET_ALL)
@ -342,17 +367,18 @@ class Communicator
return $oldCharsets;
}
}
/**
* Gets the charset(s) for this connection.
*
*
* @param int $charsetType Which charset to get. Valid values are the
* CHARSET_* constants. Any other value is treated as
* {@link self::CHARSET_ALL}.
*
*
* @return string|array The current charset. If $charsetType is
* {@link self::CHARSET_ALL}, the current values will be returned as an
* array with the types as keys, and charsets as values.
*
* @see getDefaultCharset()
* @see setCharset()
*/
@ -364,7 +390,7 @@ class Communicator
/**
* Gets the transmitter for this connection.
*
*
* @return T\TcpClient The transmitter for this connection.
*/
public function getTransmitter()
@ -374,12 +400,13 @@ class Communicator
/**
* Sends a word.
*
*
* Sends a word and automatically encodes its length when doing so.
*
*
* @param string $word The word to send.
*
*
* @return int The number of bytes sent.
*
* @see sendWordFromStream()
* @see getNextWord()
*/
@ -407,16 +434,17 @@ class Communicator
/**
* Sends a word based on a stream.
*
*
* Sends a word based on a stream and automatically encodes its length when
* doing so. The stream is read from its current position to its end, and
* then returned to its current position. Because of those operations, the
* supplied stream must be seekable.
*
*
* @param string $prefix A string to prepend before the stream contents.
* @param resource $stream The seekable stream to send.
*
*
* @return int The number of bytes sent.
*
* @see sendWord()
*/
public function sendWordFromStream($prefix, $stream)
@ -441,31 +469,31 @@ class Communicator
$stream
);
}
flock($stream, LOCK_SH);
$totalLength = strlen($prefix) + self::seekableStreamLength($stream);
static::verifyLengthSupport($totalLength);
$bytes = $this->trans->send(self::encodeLength($totalLength) . $prefix);
$bytes += $this->trans->send($stream);
flock($stream, LOCK_UN);
return $bytes;
}
/**
* Verifies that the length is supported.
*
*
* Verifies if the specified length is supported by the API. Throws a
* {@link LengthException} if that's not the case. Currently, RouterOS
* supports words up to 0xFFFFFFFF in length, so that's the only check
* performed.
*
*
* @param int $length The length to verify.
*
*
* @return void
*/
protected static function verifyLengthSupport($length)
public static function verifyLengthSupport($length)
{
if ($length > 0xFFFFFFFF) {
throw new LengthException(
@ -478,10 +506,10 @@ class Communicator
}
/**
* Encodes the length as requred by the RouterOS API.
*
* Encodes the length as required by the RouterOS API.
*
* @param int $length The length to encode.
*
*
* @return string The encoded length.
*/
public static function encodeLength($length)
@ -519,11 +547,12 @@ class Communicator
/**
* Get the next word in queue as a string.
*
*
* Get the next word in queue as a string, after automatically decoding its
* length.
*
*
* @return string The word.
*
* @see close()
*/
public function getNextWord()
@ -541,7 +570,7 @@ class Communicator
'word'
);
}
if (null !== ($remoteCharset = $this->getCharset(self::CHARSET_REMOTE))
&& null !== ($localCharset = $this->getCharset(self::CHARSET_LOCAL))
) {
@ -551,17 +580,18 @@ class Communicator
$word
);
}
return $word;
}
/**
* Get the next word in queue as a stream.
*
*
* Get the next word in queue as a stream, after automatically decoding its
* length.
*
*
* @return resource The word, as a stream.
*
* @see close()
*/
public function getNextWordAsStream()
@ -575,7 +605,7 @@ class Communicator
$remoteCharset . '.' . $localCharset . '//IGNORE//TRANSLIT'
);
}
if ($this->trans->isPersistent()) {
$old = $this->trans->lock(T\Stream::DIRECTION_RECEIVE);
$stream = $this->trans->receiveStream(
@ -591,20 +621,21 @@ class Communicator
'stream word'
);
}
return $stream;
}
/**
* Decodes the lenght of the incoming message.
*
* Decodes the lenght of the incoming message, as specified by the RouterOS
* Decodes the length of the incoming message.
*
* Decodes the length of the incoming message, as specified by the RouterOS
* API.
*
*
* @param T\Stream $trans The transmitter from which to decode the length of
* the incoming message.
*
* @return int The decoded length.
*
* @return int|double The decoded length.
* Is of type "double" only for values above "2 << 31".
*/
public static function decodeLength(T\Stream $trans)
{
@ -618,18 +649,19 @@ class Communicator
}
/**
* Decodes the lenght of the incoming message.
*
* Decodes the lenght of the incoming message, as specified by the RouterOS
* Decodes the length of the incoming message.
*
* Decodes the length of the incoming message, as specified by the RouterOS
* API.
*
*
* Difference with the non private function is that this one doesn't perform
* locking if the connection is a persistent one.
*
*
* @param T\Stream $trans The transmitter from which to decode the length of
* the incoming message.
*
* @return int The decoded length.
*
* @return int|double The decoded length.
* Is of type "double" only for values above "2 << 31".
*/
private static function _decodeLength(T\Stream $trans)
{
@ -661,7 +693,7 @@ class Communicator
/**
* Closes the opened connection, even if it is a persistent one.
*
*
* @return bool TRUE on success, FALSE on failure.
*/
public function close()

View File

@ -2,17 +2,18 @@
/**
* RouterOS API client implementation.
*
*
* RouterOS is the flag product of the company MikroTik and is a powerful router software. One of its many abilities is to allow control over it via an API. This package provides a client for that API, in turn allowing you to use PHP to control RouterOS hosts.
*
*
* PHP version 5
*
*
* @category Net
* @package PEAR2_Net_RouterOS
* @author Vasil Rangelov <boen.robot@gmail.com>
* @copyright 2011 Vasil Rangelov
* @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
* @version 1.0.0b5
* @version 1.0.0b6
* @link http://pear2.php.net/PEAR2_Net_RouterOS
*/
/**
@ -27,7 +28,7 @@ use RuntimeException;
/**
* Exception thrown when the request/response cycle goes an unexpected way.
*
*
* @category Net
* @package PEAR2_Net_RouterOS
* @author Vasil Rangelov <boen.robot@gmail.com>

View File

@ -2,17 +2,18 @@
/**
* RouterOS API client implementation.
*
*
* RouterOS is the flag product of the company MikroTik and is a powerful router software. One of its many abilities is to allow control over it via an API. This package provides a client for that API, in turn allowing you to use PHP to control RouterOS hosts.
*
*
* PHP version 5
*
*
* @category Net
* @package PEAR2_Net_RouterOS
* @author Vasil Rangelov <boen.robot@gmail.com>
* @copyright 2011 Vasil Rangelov
* @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
* @version 1.0.0b5
* @version 1.0.0b6
* @link http://pear2.php.net/PEAR2_Net_RouterOS
*/
/**
@ -22,7 +23,7 @@ namespace PEAR2\Net\RouterOS;
/**
* Generic exception class of this package.
*
*
* @category Net
* @package PEAR2_Net_RouterOS
* @author Vasil Rangelov <boen.robot@gmail.com>

View File

@ -2,17 +2,18 @@
/**
* RouterOS API client implementation.
*
*
* RouterOS is the flag product of the company MikroTik and is a powerful router software. One of its many abilities is to allow control over it via an API. This package provides a client for that API, in turn allowing you to use PHP to control RouterOS hosts.
*
*
* PHP version 5
*
*
* @category Net
* @package PEAR2_Net_RouterOS
* @author Vasil Rangelov <boen.robot@gmail.com>
* @copyright 2011 Vasil Rangelov
* @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
* @version 1.0.0b5
* @version 1.0.0b6
* @link http://pear2.php.net/PEAR2_Net_RouterOS
*/
/**
@ -24,7 +25,7 @@ use InvalidArgumentException as I;
/**
* Exception thrown when there's something wrong with message arguments.
*
*
* @category Net
* @package PEAR2_Net_RouterOS
* @author Vasil Rangelov <boen.robot@gmail.com>

View File

@ -2,17 +2,18 @@
/**
* RouterOS API client implementation.
*
*
* RouterOS is the flag product of the company MikroTik and is a powerful router software. One of its many abilities is to allow control over it via an API. This package provides a client for that API, in turn allowing you to use PHP to control RouterOS hosts.
*
*
* PHP version 5
*
*
* @category Net
* @package PEAR2_Net_RouterOS
* @author Vasil Rangelov <boen.robot@gmail.com>
* @copyright 2011 Vasil Rangelov
* @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
* @version 1.0.0b5
* @version 1.0.0b6
* @link http://pear2.php.net/PEAR2_Net_RouterOS
*/
/**
@ -25,9 +26,14 @@ namespace PEAR2\Net\RouterOS;
*/
use LengthException as L;
/**
* Used in $previous
*/
use Exception as E;
/**
* Exception thrown when there is a problem with a word's length.
*
*
* @category Net
* @package PEAR2_Net_RouterOS
* @author Vasil Rangelov <boen.robot@gmail.com>
@ -36,30 +42,31 @@ use LengthException as L;
*/
class LengthException extends L implements Exception
{
const CODE_UNSUPPORTED = 1200;
const CODE_INVALID = 1300;
const CODE_BEYOND_SHEME = 1301;
/**
* The problematic length.
*
* @var mixed The problematic length.
* @var int|double|null
*/
private $_length;
/**
* Creates a new LengthException.
*
* @param string $message The Exception message to throw.
* @param int $code The Exception code.
* @param \Exception $previous The previous exception used for the exception
* chaining.
* @param number $length The length.
*
* @param string $message The Exception message to throw.
* @param int $code The Exception code.
* @param E|null $previous The previous exception used for the
* exception chaining.
* @param int|double|null $length The length.
*/
public function __construct(
$message,
$code = 0,
$previous = null,
E $previous = null,
$length = null
) {
parent::__construct($message, $code, $previous);
@ -68,8 +75,8 @@ class LengthException extends L implements Exception
/**
* Gets the length.
*
* @return number The length.
*
* @return int|double|null The length.
*/
public function getLength()
{
@ -81,7 +88,7 @@ class LengthException extends L implements Exception
/**
* Returns a string representation of the exception.
*
*
* @return string The exception as a string.
*/
public function __toString()

View File

@ -2,17 +2,18 @@
/**
* RouterOS API client implementation.
*
*
* RouterOS is the flag product of the company MikroTik and is a powerful router software. One of its many abilities is to allow control over it via an API. This package provides a client for that API, in turn allowing you to use PHP to control RouterOS hosts.
*
*
* PHP version 5
*
*
* @category Net
* @package PEAR2_Net_RouterOS
* @author Vasil Rangelov <boen.robot@gmail.com>
* @copyright 2011 Vasil Rangelov
* @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
* @version 1.0.0b5
* @version 1.0.0b6
* @link http://pear2.php.net/PEAR2_Net_RouterOS
*/
/**
@ -31,13 +32,13 @@ use Countable;
use IteratorAggregate;
/**
* Requred for IteratorAggregate::getIterator() to work properly with foreach.
* Required for IteratorAggregate::getIterator() to work properly with foreach.
*/
use ArrayObject;
/**
* Represents a RouterOS message.
*
*
* @category Net
* @package PEAR2_Net_RouterOS
* @author Vasil Rangelov <boen.robot@gmail.com>
@ -48,27 +49,32 @@ abstract class Message implements IteratorAggregate, Countable
{
/**
* @var array An array with message attributes. Each array key is the the
* name of an attribute, and the correspding array value is the value
* for that attribute.
* An array with message attributes.
*
* Each array key is the the name of an attribute,
* and the corresponding array value is the value for that attribute.
*
* @var array<string,string|resource>
*/
protected $attributes = array();
/**
* @var string An optional tag to associate the message with.
* An optional tag to associate the message with.
*
* @var string
*/
private $_tag = null;
/**
* A shorthand gateway.
*
*
* This is a magic PHP method that allows you to call the object as a
* function. Depending on the argument given, one of the other functions in
* the class is invoked and its returned value is returned by this function.
*
* @param string $name The name of an attribute to get the value of, or NULL
* to get the tag.
*
*
* @param string|null $name The name of an attribute to get the value of,
* or NULL to get the tag.
*
* @return string|resource The value of the specified attribute,
* or the tag if NULL is provided.
*/
@ -82,9 +88,9 @@ abstract class Message implements IteratorAggregate, Countable
/**
* Sanitizes a name of an attribute (message or query one).
*
*
* @param mixed $name The name to sanitize.
*
*
* @return string The sanitized name.
*/
public static function sanitizeAttributeName($name)
@ -103,10 +109,10 @@ abstract class Message implements IteratorAggregate, Countable
/**
* Sanitizes a value of an attribute (message or query one).
*
*
* @param mixed $value The value to sanitize.
*
* @return string The sanitized value.
*
* @return string|resource The sanitized value.
*/
public static function sanitizeAttributeValue($value)
{
@ -119,8 +125,9 @@ abstract class Message implements IteratorAggregate, Countable
/**
* Gets the tag that the message is associated with.
*
*
* @return string The current tag or NULL if there isn't a tag.
*
* @see setTag()
*/
public function getTag()
@ -130,13 +137,14 @@ abstract class Message implements IteratorAggregate, Countable
/**
* Sets the tag to associate the request with.
*
*
* Sets the tag to associate the message with. Setting NULL erases the
* currently set tag.
*
*
* @param string $tag The tag to set.
*
*
* @return $this The message object.
*
* @see getTag()
*/
protected function setTag($tag)
@ -147,11 +155,12 @@ abstract class Message implements IteratorAggregate, Countable
/**
* Gets the value of an attribute.
*
*
* @param string $name The name of the attribute.
*
*
* @return string|resource|null The value of the specified attribute.
* Returns NULL if such an attribute is not set.
*
* @see setAttribute()
*/
protected function getAttribute($name)
@ -165,9 +174,10 @@ abstract class Message implements IteratorAggregate, Countable
/**
* Gets all arguments in an array.
*
*
* @return ArrayObject An ArrayObject with the keys being argument names,
* and the array values being argument values.
*
* @see getArgument()
* @see setArgument()
*/
@ -177,40 +187,30 @@ abstract class Message implements IteratorAggregate, Countable
}
/**
* Counts the number of arguments.
*
* @param int $mode The counter mode.
* Either COUNT_NORMAL or COUNT_RECURSIVE.
* When in normal mode, counts the number of arguments.
* When in recursive mode, counts the number of API words
* (including the empty word at the end).
*
* @return int The number of arguments/words.
* Counts the number of attributes.
*
* @return int The number of attributes.
*/
public function count($mode = COUNT_NORMAL)
public function count()
{
$result = count($this->attributes);
if ($mode !== COUNT_NORMAL) {
$result += 2/*first+last word*/
+ (int)(null !== $this->getTag());
}
return $result;
return count($this->attributes);
}
/**
* Sets an attribute for the message.
*
*
* @param string $name Name of the attribute.
* @param string|resource|null $value Value of the attribute as a string or
* seekable stream.
* Setting the value to NULL removes an argument of this name.
* If a seekable stream is provided, it is sent from its current
* posistion to its end, and the pointer is seeked back to its current
* position to its end, and the pointer is seeked back to its current
* position after sending.
* Non seekable streams, as well as all other types, are casted to a
* string.
*
*
* @return $this The message object.
*
* @see getArgument()
*/
protected function setAttribute($name, $value = '')
@ -226,7 +226,7 @@ abstract class Message implements IteratorAggregate, Countable
/**
* Removes all attributes from the message.
*
*
* @return $this The message object.
*/
protected function removeAllAttributes()

View File

@ -2,17 +2,18 @@
/**
* RouterOS API client implementation.
*
*
* RouterOS is the flag product of the company MikroTik and is a powerful router software. One of its many abilities is to allow control over it via an API. This package provides a client for that API, in turn allowing you to use PHP to control RouterOS hosts.
*
*
* PHP version 5
*
*
* @category Net
* @package PEAR2_Net_RouterOS
* @author Vasil Rangelov <boen.robot@gmail.com>
* @copyright 2011 Vasil Rangelov
* @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
* @version 1.0.0b5
* @version 1.0.0b6
* @link http://pear2.php.net/PEAR2_Net_RouterOS
*/
/**
@ -28,7 +29,7 @@ use Exception as E;
/**
* Exception thrown when encountering something not supported by RouterOS or
* this package.
*
*
* @category Net
* @package PEAR2_Net_RouterOS
* @author Vasil Rangelov <boen.robot@gmail.com>
@ -40,24 +41,30 @@ class NotSupportedException extends E implements Exception
const CODE_CONTROL_BYTE = 1601;
const CODE_MENU_MISMATCH = 60000;
const CODE_ARG_PROHIBITED = 60001;
/**
* @var mixed The unsuppported value.
* The unsupported value.
*
* @var mixed
*/
private $_value;
/**
* Creates a new NotSupportedException.
*
* @param string $message The Exception message to throw.
* @param int $code The Exception code.
* @param \Exception $previous The previous exception used for the exception
*
* @param string $message The Exception message to throw.
* @param int $code The Exception code.
* @param E|null $previous The previous exception used for the exception
* chaining.
* @param mixed $value The unsupported value.
* @param mixed $value The unsupported value.
*/
public function __construct(
$message,
$code = 0,
$previous = null,
E $previous = null,
$value = null
) {
parent::__construct($message, $code, $previous);
@ -66,7 +73,7 @@ class NotSupportedException extends E implements Exception
/**
* Gets the unsupported value.
*
*
* @return mixed The unsupported value.
*/
public function getValue()
@ -79,7 +86,7 @@ class NotSupportedException extends E implements Exception
/**
* Returns a string representation of the exception.
*
*
* @return string The exception as a string.
*/
public function __toString()

View File

@ -0,0 +1,43 @@
<?php
/**
* RouterOS API client implementation.
*
* RouterOS is the flag product of the company MikroTik and is a powerful router software. One of its many abilities is to allow control over it via an API. This package provides a client for that API, in turn allowing you to use PHP to control RouterOS hosts.
*
* PHP version 5
*
* @category Net
* @package PEAR2_Net_RouterOS
* @author Vasil Rangelov <boen.robot@gmail.com>
* @copyright 2011 Vasil Rangelov
* @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
* @version 1.0.0b6
* @link http://pear2.php.net/PEAR2_Net_RouterOS
*/
/**
* The namespace declaration.
*/
namespace PEAR2\Net\RouterOS;
/**
* Base of this class.
*/
use DomainException;
/**
* Exception thrown when a value can't be parsed properly.
*
* @category Net
* @package PEAR2_Net_RouterOS
* @author Vasil Rangelov <boen.robot@gmail.com>
* @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
* @link http://pear2.php.net/PEAR2_Net_RouterOS
*/
class ParserException extends DomainException implements Exception
{
const CODE_DATETIME = 1;
const CODE_DATEINTERVAL = 2;
const CODE_ARRAY = 3;
}

View File

@ -2,17 +2,18 @@
/**
* RouterOS API client implementation.
*
*
* RouterOS is the flag product of the company MikroTik and is a powerful router software. One of its many abilities is to allow control over it via an API. This package provides a client for that API, in turn allowing you to use PHP to control RouterOS hosts.
*
*
* PHP version 5
*
*
* @category Net
* @package PEAR2_Net_RouterOS
* @author Vasil Rangelov <boen.robot@gmail.com>
* @copyright 2011 Vasil Rangelov
* @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
* @version 1.0.0b5
* @version 1.0.0b6
* @link http://pear2.php.net/PEAR2_Net_RouterOS
*/
/**
@ -27,7 +28,7 @@ use PEAR2\Net\Transmitter as T;
/**
* Represents a query for RouterOS requests.
*
*
* @category Net
* @package PEAR2_Net_RouterOS
* @author Vasil Rangelov <boen.robot@gmail.com>
@ -41,31 +42,35 @@ class Query
* Checks if the property exists.
*/
const OP_EX = '';
/**
* Checks if the property does not exist.
*/
const OP_NEX = '-';
/**
* Checks if the property equals a certain value.
*/
const OP_EQ = '=';
/**
* Checks if the property is less than a certain value.
*/
const OP_LT = '<';
/**
* Checks if the property is greather than a certain value.
* Checks if the property is greater than a certain value.
*/
const OP_GT = '>';
/**
* @var array An array of the words forming the query. Each value is an
* array with the first member being the predicate (operator and name),
* and the second member being the value for the predicate.
* An array of the words forming the query.
*
* Each value is an array with the first member being the predicate
* (operator and name), and the second member being the value
* for the predicate.
*
* @var array<string,string|null>[]
*/
protected $words = array();
@ -73,16 +78,16 @@ class Query
* This class is not to be instantiated normally, but by static methods
* instead. Use {@link static::where()} to create an instance of it.
*/
private function __construct()
protected function __construct()
{
}
/**
* Sanitizes the operator of a condition.
*
*
* @param string $operator The operator to sanitize.
*
*
* @return string The sanitized operator.
*/
protected static function sanitizeOperator($operator)
@ -107,18 +112,18 @@ class Query
/**
* Creates a new query with an initial condition.
*
*
* @param string $name The name of the property to test.
* @param string|resource|null $value Value of the property as a string
* or seekable stream. Not required for existence tests.
* If a seekable stream is provided, it is sent from its current
* posistion to its end, and the pointer is seeked back to its current
* position to its end, and the pointer is seeked back to its current
* position after sending.
* Non seekable streams, as well as all other types, are casted to a
* string.
* @param string $operator One of the OP_* constants.
* Describes the operation to perform.
*
*
* @return static A new query object.
*/
public static function where(
@ -132,7 +137,7 @@ class Query
/**
* Negates the query.
*
*
* @return $this The query object.
*/
public function not()
@ -143,18 +148,18 @@ class Query
/**
* Adds a condition as an alternative to the query.
*
*
* @param string $name The name of the property to test.
* @param string|resource|null $value Value of the property as a string
* or seekable stream. Not required for existence tests.
* If a seekable stream is provided, it is sent from its current
* posistion to its end, and the pointer is seeked back to its current
* position to its end, and the pointer is seeked back to its current
* position after sending.
* Non seekable streams, as well as all other types, are casted to a
* string.
* @param string $operator One of the OP_* constants.
* Describes the operation to perform.
*
*
* @return $this The query object.
*/
public function orWhere($name, $value = null, $operator = self::OP_EX)
@ -165,18 +170,18 @@ class Query
/**
* Adds a condition in addition to the query.
*
*
* @param string $name The name of the property to test.
* @param string|resource|null $value Value of the property as a string
* or seekable stream. Not required for existence tests.
* If a seekable stream is provided, it is sent from its current
* posistion to its end, and the pointer is seeked back to its current
* position to its end, and the pointer is seeked back to its current
* position after sending.
* Non seekable streams, as well as all other types, are casted to a
* string.
* @param string $operator One of the OP_* constants.
* Describes the operation to perform.
*
*
* @return $this The query object.
*/
public function andWhere($name, $value = null, $operator = self::OP_EX)
@ -187,9 +192,9 @@ class Query
/**
* Sends the query over a communicator.
*
*
* @param Communicator $com The communicator to send the query over.
*
*
* @return int The number of bytes sent.
*/
public function send(Communicator $com)
@ -205,12 +210,12 @@ class Query
/**
* Sends the query over a communicator.
*
*
* The only difference with the non private equivalent is that this one does
* not do locking.
*
*
* @param Communicator $com The communicator to send the query over.
*
*
* @return int The number of bytes sent.
*/
private function _send(Communicator $com)
@ -239,20 +244,53 @@ class Query
return $bytes;
}
/**
* Verifies the query.
*
* Verifies the query against a communicator, i.e. whether the query
* could successfully be sent (assuming the connection is still opened).
*
* @param Communicator $com The Communicator to check against.
*
* @return $this The query object itself.
*
* @throws LengthException If the resulting length of an API word is not
* supported.
*/
public function verify(Communicator $com)
{
foreach ($this->words as $queryWord) {
list($predicate, $value) = $queryWord;
if (null === $value) {
$com::verifyLengthSupport(strlen('?' . $predicate));
} elseif (is_string($value)) {
$com::verifyLengthSupport(
strlen('?' . $predicate . '=' . $value)
);
} else {
$com::verifyLengthSupport(
strlen('?' . $predicate . '=') +
$com::seekableStreamLength($value)
);
}
}
return $this;
}
/**
* Adds a condition.
*
*
* @param string $name The name of the property to test.
* @param string|resource|null $value Value of the property as a string
* or seekable stream. Not required for existence tests.
* If a seekable stream is provided, it is sent from its current
* posistion to its end, and the pointer is seeked back to its current
* position to its end, and the pointer is seeked back to its current
* position after sending.
* Non seekable streams, as well as all other types, are casted to a
* string.
* @param string $operator One of the ACTION_* constants.
* Describes the operation to perform.
*
*
* @return $this The query object.
*/
protected function addWhere($name, $value, $operator)

Some files were not shown because too many files have changed in this diff Show More