Compare commits

..

318 Commits

Author SHA1 Message Date
slawkens
0342293847 Merge branch 'develop' into feature/settings 2023-08-05 20:52:35 +02:00
slawkens
c802d427eb Merge branch '0.9' into develop 2023-08-05 20:52:26 +02:00
slawkens
aacc120360 Remove deprecated utf8_decode 2023-08-05 20:52:01 +02:00
slawkens
757ec28028 Removed deprecated functions: utf8_encode & decode 2023-08-05 20:51:18 +02:00
slawkens
41fa695d8b Add some functions to compatibility layer of gesioraac 2023-08-05 20:50:33 +02:00
slawkens
b12c30982d Merge branch '0.9' into develop 2023-08-05 11:57:38 +02:00
slawkens
fcb2fc3002 Add .htaccess to .gitignore 2023-08-05 11:57:27 +02:00
slawkens
cb6e777c69 Move rest of config to settings
Remove config.php completely
Add new settings category: Game
Fix account_login_by_email
Min textarea size = 2 + adjusted automatically
2023-08-05 09:38:26 +02:00
slawkens
eca896954c Every setting needs to have default 2023-08-04 15:47:32 +02:00
slawkens
18bb23d969 Move create character blocked names down 2023-08-04 15:47:14 +02:00
slawkens
6890d531e5 add last_kills_limit to compat config 2023-07-30 14:39:56 +02:00
slawkens
3317dc48e8 Add database_hash setting 2023-07-30 14:39:37 +02:00
slawkens
8faa954a65 Merge branch 'develop' into feature/settings 2023-07-29 07:27:58 +02:00
slawkens
bb0e621308 Merge branch '0.9' into develop 2023-07-29 07:27:26 +02:00
slawkens
53221a9fd1 There is no more info. That never worked. 2023-07-29 07:27:07 +02:00
slawkens
0f9b217567 Fix default value displaying 2023-07-22 15:01:00 +02:00
slawkens
03ab4a5eef Move database settings to separate category 2023-07-22 14:55:10 +02:00
slawkens
c6ce60c5d1 Merge branch 'develop' into feature/settings 2023-07-22 14:46:38 +02:00
slawkens
d3b15a0a3e Fix multiple redirects error in browser 2023-07-22 14:46:28 +02:00
slawkens
23047aa608 Fix multiple redirects error in browser 2023-07-22 14:46:20 +02:00
slawkens
20dd49b1c5 Add new possibility: to deny saving setting if condition is not met 2023-07-22 14:37:57 +02:00
slawkens
3236f1aebb Merge branch 'develop' into feature/settings 2023-07-22 14:05:15 +02:00
slawkens
beff3e3aa6 Merge branch '0.9' into develop 2023-07-22 14:05:01 +02:00
slawkens
4a629b4418 Add protection, nothing important - thrown exception before 2023-07-22 14:03:57 +02:00
slawkens
4d61b0ef85 Add super fancy No Refresh saving with a toast 2023-07-22 13:58:20 +02:00
slawkens
b433615e68 New setting: donate_column + move donate config to settings 2023-07-22 13:03:43 +02:00
slawkens
a2fcb21b4f Improve character npc name check 2023-07-22 11:35:05 +02:00
slawkens
b05780529a fixes 2023-07-22 11:17:58 +02:00
slawkens
da19a34335 New create character checks configurable: block monsters & spells names 2023-07-22 11:10:07 +02:00
slawkens
ea21e27cdc Fix for install warning - min/max length 2023-07-22 11:03:59 +02:00
slawkens
aad175548a create character name config moved to settings 2023-07-22 10:57:42 +02:00
slawkens
d82e3a21e5 Fix google_analytics 2023-07-22 10:43:23 +02:00
slawkens
191137282b Create character blocked words (by @gpedro), just moved to settings 2023-07-22 10:33:20 +02:00
slawkens
d7e6545156 add mail_lost_account_interval 2023-07-22 10:32:31 +02:00
slawkens
957421a98c google_analytics_id 2023-07-22 10:31:41 +02:00
slawkens
f35aba10ed Merge branch 'develop' into feature/settings 2023-07-22 09:58:38 +02:00
Gabriel Pedro
3c3ddc4578 feat: custom words blocked (#190)
* Update config.php

* Update validator.php

* Update config.php
2023-07-22 09:54:03 +02:00
slawkens
81adeef01d add last_kills_limit + move shop 2023-07-22 09:52:06 +02:00
slawkens
b92b642078 Reword email settings + move two new settings 2023-07-22 09:48:44 +02:00
slawkens
baf9c9ea61 Enable script option 2023-07-22 09:35:54 +02:00
slawkens
0788dc8848 Merge branch '0.9' into develop 2023-07-21 21:22:41 +02:00
slawkens
5791d1e7f9 Update template.php 2023-07-21 21:22:23 +02:00
slawkens
a9cb017def Fix menu highlighting & opening 2023-07-21 21:22:13 +02:00
slawkens
8490b3b2a8 Update template.php 2023-07-21 21:22:06 +02:00
slawkens
f93e478326 Fix menu highlighting & opening 2023-07-21 21:21:59 +02:00
slawkens
d1a2ce25b2 Update 5-database.php 2023-07-21 20:43:45 +02:00
slawkens
94f8e3602c Merge branch 'develop' into feature/settings 2023-07-21 16:53:28 +02:00
slawkens
eaa9d6be43 Merge branch '0.9' into develop 2023-07-21 16:38:22 +02:00
slawkens
7588904372 Remove debugging var_dump 2023-07-21 16:38:10 +02:00
slawkens
712ca30293 Merge branch '0.9' into develop 2023-07-21 15:54:43 +02:00
slawkens
5fa4890b70 Add support for menu_default_color 2023-07-21 15:54:22 +02:00
slawkens
ca56b4f101 Fix menu cannot remove 2023-07-21 15:12:07 +02:00
slawkens
159f59242f Add more info into comment 2023-07-21 12:48:17 +02:00
slawkens
0765d3b9db Add more deprecated configs 2023-07-21 12:47:41 +02:00
slawkens
a82672c015 Merge branch 'develop' into feature/settings 2023-07-21 11:59:01 +02:00
slawkens
707aea18db Merge branch '0.9' into develop 2023-07-21 11:58:51 +02:00
slawkens
848c5c0887 Change default timezone 2023-07-21 11:58:18 +02:00
slawkens
571602e79c Fix create account, if account_create_character_create is enabled 2023-07-21 11:52:34 +02:00
slawkens
160ed3b237 Remove configs from previous commit 2023-07-21 11:39:25 +02:00
slawkens
1543dd864e Save config.php in Settings
Egg and hen problem solved :)
* Test database connection on save settings -> prevents from making website unusable if connection is wrong
* Test server_path -> same
There is no config.php anymore, just config.local.php, which can be edited manually and also from admin panel
2023-07-21 11:38:52 +02:00
slawkens
399f263b42 Rename variable 2023-07-21 06:05:33 +02:00
slawkens
1b2fd39ea7 Move news config to settings 2023-07-20 21:01:33 +02:00
slawkens
ed7daf9482 Move signature config to settings 2023-07-20 20:52:08 +02:00
slawkens
978090c8ae More config to settings: account_types, genders, highscores, admin 2023-07-20 20:24:07 +02:00
slawkens
ac3a6c36d5 Remove whitespaces 2023-07-20 18:13:06 +02:00
slawkens
a8a2c72381 Move status config to settings 2023-07-20 18:12:22 +02:00
slawkens
55a5ccdd1e Move forum config to settings 2023-07-20 16:36:59 +02:00
slawkens
a7b8ccaee2 Merge branch 'develop' into feature/settings 2023-07-20 14:24:46 +02:00
slawkens
e14df529c0 Revert some change 2023-07-19 22:40:39 +02:00
slawkens
9f67cab503 Add twig context for twig hook() function
Allows to use variables from template inside the hook file with usage of $context variable
2023-07-19 22:40:11 +02:00
slawkens
99c53c75f2 New guild hooks, for some upcoming big feature ;) 2023-07-19 22:26:47 +02:00
slawkens
df7c82c571 Fix highscores if there is only 1 record 2023-07-19 11:57:32 +02:00
slawkens
ddb093ec48 Fix highscores if there is only 1 record 2023-07-19 11:57:26 +02:00
slawkens
afa1adb90b Add settings.callbacks.get 2023-07-13 16:47:09 +02:00
slawkens
e83880653a Extract Settings:save function 2023-07-13 15:29:19 +02:00
slawkens
4af944a00b Change variable name 2023-07-13 15:20:13 +02:00
slawkens
48ceada956 Rename team_* variables + add to deprecated 2023-07-13 15:13:15 +02:00
slawkens
e7ef1679a0 nothing important 2023-07-13 13:04:31 +02:00
slawkens
228b2d071b Add: show_if - account_mail_verify 2023-07-13 13:04:22 +02:00
slawkens
1ea9a76ea9 Fix: check on page load if radio button is checked 2023-07-13 13:03:52 +02:00
slawkens
c7c8ff266b Hide section title on show_if 2023-07-13 12:10:07 +02:00
slawkens
b062c424d8 Merge branch 'develop' into feature/settings 2023-07-13 11:08:48 +02:00
slawkens
714476bf29 Merge branch '0.9' into develop 2023-07-13 11:08:30 +02:00
slawkens
e49690b52b Thanks @anyeor for previous fix 2023-07-13 11:03:37 +02:00
slawkens
f9d35b719b Fix: cannot create topic on this board (check wasn't working) 2023-07-11 11:17:34 +02:00
slawkens
c886384f2c Merge branch 'develop' into feature/settings 2023-07-08 19:16:22 +02:00
slawkens
a61cd43c3c Forum: nothing important, just formatting 2023-07-07 17:43:28 +02:00
slawkens
6d1b3235d2 Merge branch '0.9' into develop 2023-07-07 17:29:02 +02:00
slawkens
e7e9d8e3b9 Shorten some forum code about length 2023-07-07 17:20:50 +02:00
slawkens
8cf0e80019 Forum: better error messages (Suggested by @anyeor) 2023-07-07 17:20:23 +02:00
slawkens
c392fa7272 Fix guild description on guilds page 2023-07-02 13:48:57 +02:00
slawkens
082884baa0 Fix guild description not shown 2023-07-02 00:26:44 +02:00
slawkens
3a31a0326c Fix guild description not shown 2023-07-02 00:26:33 +02:00
slawkens
2d561f267d Fix guild description not shown on guilds page 2023-06-30 19:52:20 +02:00
slawkens
5eafff737a Guilds & Characters: Use CSS word-break: break-all instead of PHP wordwrap
Suggested by @anyeor
2023-06-30 19:52:05 +02:00
slawkens
8cf4d0cb0f Add word-break on forum thread & reply
When someone inserts long word, is will break into multiple lines
2023-06-30 19:43:36 +02:00
slawkens
d1953470d9 Add word-break on forum thread & reply
When someone inserts long word, is will break into multiple lines
2023-06-30 19:43:31 +02:00
slawkens
3a52f2c403 nothing important 2023-06-30 17:35:39 +02:00
slawkens
ac40922957 Merge branch '0.9' into develop 2023-06-30 17:32:40 +02:00
slawkens
5aed9ee1a4 Forum: Fix quote and edit post buttons not being shown 2023-06-30 17:30:29 +02:00
slawkens
8318169c39 Fix twig exception thrown when player does not exist 2023-06-30 17:30:01 +02:00
slawkens
ad00cf3fc3 Fix BASE_DIR when accessing /tools 2023-06-30 17:29:49 +02:00
slawkens
3ff7b21287 Move <base href> above, so it works, thanks @Leesneaks 2023-06-30 17:28:34 +02:00
slawkens
36fbae850d Revert "<base> is not working properly, use full URL instead"
This reverts commit fa015b8d39.
2023-06-30 17:28:19 +02:00
slawkens
24ff5684cd More changes to deleted characters (Account, guilds)
Account: Cannot change name, comment, gender
+ Cannot be deleted if owns a guild
Guilds: Cannot create, cannot be invited, cannot accept invite, cannot be passed leadership to
2023-06-30 17:27:31 +02:00
slawkens
aab62fb724 Important fix: Not allow create char if limit is exceeded (by @anyeor )
Could have been used to spam database, now it doesn't ignore deleted characters

He is not my brother :P Just same last name
2023-06-30 17:25:32 +02:00
slawkens
a810890614 code formatting 2023-06-30 17:25:21 +02:00
slawkens
a3bfdc1ec8 small adjustments 2023-06-25 08:54:36 +02:00
slawkens
a7dc719934 small adjustments 2023-06-25 08:54:22 +02:00
slawkens
74433303fb Better Gesior support 2023-06-23 21:52:23 +02:00
slawkens
30d62bda3b Better Gesior support 2023-06-23 21:52:11 +02:00
slawkens
cc7703766e Patching some changes from master 2023-06-19 08:05:58 +02:00
SRNT-GG
9d664d3577 WIP - Removing unneccessary closing tags to prevent potential issues. (#223)
* Part 1

Removing closing tags when no HTML or other output comes after the last PHP codeblock.

* Further removals

* nothing

---------

Co-authored-by: slawkens <slawkens@gmail.com>
2023-06-15 21:08:20 +02:00
SRNT-GG
76bfab1303 WIP - Removing unneccessary closing tags to prevent potential issues. (#223)
* Part 1

Removing closing tags when no HTML or other output comes after the last PHP codeblock.

* Further removals

* nothing

---------

Co-authored-by: slawkens <slawkens@gmail.com>
2023-06-15 21:06:22 +02:00
slawkens
7d2fc48437 Fix links to edit/delete/hide directly from page 2023-06-11 18:57:57 +02:00
slawkens
171c114b0f Fix links to edit/delete/hide directly from page 2023-06-11 18:57:52 +02:00
slawkens
b1d2ac34a2 Update branch name 2023-06-03 18:51:57 +02:00
slawkens
c7ce87c4b6 do not report if CI test 2 2023-06-03 18:50:43 +02:00
slawkens
4e22c42b10 test dump env 2023-06-03 18:50:34 +02:00
slawkens
eabe789bbb Disable reporting on CI 2023-06-03 18:50:22 +02:00
slawkens
aa1403480c Update to 0.10.0-dev 2023-06-03 18:50:14 +02:00
slawkens
91c8f1f5bc do not report if CI test 2 2023-06-03 18:41:16 +02:00
slawkens
b421bf3931 test dump env 2023-06-03 18:38:30 +02:00
slawkens
6e6f4679f4 Disable reporting on CI 2023-06-03 12:24:18 +02:00
slawkens
5bb3e57b7b Rename to .htaccess.dist
Causes problems on default setup
2023-06-03 09:04:30 +02:00
slawkens
17221f5369 Rename to .htaccess.dist
Causes problems on default setup
2023-06-03 09:04:24 +02:00
slawkens
98d4d3fcf0 Install composer deps with --no-dev 2023-06-03 06:47:16 +02:00
slawkens
82092338d6 Install composer deps with --no-dev 2023-06-03 06:47:06 +02:00
slawkens
9868b41a61 <base> is not working properly, use full URL instead 2023-06-02 15:24:14 +02:00
slawkens
c247789adf <base> is not working properly, use full URL instead 2023-06-02 15:24:10 +02:00
slawkens
48822b6561 Use Whoops only if installed, otherwise use myaac exception handler 2023-06-02 15:20:13 +02:00
slawkens
cd22f8def5 Use Whoops only if installed, otherwise use myaac exception handler 2023-06-02 15:20:07 +02:00
slawkens
0f30ebbcea change branch name in release.sh 2023-06-02 08:05:13 +02:00
slawkens
1a2e46f09b Ignore cypress in git-export + install composer deps on release 2023-06-02 08:04:17 +02:00
slawkens
52ac011556 Ignore cypress in git-export + install composer deps on release 2023-06-02 08:04:13 +02:00
slawkens
f34e5f2ac0 Release 0.9.0-alpha 2023-06-02 06:37:25 +02:00
slawkens
ca8db22639 Better news back button 2023-06-01 11:23:36 +02:00
slawkens
1846bf5255 Change button style (characters - view)
was causing issues in other templates
2023-06-01 09:57:27 +02:00
slawkens
dce0ac2f8f nothing important 2023-05-29 10:09:21 +02:00
slawkens
9cc60983d0 Update CHANGELOG.md 2023-05-29 08:55:41 +02:00
slawkens
7c2c88f780 Add Whoops exception handler (nicer debug info in dev mode)
On production = no errors
2023-05-29 08:55:26 +02:00
slawkens
7690811da3 Update install.php 2023-05-29 08:46:07 +02:00
slawkens
7dc2e404ed Fixed many links to admin panel, if ADMIN_PANEL_FOLDER is changed 2023-05-29 00:00:34 +02:00
slawkens
080ab56ea9 Update functions.php 2023-05-28 23:56:35 +02:00
slawkens
83915f080c Fixed when page is hidden 2023-05-28 23:56:26 +02:00
slawkens
2841f17729 fix images base url, uploaded by tinymce 2023-05-28 23:54:36 +02:00
slawkens
0187ba4938 New hook: HOOK_ACCOUNT_CREATE_AFTER_PASSWORD
for password strength meter
2023-05-26 22:49:24 +02:00
slawkens
bedfc0a2e0 Update bootstrap to v5.2.3 in install 2023-05-26 17:50:38 +02:00
slawkens
ea08c04963 nothing important 2023-05-26 16:49:28 +02:00
slawkens
067f2af3e5 Wait for success, then screenshot 2023-05-26 16:15:39 +02:00
slawkens
8d98306f8e optimize workflow 2023-05-26 16:12:50 +02:00
slawkens
09a045334c Update cypress.yml 2023-05-26 14:53:33 +02:00
slawkens
bc8e5fc144 Update .gitattributes 2023-05-26 14:51:33 +02:00
slawkens
77e0d28a9d Delete .travis.yml 2023-05-26 14:09:10 +02:00
slawkens
480a054f0c Fixed ADMIN_PANEL_FOLDER, can be 100% custom now 2023-05-26 14:04:52 +02:00
slawkens
26c895d475 Block access to some files [skip ci] 2023-05-26 13:51:05 +02:00
slawkens
5cbb55cfb1 Upload videos too 2023-05-26 13:11:39 +02:00
slawkens
dcb9506a1b admin is already created during install 2023-05-26 13:10:14 +02:00
slawkens
2acec4df12 bring back matrix, wasn't the issue 2023-05-26 13:05:35 +02:00
slawkens
4bd761c726 remove typo 2023-05-26 13:05:29 +02:00
slawkens
2f732b8411 wrong position 2023-05-26 13:00:26 +02:00
slawkens
5aa02055bf fix path 2023-05-26 12:58:28 +02:00
slawkens
6ed15565c8 Import TFS Schema 2023-05-26 12:55:08 +02:00
slawkens
77a2c55c87 Update cypress.yml 2023-05-26 12:50:37 +02:00
slawkens
4a9fa01eb7 Update cypress.yml 2023-05-26 12:49:11 +02:00
slawkens
bd031d8980 create database manually 2023-05-26 12:46:03 +02:00
slawkens
b76a037a94 last try to fix mysql 2023-05-26 12:22:06 +02:00
slawkens
e71daa2520 Update cypress.yml 2023-05-26 12:18:51 +02:00
slawkens
f372aeb067 Update cypress.yml 2023-05-26 12:13:23 +02:00
slawkens
ef37bbcb81 Update cypress.yml 2023-05-26 11:49:24 +02:00
slawkens
944457463e Update cypress.yml 2023-05-26 11:01:44 +02:00
slawkens
6f7f25bb46 Update cypress.yml 2023-05-26 10:54:57 +02:00
slawkens
d60d7f2250 test 5.7 mysql 2023-05-26 10:48:47 +02:00
slawkens
2b8c4b3eca test connect with root 2023-05-26 10:44:02 +02:00
slawkens
7039bda359 Update cypress.yml 2023-05-26 10:38:30 +02:00
slawkens
d346a8f73f Update cypress.yml 2023-05-26 10:27:38 +02:00
slawkens
523f2dee7c mysqlPass 2023-05-26 10:21:05 +02:00
slawkens
b33e39491b MySQL needs to be started manually 2023-05-26 10:19:13 +02:00
slawkens
317ebf4387 Update cypress.yml 2023-05-26 10:12:28 +02:00
slawkens
31ba780099 Update cypress.yml 2023-05-26 10:08:51 +02:00
slawkens
d1b30619e2 fix path to config.lua 2023-05-26 09:56:49 +02:00
slawkens
3fab52296a Update cypress.yml 2023-05-26 09:52:11 +02:00
slawkens
a6e109799a Update cypress.yml 2023-05-26 09:48:55 +02:00
slawkens
80af2cd691 cypress-workflow: config.lua move + replace values 2023-05-26 09:47:39 +02:00
slawkens
d911b55e25 Update cypress.yml 2023-05-26 09:24:49 +02:00
slawkens
eb73fc4538 try fix cypress 2023-05-26 09:19:46 +02:00
slawkens
75f77ec7a3 Fix: Run PHP Server 2023-05-26 09:11:04 +02:00
slawkens
a1d969bbfd fix env 2023-05-26 09:00:21 +02:00
slawkens
11f1ad6d76 fix path 2023-05-26 08:53:49 +02:00
slawkens
7facf0adad fix branch 2023-05-26 08:52:05 +02:00
slawkens
2b739c2b40 Add Cypress workflow 2023-05-26 08:49:28 +02:00
slawkens
269ae323e0 Add Cypress tests: install + create account 2023-05-26 08:49:04 +02:00
slawkens
0d0e5812dd Change step to $_REQUEST 2023-05-26 08:36:20 +02:00
slawkens
61c2661377 Fix warning when no header language set 2023-05-25 11:39:45 +02:00
slawkens
de710dff94 Add cypress/e2e/2-advanced-examples to .gitignore 2023-05-25 11:39:02 +02:00
slawkens
8c524171fb Add cypress.env.json to .gitignore 2023-05-25 09:31:29 +02:00
slawkens
946d24690c Update common.php 2023-05-25 09:30:44 +02:00
slawkens
250d89482e guild_management: show_if 2023-05-17 06:12:10 +02:00
slawkens
2f8ee7a7eb Add new function: only_if, to hide fields when they are not enabled [WIP]
Not fully finished yet
2023-05-17 06:07:52 +02:00
slawkens
7aff4557a6 Lets call it settings.name instead 2023-05-16 14:17:21 +02:00
slawkens
481ba5a30f More detailed error message in settings 2023-05-16 12:47:58 +02:00
slawkens
52dc459704 Better boolean detection 2023-05-16 12:46:45 +02:00
slawkens
dc3477d68d Nothing important 2023-05-16 12:46:02 +02:00
slawkens
24ab125d28 Add Settings menu, including all plugins with settings
One change included in previous commit, due to missclick
2023-05-16 11:44:13 +02:00
slawkens
939508e799 Re-enable plugin if disabled and already installed 2023-05-16 11:41:44 +02:00
slawkens
433ccff851 Add min, max, step to number field option 2023-05-16 11:37:38 +02:00
slawkens
7929967ddc [WIP] More work on settings
Move more config to settings (mainly mail_* + some other)
Remove mail_admin, wasnt used anywhere
Add return type to some functions
Add Twig settings(key) function
Possibility to save setting to db
2023-05-15 23:14:13 +02:00
slawkens
449fc2c1cf Fix path 2023-05-15 17:05:30 +02:00
slawkens
bd0570ac30 Rename 2023-05-15 17:00:41 +02:00
slawkens
bf137189c5 Update CHANGELOG.md 2023-05-15 00:22:51 +02:00
slawkens
1fa6788310 [WIP] Some work on settings
Add hidden settings
New method: parse, to parse settings from array
Move base html to twig template
Remove vocation loading from .xml, instead use predefined voc names
2023-05-15 00:22:27 +02:00
slawkens
44d5d7ae64 Merge branch 'develop' into feature/settings 2023-05-13 12:57:11 +02:00
slawkens
da4e18cb69 Fixes to routing 2023-05-13 12:49:17 +02:00
slawkens
7723f87bbf Merge branch 'develop' into feature/settings 2023-05-13 12:06:36 +02:00
slawkens
85769c1439 Empty URL = show news 2023-05-13 11:34:51 +02:00
slawkens
034c369ddb Update plugins.php 2023-05-09 21:54:00 +02:00
slawkens
4e5a0a6134 Execute migrations just after db connect 2023-05-09 21:53:55 +02:00
slawkens
3067b79363 Add 36th migration for settings table 2023-05-09 21:53:12 +02:00
slawkens
40c00a1434 Merge branch 'develop' into feature/settings 2023-05-08 13:05:22 +02:00
slawkens
4d3ad4b6b9 Update jQuery to v3.6.4 and jQuery UI to v1.13.2 2023-04-19 23:15:28 +02:00
slawkens
e900a62e75 Print more info if character cannot be created 2023-04-12 12:52:14 +02:00
slawkens
c3969364aa Fix default news route if friendly_urls is disabled 2023-04-01 22:13:24 +02:00
slawkens
e9df9f10dc Add check for player_deaths columns 2023-04-01 15:11:12 +02:00
slawkens
f78f5b5361 OK, so phplint is working! 2023-03-31 10:23:10 +02:00
slawkens
c061438a35 test phplint 2023-03-31 10:21:27 +02:00
slawkens
8441dbe007 Add actions/checkout@v3 2023-03-31 10:18:48 +02:00
slawkens
e21a741a78 Use overtrue/phplint@8.2 for phplint 2023-03-31 10:17:21 +02:00
slawkens
955f437e6c test github actions 2023-03-31 09:35:05 +02:00
Matheus Collier
fd419076c2 [UPDATE] Adding monster looks to db (#220)
* [UPDATE] Adding monster looks to db

* small adjustments

add into schema.sql + change position in table

* add DEFAULT = ''

---------

Co-authored-by: slawkens <slawkens@gmail.com>
2023-03-31 09:04:13 +02:00
slawkens
7569536d56 Fix when server uses another items serializer 2023-03-26 00:27:16 +01:00
slawkens
3a6102900f fix small bug on install - please fill all input 2023-03-26 00:24:57 +01:00
slawkens
6dbc694409 Do not allow continue install when there is no server database imported 2023-03-26 00:23:50 +01:00
slawkens
7a3dcc4dc6 small fixes to account_login_by_email 2023-03-25 19:17:55 +01:00
slawkens
23393b5d3e Fix cannot go forward when config.local.php cannot be saved 2023-03-22 09:15:32 +01:00
slawkens
863f3ad510 Change from warning to error (config.local.php save error) 2023-03-22 09:15:05 +01:00
slawkens
e6d86ca280 plugins folder should be accessible from public 2023-03-15 17:51:24 +01:00
slawkens
c22e25e3d2 Update nginx-sample.conf 2023-03-06 08:26:29 +01:00
slawkens
52ffb195ec fix account/lost links 2023-02-19 08:01:02 +01:00
slawkens
92a51af638 Fix account number show 2023-02-19 07:31:51 +01:00
slawkens
d7a9158cf2 Update routes.php 2023-02-18 21:45:09 +01:00
slawkens
f0f84090d2 fix creatures post route, back button 2023-02-18 21:26:22 +01:00
slawkens
9d78a3b5cf more php 8.x compatibility 2023-02-18 21:22:54 +01:00
slawkens
2fc163af5a Update tables.headline.html.twig 2023-02-18 21:12:08 +01:00
slawkens
10be98e371 Create account.back_button.html.twig 2023-02-18 21:11:55 +01:00
slawkens
e0eb083e44 new buttons code for tibiacom template, can create button with any text 2023-02-18 21:11:35 +01:00
slawkens
e17cd78153 fix player save on tfs 1.5 with new ipv6 2023-02-18 20:57:44 +01:00
slawkens
0015f511f8 Preparation v0.9.0-alpha release (Updated CHANGELOG) 2023-02-18 13:05:53 +01:00
slawkens
f0f71c9f85 fixes 2023-02-18 09:33:04 +01:00
slawkens
0002543cca feature: Cache::remember($key, $ttl, $callback) + example usage 2023-02-18 08:53:42 +01:00
slawkens
c1096415aa Add check for tables in admin panel 2023-02-18 07:15:11 +01:00
slawkens
6625768228 Remove accounts.blocked 2023-02-18 07:14:51 +01:00
slawkens
a27f601fe8 feature: new functions: getGuildNameById + geGuildLogoById 2023-02-17 20:05:43 +01:00
slawkens
72a877d9ca Show more info about bot 2023-02-17 19:06:13 +01:00
slawkens
b7ba09a551 small fix 2023-02-17 18:48:01 +01:00
slawkens
a98cb66c53 feature: visitors counter shows now user browser, and also if its bot 2023-02-17 18:41:25 +01:00
slawkens
6785ecad1d Ignore case on plugin route method 2023-02-17 17:54:38 +01:00
slawkens
937af536b6 patch from master - long player ip caused error 2023-02-17 17:17:19 +01:00
slawkens
5487314230 preparation for guild wars 2023-02-17 17:10:01 +01:00
slawkens
51e9bb2a7f set default for optional parameter (twig functions) 2023-02-17 17:09:38 +01:00
slawkens
376bb981ae string is also spaces, lets admin that 2023-02-17 13:35:05 +01:00
slawkens
ed9d78d2f3 Fixes for config.account_create_auto_login 2023-02-17 13:15:13 +01:00
slawkens
3c4e50dbda formatting 2023-02-16 11:24:19 +01:00
slawkens
523f9dd95a New hook: HOOK_ACCOUNT_CHANGE_PASSWORD_POST 2023-02-16 11:24:00 +01:00
slawkens
a43742c8b1 rename hook 2023-02-16 11:22:12 +01:00
slawkens
c49e4fd63d add hook for disable accounts edit for next.my-aac.org (security) 2023-02-16 11:07:00 +01:00
slawkens
905cce7021 Update mailer.php 2023-02-16 10:53:15 +01:00
slawkens
7a49b5dedc Disable add php pages in admin panel for security. Option to disable plugins upload 2023-02-16 10:53:06 +01:00
slawkens
3a2870a6bb 760 is correct permission 2023-02-16 10:06:08 +01:00
slawkens
9a475f2c57 fix for othire where size is saved in houses.tiles 2023-02-16 08:44:17 +01:00
slawkens
58598742e8 change spaces to tabs 2023-02-16 08:43:21 +01:00
slawkens
d04e44f52f add info which plugin is going to be uninstalled 2023-02-16 07:21:38 +01:00
slawkens
c7ec1f44e9 Option to enable/disable plugin by renaming file + cleanup
new function: getAllPluginsJson
removeComments removed - json doesnt allow for comments anyway
2023-02-16 06:57:46 +01:00
slawkens
3ed9a5d3d8 add hook: HOOK_GUILDS_AFTER_INVITED_CHARACTERS, for guild wars 2023-02-16 05:16:22 +01:00
slawkens
61285b6b8c small fix to routes with string 2023-02-15 17:32:48 +01:00
slawkens
d17c547bca add $params as optional parameter to hook twig function 2023-02-15 17:12:56 +01:00
slawkens
7bc20b0993 change spaces to tabs 2023-02-15 17:12:30 +01:00
slawkens
6c4b3dea96 Delete autoload.php 2023-02-15 08:06:57 +01:00
slawkens
6ae1bf5814 Add missing header to some files 2023-02-15 08:06:08 +01:00
slawkens
8503135ce0 add some notice 2023-02-14 23:22:17 +01:00
slawkens
590fe0762d small fixes 2023-02-14 22:03:22 +01:00
slawkens
d565b90736 Update accounts.php 2023-02-14 21:51:54 +01:00
slawkens
c88156802a fix pages not found 2023-02-14 21:51:46 +01:00
slawkens
7d8dbcbde7 fixes to account number part 3 2023-02-14 19:40:55 +01:00
slawkens
66ec66b291 Allow TinyMCE to resize horizontally and vertically 2023-02-14 18:47:56 +01:00
slawkens
fc0eb0e793 add missing hook 2023-02-14 18:40:46 +01:00
slawkens
ed7e9e1eae fixes to account number part 2 2023-02-14 18:40:31 +01:00
slawkens
8985917a96 Fixes to account number 2023-02-14 18:28:31 +01:00
slawkens
c72bc39aac Update .gitignore 2023-02-14 16:36:25 +01:00
slawkens
b29c5c6aa6 fix typo 2023-02-14 16:10:06 +01:00
slawkens
07486762dc Add categories in tabs, move more settings, revert back getPluginSettings
Categories and sections are now not numbered
Remove example settings plugin
2023-02-14 16:03:22 +01:00
slawkens
50fe38d5fc add missing hook 2023-02-08 15:22:14 +01:00
slawkens
5d48a69649 php 8 compatibility 2023-02-08 15:22:03 +01:00
slawkens
1345ad97d5 add settings migration 2023-02-08 15:03:40 +01:00
slawkens
1340b8e63e Merge branch 'develop' into feature/settings 2023-02-08 15:02:56 +01:00
slawkens
3a3411c117 New hooks for admin page, for head, body, and before_page
+move LOGIN_POST to correct place
2023-02-07 16:27:02 +01:00
slawkens
1166ddfe87 Remove google recaptcha from code
will be included as plugin. This allows for custom recaptcha's
2023-02-07 15:20:24 +01:00
slawkens
574e361f90 fix warning 2023-02-07 12:03:18 +01:00
slawkens
f3745a2752 Feature/new router (#165)
* Remove unneeded escape

* Fix guild back buttons (change logo & motd)

* small adjustment in news.php

* Fix create character when admin (any case is allowed now)

* Fix forum table style (boards & thread view)

* Small improvement to plugins.enabled check

* [WIP] nikic/fast-route implementation

I will describe it more in Pull Request

* Optimisations & fixes.

* Fix path - should not be absolute

* Add PLUGINS to Twig path

* Don't hide "Install Plugin" Box by default

* Update package-lock.json

* nothing important, just early exit & fixes

Fix creature display

* fix premium_ends_at for tfs 1.3+

* Move pages

* Move pages tbc

* $db->select: make $where parameter optional, allows to get all records

* Add some error box to error

* fix parse error

* Rewriting the router v2

To be more flexible

* small fixes

* fix & add admin icons

* Move mass_* pages to correct folder

* fix logout hook 2

* Delete accountmanagement.php

* This code wasn't used

* Add missing var

* Add redirect_from && redirect_to to router options

+ Also add * for all methods shortcut

* Remove comments

Not allowed in normal json

* Allow admin pages included into plugins dir

* block access to some files

* Fix admin logout

* Fix #178

* feature: mail confirmed reward

Suggested by @EPuncker

# Conflicts:
#	system/hooks.php

* remove misleading comment

* adjust required version according to composer.json

* fix duplicated word

* Adjustments & fixed to mass actions

* Add password confirm, and change text type to password

* Add list of Open Source Software MyAAC is using

* Fix signature

* Show First, Second instead of numbers

* fix base dir detection

* fix double ACTION define + undefined URI in template

* new function> escapeHtml + fix css in admin menus

* fix changelog add

* fix news adding, rename const to NEWS_*

* Add verify to pages, add messages, limits, fix add

* fix "Please fill all input"

* add required input to admin pages

* shorten some expressions with ??

* shorten code + fix conversion (int)

* Move account_types to config, account.web_flags to common.php

* Update example.json

* feature: router aliases

* shorten some code + const convert

* remove wrong char

* fix signature on custom basedir

* fix: mass teleport position validation (#214)

* fix: mass teleport position validation

* fix: max position

* Fix execute in CLI

* fix warning in reload cache in dev mode

* Configurable admin panel folder

* feature: plugin require more options with comma

* $config_account_salt -> USE_ACCOUNT_SALT

* fix forum show_thread

* Update show_thread.php

---------

Co-authored-by: Gabriel Pedro <gpedro@users.noreply.github.com>
2023-02-07 11:41:05 +01:00
slawkens
4dbcad5ad5 Merge branch 'develop' into feature/settings 2021-06-08 22:06:21 +02:00
slawkens
6035d05d65 Update 33.php 2021-03-08 14:44:09 +01:00
slawkens
dfd78b9735 Merge branch 'develop' into feature/settings 2021-03-05 10:10:51 +01:00
slawkens
6edc90c82c Add email + password fields as type 2020-06-20 08:48:31 +02:00
slawkens
084e191b28 Add Sections + Add setting($key) function
Reorganisation
2020-06-09 23:48:31 +02:00
slawkens
96068d003b Add Settings menu 2020-06-09 01:44:13 +02:00
slawkens
a6e20fa62c Change name to settings 2020-06-09 01:43:07 +02:00
slawkens
df0ad6e277 Change options.php to settings.php 2020-06-09 01:40:28 +02:00
slawkens
fa0de1c413 Settings [WIP]
New Settings class
New Plugins::load() method
Move config.php to settings.php
MyAAC Settings will have plugin_name = 'core'
Add compat_config.php
2020-06-09 01:39:55 +02:00
slawkens
909bfffb51 Move $menus to menus.php
Also fix active link when menu item has subpage
2020-06-09 01:36:07 +02:00
slawkens
7b1aed7a94 Remove useless title_separator from config 2020-06-09 00:48:19 +02:00
slawkens
78ba282a1b Add $member var annotation 2020-06-06 17:10:34 +02:00
slawkens
5362c4970f Add $limit parameter to $db->select method 2020-06-06 17:08:41 +02:00
slawkens
90cab6d3ee New myaac_settings table 2020-06-06 09:26:17 +02:00
slawkens
e462348db0 Merge branch 'develop' into feature/settings 2020-06-06 09:17:23 +02:00
slawkens
69bbb375e2 Merge branch 'develop' into plugin-options 2020-06-06 08:00:05 +02:00
slawkens
d89d8cdf8d Add Settings Class 2020-06-06 07:55:26 +02:00
slawkens
cdef0796a7 Rename to settings.php 2020-06-06 07:52:31 +02:00
slawkens
7469f13254 Forgot the plugin example of options 2020-05-15 00:06:03 +02:00
slawkens
89d82e5117 New admin panel Pages: Options + Config [WIP] 2020-05-14 23:59:37 +02:00
258 changed files with 7652 additions and 3085 deletions

6
.gitattributes vendored
View File

@@ -3,8 +3,12 @@
.gitignore export-ignore .gitignore export-ignore
.github export-ignore .github export-ignore
.editorconfig export-ignore .editorconfig export-ignore
.travis.yml export-ignore
_config.yml export-ignore _config.yml export-ignore
release.sh export-ignore release.sh export-ignore
# cypress
cypress export-ignore
cypress.config.js export-ignore
cypress.env.json
*.sh text eol=lf *.sh text eol=lf

120
.github/workflows/cypress.yml vendored Normal file
View File

@@ -0,0 +1,120 @@
name: Cypress
on:
pull_request:
branches: [develop]
push:
branches: [develop]
jobs:
cypress:
runs-on: ubuntu-latest
services:
mysql:
image: mysql:8.0
env:
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: myaac
MYSQL_USER: myaac
MYSQL_PASSWORD: myaac
ports:
- 3306/tcp
options: --health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=3
strategy:
fail-fast: false
matrix:
php-versions: [ '7.4', '8.0', '8.1' ]
name: MyAAC on PHP ${{ matrix.php-versions }}
steps:
- name: 📌 MySQL Start & init & show db
run: |
sudo /etc/init.d/mysql start
mysql -e 'CREATE DATABASE myaac;' -uroot -proot
mysql -e "SHOW DATABASES" -uroot -proot
- name: Checkout MyAAC
uses: actions/checkout@v3
with:
ref: 0.9
- name: Checkout TFS
uses: actions/checkout@v3
with:
repository: otland/forgottenserver
ref: 1.4
path: tfs
- name: Import TFS Schema
run: |
mysql -uroot -proot myaac < tfs/schema.sql
- name: Rename config.lua
run: mv tfs/config.lua.dist tfs/config.lua
- name: Replace mysqlUser
uses: jacobtomlinson/gha-find-replace@v2
with:
find: 'mysqlUser = "forgottenserver"'
replace: 'mysqlUser = "root"'
regex: false
include: 'tfs/config.lua'
- name: Replace mysqlPass
uses: jacobtomlinson/gha-find-replace@v2
with:
find: 'mysqlPass = ""'
replace: 'mysqlPass = "root"'
regex: false
include: 'tfs/config.lua'
- name: Replace mysqlDatabase
uses: jacobtomlinson/gha-find-replace@v2
with:
find: 'mysqlDatabase = "forgottenserver"'
replace: 'mysqlDatabase = "myaac"'
regex: false
include: 'tfs/config.lua'
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php-versions }}
extensions: mbstring, dom, fileinfo, mysql, json, xml, pdo, pdo_mysql
- name: Get composer cache directory
id: composer-cache
run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT
- name: Cache composer dependencies
uses: actions/cache@v3
with:
path: ${{ steps.composer-cache.outputs.dir }}
# Use composer.json for key, if composer.lock is not committed.
# key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }}
key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }}
restore-keys: ${{ runner.os }}-composer-
- name: Install Composer dependencies
run: composer install --no-progress --prefer-dist --optimize-autoloader
- name: Run PHP server
run: nohup php -S localhost:8080 > php.log 2>&1 &
- name: Cypress Run
uses: cypress-io/github-action@v5
env:
CYPRESS_URL: http://localhost:8080
CYPRESS_SERVER_PATH: /home/runner/work/myaac/myaac/tfs
- name: Save screenshots
uses: actions/upload-artifact@v3
if: always()
with:
name: cypress-screenshots
path: cypress/screenshots
- name: Upload Cypress Videos
uses: actions/upload-artifact@v3
if: always()
with:
name: cypress-videos
path: cypress/videos

View File

@@ -1,13 +1,16 @@
name: PHP Linting name: PHP Linting
on: on:
pull_request: pull_request:
branches: [master, develop] branches: [develop]
push: push:
branches: [master] branches: [develop]
jobs: jobs:
phplint: phplint:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v1 - uses: actions/checkout@v3
- uses: michaelw90/PHP-Lint@master - uses: overtrue/phplint@8.2
with:
path: .
options: --exclude=*.log

7
.gitignore vendored
View File

@@ -2,6 +2,9 @@ Thumbs.db
.DS_Store .DS_Store
.idea .idea
#
/.htaccess
# composer # composer
composer.lock composer.lock
vendor vendor
@@ -9,6 +12,10 @@ vendor
# npm # npm
node_modules node_modules
# cypress
cypress.env.json
cypress/e2e/2-advanced-examples
# created by release.sh # created by release.sh
releases releases
tmp tmp

View File

@@ -6,6 +6,10 @@
Options -MultiViews Options -MultiViews
</IfModule> </IfModule>
<FilesMatch "^(CHANGELOG\.md|README\.md|composer\.json|composer\.lock|package\.json|package-lock\.json|cypress\.env\.json)$">
Require all denied
</FilesMatch>
<IfModule mod_rewrite.c> <IfModule mod_rewrite.c>
RewriteEngine On RewriteEngine On

View File

@@ -1,18 +0,0 @@
language: php
php:
- 7.1
- 7.2
- 7.3
- 7.4
- 8.0
cache:
directories:
- $HOME/.composer/cache
before_script:
- composer require php-parallel-lint/php-parallel-lint --no-suggest --no-progress --no-interaction --no-ansi --quiet --optimize-autoloader
script:
- php vendor/bin/parallel-lint --no-progress --no-colors --exclude vendor --exclude "system/libs/pot/OTS_DB_PDOQuery.php" .

View File

@@ -1,9 +1,55 @@
# Changelog # Changelog
## [0.9.0 - x.x.2020] ## [0.9.0-alpha - 02.06.2023]
Minimum PHP version for this release is 7.2.5.
### Added ### Added
* reworked Admin Panel (@Leesneaks, @gpedro, @slawkens)
* updated to Bootstrap v4
* new Menu
* new Dashboard: statistics, server status
* new Admin Bar showed on top when admin logged in
* new page: Server Data, to reload server data
* new pages: mass account & teleport tools
* changelogs editor
* revised Accounts & Players editors
* option to add/modify menus with plugins
* option to enable/disable plugins
* better, updated TinyMCE editor (v6.x)
* with option to upload images
* list of open source libraries used in project
* brand new charming installation page (by @fernandomatos)
* using Bootstrap
* new pages router: nikic/fast-route, allowing for better customisation
* Guild Wars support (available as plugin)
* support for login and create account only by email (configurable)
* with no need for account name
* Google ReCAPTCHA v3 support (available as plugin)
* automatically load towns names from .OTBM file
* support for Account Number
* suggest account number option
* many new functions, hooks and configurables
* better Exception Handler (Whoops - https://github.com/filp/whoops)
* add Cypress testing
### Changed ### Changed
* Composer is now used for external libraries like: Twig, PHPMailer, fast-route etc.
* mail support is disabled on fresh install, can be manually enabled by user
* disable add php pages in admin panel for security. Option to disable plugins upload
* visitors counter shows now user browser, and also if its bot
* changes in required and optional PHP extensions
* reworked Pages:
* Bans
* works now for TFS 1.x
* Highscores
* frags works for TFS 1.x
* cached
* creatures
* moved pages to Twig:
* experience stages
* update player_deaths entries on name change
* change_password email to be more informal
### Fixed ### Fixed
* hundrets of bug fixes, mostly patched from 0.8, so it makes no sense writing them again here

View File

@@ -1,3 +1,3 @@
* Gesior.pl (2007 - 2008) * Gesior.pl (2007 - 2008)
* Slawkens (2009 - 2022) * Slawkens (2009 - 2023)
* Contributors listed in CONTRIBUTORS.txt * Contributors listed in CONTRIBUTORS.txt

View File

@@ -36,7 +36,7 @@ Official website: https://my-aac.org
chmod 660 images/guilds chmod 660 images/guilds
chmod 660 images/houses chmod 660 images/houses
chmod 660 images/gallery chmod 660 images/gallery
chmod -R 770 system/cache chmod -R 760 system/cache
Visit http://your_domain/install (http://localhost/install) and follow instructions in the browser. Visit http://your_domain/install (http://localhost/install) and follow instructions in the browser.

View File

@@ -1 +1,2 @@
<?php <?php
// nothing yet here

View File

@@ -0,0 +1,35 @@
<?php
$order = 10;
$settingsMenu = [];
$settingsMenu[] = [
'name' => 'MyAAC',
'link' => 'settings&plugin=core',
'icon' => 'list',
'order' => $order,
];
foreach (Plugins::getAllPluginsSettings() as $setting) {
$file = BASE . $setting['settingsFilename'];
if (!file_exists($file)) {
warning('Plugin setting: ' . $file . ' - cannot be loaded.');
continue;
}
$order += 10;
$settings = require $file;
$settingsMenu[] = [
'name' => $settings['name'],
'link' => 'settings&plugin=' . $setting['pluginFilename'],
'icon' => 'list',
'order' => $order,
];
}
unset($settings, $file, $order);
return $settingsMenu;

View File

@@ -6,10 +6,6 @@ require '../common.php';
const ADMIN_PANEL = true; const ADMIN_PANEL = true;
const MYAAC_ADMIN = true; const MYAAC_ADMIN = true;
if(file_exists(BASE . 'config.local.php')) {
require_once BASE . 'config.local.php';
}
if(file_exists(BASE . 'install') && (!isset($config['installed']) || !$config['installed'])) if(file_exists(BASE . 'install') && (!isset($config['installed']) || !$config['installed']))
{ {
header('Location: ' . BASE_URL . 'install/'); header('Location: ' . BASE_URL . 'install/');
@@ -29,10 +25,9 @@ define('PAGE', $page);
require SYSTEM . 'functions.php'; require SYSTEM . 'functions.php';
require SYSTEM . 'init.php'; require SYSTEM . 'init.php';
if(config('env') === 'dev') { // verify myaac tables exists in database
ini_set('display_errors', 1); if(!$db->hasTable('myaac_account_actions')) {
ini_set('display_startup_errors', 1); throw new RuntimeException('Seems that the table <strong>myaac_account_actions</strong> of MyAAC doesn\'t exist in the database. This is a fatal error. You can try to reinstall MyAAC by visiting <a href="' . BASE_URL . 'install">this</a> url.');
error_reporting(E_ALL);
} }
// event system // event system
@@ -42,7 +37,6 @@ $hooks->load();
require SYSTEM . 'status.php'; require SYSTEM . 'status.php';
require SYSTEM . 'login.php'; require SYSTEM . 'login.php';
require SYSTEM . 'migrate.php';
require __DIR__ . '/includes/functions.php'; require __DIR__ . '/includes/functions.php';
$twig->addGlobal('config', $config); $twig->addGlobal('config', $config);
@@ -70,7 +64,9 @@ if(!@file_exists($file)) {
} }
ob_start(); ob_start();
include($file); if($hooks->trigger(HOOK_ADMIN_BEFORE_PAGE)) {
require $file;
}
$content .= ob_get_contents(); $content .= ob_get_contents();
ob_end_clean(); ob_end_clean();

View File

@@ -10,12 +10,17 @@
defined('MYAAC') or die('Direct access not allowed!'); defined('MYAAC') or die('Direct access not allowed!');
$title = 'Account editor'; $title = 'Account editor';
$admin_base = BASE_URL . 'admin/?p=accounts'; $admin_base = ADMIN_URL . '?p=accounts';
$use_datatable = true; $use_datatable = true;
if ($config['account_country']) if ($config['account_country'])
require SYSTEM . 'countries.conf.php'; require SYSTEM . 'countries.conf.php';
$nameOrNumberColumn = 'name';
if (USE_ACCOUNT_NUMBER) {
$nameOrNumberColumn = 'number';
}
$hasSecretColumn = $db->hasColumn('accounts', 'secret'); $hasSecretColumn = $db->hasColumn('accounts', 'secret');
$hasCoinsColumn = $db->hasColumn('accounts', 'coins'); $hasCoinsColumn = $db->hasColumn('accounts', 'coins');
$hasPointsColumn = $db->hasColumn('accounts', 'premium_points'); $hasPointsColumn = $db->hasColumn('accounts', 'premium_points');
@@ -32,7 +37,7 @@ if ($config['account_country']) {
$countries[$code] = $c; $countries[$code] = $c;
} }
$web_acc = ACCOUNT_WEB_FLAGS; $web_acc = ACCOUNT_WEB_FLAGS;
$acc_type = config('account_types'); $acc_type = setting('core.account_types');
?> ?>
<link rel="stylesheet" type="text/css" href="<?php echo BASE_URL; ?>tools/css/jquery.datetimepicker.css"/ > <link rel="stylesheet" type="text/css" href="<?php echo BASE_URL; ?>tools/css/jquery.datetimepicker.css"/ >
@@ -48,16 +53,16 @@ else if (isset($_REQUEST['search'])) {
if (strlen($search_account) < 3 && !Validator::number($search_account)) { if (strlen($search_account) < 3 && !Validator::number($search_account)) {
echo_error('Player name is too short.'); echo_error('Player name is too short.');
} else { } else {
$query = $db->query('SELECT `id` FROM `accounts` WHERE `name` = ' . $db->quote($search_account)); $query = $db->query('SELECT `id` FROM `accounts` WHERE `' . $nameOrNumberColumn . '` = ' . $db->quote($search_account));
if ($query->rowCount() == 1) { if ($query->rowCount() == 1) {
$query = $query->fetch(); $query = $query->fetch();
$id = (int)$query['id']; $id = (int)$query['id'];
} else { } else {
$query = $db->query('SELECT `id`, `name` FROM `accounts` WHERE `name` LIKE ' . $db->quote('%' . $search_account . '%')); $query = $db->query('SELECT `id`, `' . $nameOrNumberColumn . '` FROM `accounts` WHERE `' . $nameOrNumberColumn . '` LIKE ' . $db->quote('%' . $search_account . '%'));
if ($query->rowCount() > 0 && $query->rowCount() <= 10) { if ($query->rowCount() > 0 && $query->rowCount() <= 10) {
$str_construct = 'Do you mean?<ul class="mb-0">'; $str_construct = 'Do you mean?<ul class="mb-0">';
foreach ($query as $row) foreach ($query as $row)
$str_construct .= '<li><a href="' . $admin_base . '&id=' . $row['id'] . '">' . $row['name'] . '</a></li>'; $str_construct .= '<li><a href="' . $admin_base . '&id=' . $row['id'] . '">' . $row[$nameOrNumberColumn] . '</a></li>';
$str_construct .= '</ul>'; $str_construct .= '</ul>';
echo_error($str_construct); echo_error($str_construct);
} else if ($query->rowCount() > 10) } else if ($query->rowCount() > 10)
@@ -145,7 +150,7 @@ else if (isset($_REQUEST['search'])) {
$web_lastlogin = strtotime($_POST['web_lastlogin']); $web_lastlogin = strtotime($_POST['web_lastlogin']);
verify_number($web_lastlogin, 'Web Last login', 11); verify_number($web_lastlogin, 'Web Last login', 11);
if (!$error) { if (!$error && $hooks->trigger(HOOK_ADMIN_ACCOUNTS_SAVE_POST, ['account_id' => $account->getId(), 'account_email' => $account->getEMail()])) {
if (USE_ACCOUNT_NAME) { if (USE_ACCOUNT_NAME) {
$account->setName($name); $account->setName($name);
} }
@@ -203,7 +208,7 @@ else if (isset($_REQUEST['search'])) {
} }
} }
} else if ($id == 0) { } else if ($id == 0) {
$accounts_db = $db->query('SELECT `id`, `name`' . ($hasTypeColumn ? ',type' : ($hasGroupColumn ? ',group_id' : '')) . ' FROM `accounts` ORDER BY `id` ASC'); $accounts_db = $db->query('SELECT `id`, `' . $nameOrNumberColumn . '`' . ($hasTypeColumn ? ',type' : ($hasGroupColumn ? ',group_id' : '')) . ' FROM `accounts` ORDER BY `id` ASC');
?> ?>
<div class="col-12 col-sm-12 col-lg-10"> <div class="col-12 col-sm-12 col-lg-10">
<div class="card card-info card-outline"> <div class="card card-info card-outline">
@@ -215,7 +220,7 @@ else if (isset($_REQUEST['search'])) {
<thead> <thead>
<tr> <tr>
<th>ID</th> <th>ID</th>
<th>Name</th> <th><?= ($nameOrNumberColumn == 'number' ? 'Number' : 'Name'); ?></th>
<?php if($hasTypeColumn || $hasGroupColumn): ?> <?php if($hasTypeColumn || $hasGroupColumn): ?>
<th>Position</th> <th>Position</th>
<?php endif; ?> <?php endif; ?>
@@ -226,7 +231,7 @@ else if (isset($_REQUEST['search'])) {
<?php foreach ($accounts_db as $account_lst): ?> <?php foreach ($accounts_db as $account_lst): ?>
<tr> <tr>
<th><?php echo $account_lst['id']; ?></th> <th><?php echo $account_lst['id']; ?></th>
<td><?php echo $account_lst['name']; ?></a></td> <td><?php echo $account_lst[$nameOrNumberColumn]; ?></a></td>
<?php if($hasTypeColumn || $hasGroupColumn): ?> <?php if($hasTypeColumn || $hasGroupColumn): ?>
<td> <td>
<?php if ($hasTypeColumn) { <?php if ($hasTypeColumn) {
@@ -284,6 +289,11 @@ else if (isset($_REQUEST['search'])) {
<label for="name">Account Name:</label> <label for="name">Account Name:</label>
<input type="text" class="form-control" id="name" name="name" autocomplete="off" value="<?php echo $account->getName(); ?>"/> <input type="text" class="form-control" id="name" name="name" autocomplete="off" value="<?php echo $account->getName(); ?>"/>
</div> </div>
<?php elseif (USE_ACCOUNT_NUMBER): ?>
<div class="col-12 col-sm-12 col-lg-4">
<label for="name">Account Number:</label>
<input type="text" class="form-control" id="name" name="name" autocomplete="off" value="<?php echo $account->getNumber(); ?>"/>
</div>
<?php endif; ?> <?php endif; ?>
<div class="col-12 col-sm-12 col-lg-5"> <div class="col-12 col-sm-12 col-lg-5">
<div class="form-check"> <div class="form-check">
@@ -351,7 +361,7 @@ else if (isset($_REQUEST['search'])) {
</div> </div>
<div class="form-group row"> <div class="form-group row">
<div class="col-12 col-sm-12 col-lg-6"> <div class="col-12 col-sm-12 col-lg-6">
<label for="email">Email:</label><?php echo (config('mail_enabled') ? ' (<a href="' . ADMIN_URL . '?p=mailer&mail_to=' . $account->getEMail() . '">Send Mail</a>)' : ''); ?> <label for="email">Email:</label><?php echo (setting('core.mail_enabled') ? ' (<a href="' . ADMIN_URL . '?p=mailer&mail_to=' . $account->getEMail() . '">Send Mail</a>)' : ''); ?>
<input type="text" class="form-control" id="email" name="email" autocomplete="off" value="<?php echo $account->getEMail(); ?>"/> <input type="text" class="form-control" id="email" name="email" autocomplete="off" value="<?php echo $account->getEMail(); ?>"/>
</div> </div>
<?php if ($hasCoinsColumn): ?> <?php if ($hasCoinsColumn): ?>

View File

@@ -47,12 +47,11 @@ $tmp = '';
if (fetchDatabaseConfig('site_closed_message', $tmp)) if (fetchDatabaseConfig('site_closed_message', $tmp))
$closed_message = $tmp; $closed_message = $tmp;
$configAdminPanelModules = config('admin_panel_modules'); $settingAdminPanelModules = setting('core.admin_panel_modules');
if (isset($configAdminPanelModules)) { if (count($settingAdminPanelModules) > 0) {
echo '<div class="row">'; echo '<div class="row">';
$configAdminPanelModules = explode(',', $configAdminPanelModules);
$twig_loader->prependPath(__DIR__ . '/modules/templates'); $twig_loader->prependPath(__DIR__ . '/modules/templates');
foreach ($configAdminPanelModules as $box) { foreach ($settingAdminPanelModules as $box) {
$file = __DIR__ . '/modules/' . $box . '.php'; $file = __DIR__ . '/modules/' . $box . '.php';
if (file_exists($file)) { if (file_exists($file)) {
include($file); include($file);

View File

@@ -10,6 +10,12 @@
defined('MYAAC') or die('Direct access not allowed!'); defined('MYAAC') or die('Direct access not allowed!');
$title = 'Login'; $title = 'Login';
require PAGES . 'account/login.php';
if ($logged) {
header('Location: ' . (admin() ? ADMIN_URL : BASE_URL));
return;
}
$twig->display('admin.login.html.twig', [ $twig->display('admin.login.html.twig', [
'logout' => (ACTION == 'logout' ? 'You have been logged out!' : ''), 'logout' => (ACTION == 'logout' ? 'You have been logged out!' : ''),
'account' => USE_ACCOUNT_NAME ? 'Name' : 'Number', 'account' => USE_ACCOUNT_NAME ? 'Name' : 'Number',

View File

@@ -15,8 +15,8 @@ if (!hasFlag(FLAG_CONTENT_MAILER) && !superAdmin()) {
return; return;
} }
if (!config('mail_enabled')) { if (!setting('core.mail_enabled')) {
echo 'Mail support disabled.'; echo 'Mail support disabled in config.';
return; return;
} }

View File

@@ -46,6 +46,7 @@ if (isset($_REQUEST['template'])) {
if ($cache->enabled()) { if ($cache->enabled()) {
$cache->delete('template_menus'); $cache->delete('template_menus');
} }
success('Saved at ' . date('H:i')); success('Saved at ' . date('H:i'));
} }
@@ -56,6 +57,7 @@ if (isset($_REQUEST['template'])) {
echo 'Cannot find template config.php file.'; echo 'Cannot find template config.php file.';
return; return;
} }
if (!isset($config['menu_categories'])) { if (!isset($config['menu_categories'])) {
echo "No menu categories set in template config.php.<br/>This template doesn't support dynamic menus."; echo "No menu categories set in template config.php.<br/>This template doesn't support dynamic menus.";
return; return;
@@ -91,15 +93,16 @@ if (isset($_REQUEST['template'])) {
<ul class="sortable" id="sortable-<?php echo $id ?>"> <ul class="sortable" id="sortable-<?php echo $id ?>">
<?php <?php
if (isset($menus[$id])) { if (isset($menus[$id])) {
foreach ($menus[$id] as $i => $menu): $i = 0;
foreach ($menus[$id] as $menu):
?> ?>
<li class="ui-state-default" id="list-<?php echo $id ?>-<?php echo $i ?>"><label>Name:</label> <input type="text" name="menu[<?php echo $id ?>][]" value="<?php echo escapeHtml($menu['name']); ?>"/> <li class="ui-state-default" id="list-<?php echo $id ?>-<?php echo $i ?>"><label>Name:</label> <input type="text" name="menu[<?php echo $id ?>][]" value="<?php echo escapeHtml($menu['name']); ?>"/>
<label>Link:</label> <input type="text" name="menu_link[<?php echo $id ?>][]" value="<?php echo $menu['link'] ?>"/> <label>Link:</label> <input type="text" name="menu_link[<?php echo $id ?>][]" value="<?php echo $menu['link'] ?>"/>
<input type="hidden" name="menu_blank[<?php echo $id ?>][]" value="0"/> <input type="hidden" name="menu_blank[<?php echo $id ?>][]" value="0"/>
<label><input class="blank-checkbox" type="checkbox" <?php echo($menu['blank'] == 1 ? 'checked' : '') ?>/><span title="Open in New Window">New Window</span></label> <label><input class="blank-checkbox" type="checkbox" <?php echo($menu['blank'] == 1 ? 'checked' : '') ?>/><span title="Open in New Window">New Window</span></label>
<input class="color-picker" type="text" name="menu_color[<?php echo $id ?>][]" value="#<?php echo $menu['color'] ?>"/> <input class="color-picker" type="text" name="menu_color[<?php echo $id ?>][]" value="<?php echo (empty($menu['color']) ? ($config['menu_default_color'] ?? '#ffffff') : $menu['color']); ?>"/>
<a class="remove-button" id="remove-button-<?php echo $id ?>-<?php echo $i ?>"><i class="fas fa-trash"></a></i></li> <a class="remove-button" id="remove-button-<?php echo $id ?>-<?php echo $i ?>"><i class="fas fa-trash"></a></i></li>
<?php $last_id[$id] = $i; <?php $i++; $last_id[$id] = $i;
endforeach; endforeach;
} ?> } ?>
</ul> </ul>
@@ -120,7 +123,8 @@ if (isset($_REQUEST['template'])) {
<?php <?php
$twig->display('admin.menus.js.html.twig', array( $twig->display('admin.menus.js.html.twig', array(
'menus' => $menus, 'menus' => $menus,
'last_id' => $last_id 'last_id' => $last_id,
'menu_default_color' => $config['menu_default_color'] ?? '#ffffff'
)); ));
?> ?>
<?php <?php

View File

@@ -1,4 +1,6 @@
<?php <?php
defined('MYAAC') or die('Direct access not allowed!');
$balance = ($db->hasColumn('players', 'balance') ? $db->query('SELECT `balance`, `id`, `name`,`level` FROM `players` ORDER BY `balance` DESC LIMIT 10;') : 0); $balance = ($db->hasColumn('players', 'balance') ? $db->query('SELECT `balance`, `id`, `name`,`level` FROM `players` ORDER BY `balance` DESC LIMIT 10;') : 0);
$twig->display('balance.html.twig', array( $twig->display('balance.html.twig', array(

View File

@@ -1,4 +1,6 @@
<?php <?php
defined('MYAAC') or die('Direct access not allowed!');
$coins = ($db->hasColumn('accounts', 'coins') ? $db->query('SELECT `coins`, `' . (USE_ACCOUNT_NAME ? 'name' : 'id') . '` as `name` FROM `accounts` ORDER BY `coins` DESC LIMIT 10;') : 0); $coins = ($db->hasColumn('accounts', 'coins') ? $db->query('SELECT `coins`, `' . (USE_ACCOUNT_NAME ? 'name' : 'id') . '` as `name` FROM `accounts` ORDER BY `coins` DESC LIMIT 10;') : 0);
$twig->display('coins.html.twig', array( $twig->display('coins.html.twig', array(

View File

@@ -1,4 +1,6 @@
<?php <?php
defined('MYAAC') or die('Direct access not allowed!');
$players = ($db->hasColumn('accounts', 'created') ? $db->query('SELECT `created`, `' . (USE_ACCOUNT_NAME ? 'name' : 'id') . '` as `name` FROM `accounts` ORDER BY `created` DESC LIMIT 10;') : 0); $players = ($db->hasColumn('accounts', 'created') ? $db->query('SELECT `created`, `' . (USE_ACCOUNT_NAME ? 'name' : 'id') . '` as `name` FROM `accounts` ORDER BY `created` DESC LIMIT 10;') : 0);
$twig->display('created.html.twig', array( $twig->display('created.html.twig', array(

View File

@@ -1,4 +1,6 @@
<?php <?php
defined('MYAAC') or die('Direct access not allowed!');
$players = ($db->hasColumn('players', 'lastlogin') ? $db->query('SELECT name, level, lastlogin FROM players ORDER BY lastlogin DESC LIMIT 10;') : 0); $players = ($db->hasColumn('players', 'lastlogin') ? $db->query('SELECT name, level, lastlogin FROM players ORDER BY lastlogin DESC LIMIT 10;') : 0);
$twig->display('lastlogin.html.twig', array( $twig->display('lastlogin.html.twig', array(
'players' => $players, 'players' => $players,

View File

@@ -1,4 +1,6 @@
<?php <?php
defined('MYAAC') or die('Direct access not allowed!');
$points = ($db->hasColumn('accounts', 'premium_points') ? $db->query('SELECT `premium_points`, `' . (USE_ACCOUNT_NAME ? 'name' : 'id') . '` as `name` FROM `accounts` ORDER BY `premium_points` DESC LIMIT 10;') : 0); $points = ($db->hasColumn('accounts', 'premium_points') ? $db->query('SELECT `premium_points`, `' . (USE_ACCOUNT_NAME ? 'name' : 'id') . '` as `name` FROM `accounts` ORDER BY `premium_points` DESC LIMIT 10;') : 0);
$twig->display('points.html.twig', array( $twig->display('points.html.twig', array(

View File

@@ -76,18 +76,18 @@ if (!empty($action)) {
$enable_tinymce = $_page['enable_tinymce'] == '1'; $enable_tinymce = $_page['enable_tinymce'] == '1';
$access = $_page['access']; $access = $_page['access'];
} else { } else {
if(Pages::update($id, $name, $p_title, $body, $player_id, $php, $enable_tinymce, $access)) { if(Pages::update($id, $name, $p_title, $body, $player_id, $php, $enable_tinymce, $access, $errors)) {
$action = $name = $p_title = $body = ''; $action = $name = $p_title = $body = '';
$player_id = 1; $player_id = 1;
$access = 0; $access = 0;
$php = false; $php = false;
$enable_tinymce = true; $enable_tinymce = true;
success("Updated successful."); success('Updated successful.');
} }
} }
} else if ($action == 'hide') { } else if ($action == 'hide') {
Pages::toggleHidden($id, $errors, $status); Pages::toggleHidden($id, $errors, $status);
success(($status == 1 ? 'Show' : 'Hide') . " successful."); success(($status == 1 ? 'Show' : 'Hide') . ' successful.');
} }
if (!empty($errors)) if (!empty($errors))
@@ -152,6 +152,10 @@ class Pages
$errors[] = 'Enable PHP is wrong.'; $errors[] = 'Enable PHP is wrong.';
return false; return false;
} }
if ($php == 1 && !getBoolean(setting('core.admin_pages_php_enable'))) {
$errors[] = 'PHP pages disabled on this server. To enable go to Settings in Admin Panel and enable <strong>Enable PHP Pages</strong>.';
return false;
}
if(!isset($enable_tinymce) || ($enable_tinymce != 0 && $enable_tinymce != 1)) { if(!isset($enable_tinymce) || ($enable_tinymce != 0 && $enable_tinymce != 1)) {
$errors[] = 'Enable TinyMCE is wrong.'; $errors[] = 'Enable TinyMCE is wrong.';
return false; return false;
@@ -200,7 +204,7 @@ class Pages
return !count($errors); return !count($errors);
} }
static public function update($id, $name, $title, $body, $player_id, $php, $enable_tinymce, $access) static public function update($id, $name, $title, $body, $player_id, $php, $enable_tinymce, $access, &$errors)
{ {
if(!self::verify($name, $title, $body, $player_id, $php, $enable_tinymce, $access, $errors)) { if(!self::verify($name, $title, $body, $player_id, $php, $enable_tinymce, $access, $errors)) {
return false; return false;
@@ -254,5 +258,3 @@ class Pages
return !count($errors); return !count($errors);
} }
} }
?>

View File

@@ -16,4 +16,4 @@ if (!function_exists('phpinfo')) { ?>
<?php return; <?php return;
} }
?> ?>
<iframe src="<?php echo BASE_URL; ?>admin/tools/phpinfo.php" width="1024" height="550"></iframe> <iframe src="<?php echo ADMIN_URL; ?>tools/phpinfo.php" width="1024" height="550"></iframe>

View File

@@ -10,7 +10,7 @@
defined('MYAAC') or die('Direct access not allowed!'); defined('MYAAC') or die('Direct access not allowed!');
$title = 'Player editor'; $title = 'Player editor';
$player_base = BASE_URL . 'admin/?p=players'; $player_base = ADMIN_URL . '?p=players';
$use_datatable = true; $use_datatable = true;
require_once LIBS . 'forum.php'; require_once LIBS . 'forum.php';
@@ -663,7 +663,14 @@ else if (isset($_REQUEST['search'])) {
</div> </div>
<div class="col-12 col-sm-12 col-lg-6"> <div class="col-12 col-sm-12 col-lg-6">
<label for="lastip" class="control-label">Last IP:</label> <label for="lastip" class="control-label">Last IP:</label>
<input type="text" class="form-control" id="lastip" name="lastip" autocomplete="off" maxlength="10" value="<?php echo longToIp($player->getLastIP()); ?>" readonly/> <input type="text" class="form-control" id="lastip" name="lastip" autocomplete="off" maxlength="10" value="<?php
if (strlen($player->getLastIP()) > 11) {
echo inet_ntop($player->getLastIP());
}
else {
echo longToIp($player->getLastIP());
}
?>" readonly/>
</div> </div>
</div> </div>
<?php if ($db->hasColumn('players', 'loss_experience')): ?> <?php if ($db->hasColumn('players', 'loss_experience')): ?>

View File

@@ -13,6 +13,10 @@ $use_datatable = true;
require_once LIBS . 'plugins.php'; require_once LIBS . 'plugins.php';
if (!getBoolean(setting('core.admin_plugins_manage_enable'))) {
warning('Plugin installation and management is disabled in Settings.<br/>If you wish to enable, go to Settings and enable <strong>Enable Plugins Manage</strong>.');
}
else {
$twig->display('admin.plugins.form.html.twig'); $twig->display('admin.plugins.form.html.twig');
if (isset($_REQUEST['uninstall'])) { if (isset($_REQUEST['uninstall'])) {
@@ -23,13 +27,27 @@ if (isset($_REQUEST['uninstall'])) {
} else { } else {
error('Error while uninstalling plugin ' . $uninstall . ': ' . Plugins::getError()); error('Error while uninstalling plugin ' . $uninstall . ': ' . Plugins::getError());
} }
} else if (isset($_FILES["plugin"]["name"])) { } else if (isset($_REQUEST['enable'])) {
$file = $_FILES["plugin"]; $enable = $_REQUEST['enable'];
$filename = $file["name"]; if (Plugins::enable($enable)) {
$tmp_name = $file["tmp_name"]; success('Successfully enabled plugin ' . $enable);
$type = $file["type"]; } else {
error('Error while enabling plugin ' . $enable . ': ' . Plugins::getError());
}
} else if (isset($_REQUEST['disable'])) {
$disable = $_REQUEST['disable'];
if (Plugins::disable($disable)) {
success('Successfully disabled plugin ' . $disable);
} else {
error('Error while disabling plugin ' . $disable . ': ' . Plugins::getError());
}
} else if (isset($_FILES['plugin']['name'])) {
$file = $_FILES['plugin'];
$filename = $file['name'];
$tmp_name = $file['tmp_name'];
$type = $file['type'];
$name = explode(".", $filename); $name = explode('.', $filename);
$accepted_types = array('application/zip', 'application/x-zip-compressed', 'multipart/x-zip', 'application/x-compressed', 'application/octet-stream', 'application/zip-compressed'); $accepted_types = array('application/zip', 'application/x-zip-compressed', 'multipart/x-zip', 'application/x-compressed', 'application/octet-stream', 'application/zip-compressed');
if (isset($file['error'])) { if (isset($file['error'])) {
@@ -88,23 +106,26 @@ if (isset($_REQUEST['uninstall'])) {
} }
} }
} }
}
$plugins = array(); $plugins = array();
foreach (get_plugins() as $plugin) { foreach (get_plugins(true) as $plugin) {
$string = file_get_contents(BASE . 'plugins/' . $plugin . '.json'); $string = file_get_contents(BASE . 'plugins/' . $plugin . '.json');
$string = Plugins::removeComments($string);
$plugin_info = json_decode($string, true); $plugin_info = json_decode($string, true);
if ($plugin_info == false) { if (!$plugin_info) {
warning('Cannot load plugin info ' . $plugin . '.json'); warning('Cannot load plugin info ' . $plugin . '.json');
} else { } else {
$disabled = (strpos($plugin, 'disabled.') !== false);
$pluginOriginal = ($disabled ? str_replace('disabled.', '', $plugin) : $plugin);
$plugins[] = array( $plugins[] = array(
'name' => isset($plugin_info['name']) ? $plugin_info['name'] : '', 'name' => $plugin_info['name'] ?? '',
'description' => isset($plugin_info['description']) ? $plugin_info['description'] : '', 'description' => $plugin_info['description'] ?? '',
'version' => isset($plugin_info['version']) ? $plugin_info['version'] : '', 'version' => $plugin_info['version'] ?? '',
'author' => isset($plugin_info['author']) ? $plugin_info['author'] : '', 'author' => $plugin_info['author'] ?? '',
'contact' => isset($plugin_info['contact']) ? $plugin_info['contact'] : '', 'contact' => $plugin_info['contact'] ?? '',
'file' => $plugin, 'file' => $pluginOriginal,
'enabled' => !$disabled,
'uninstall' => isset($plugin_info['uninstall']) 'uninstall' => isset($plugin_info['uninstall'])
); );
} }

56
admin/pages/settings.php Normal file
View File

@@ -0,0 +1,56 @@
<?php
/**
* Menus
*
* @package MyAAC
* @author Slawkens <slawkens@gmail.com>
* @copyright 2019 MyAAC
* @link https://my-aac.org
*/
defined('MYAAC') or die('Direct access not allowed!');
$title = 'Settings';
require_once SYSTEM . 'clients.conf.php';
if (empty($_GET['plugin'])) {
error('Please select plugin from left Panel.');
return;
}
$plugin = $_GET['plugin'];
if($plugin != 'core') {
$pluginSettings = Plugins::getPluginSettings($plugin);
if (!$pluginSettings) {
error('This plugin does not exist or does not have settings defined.');
return;
}
$settingsFilePath = BASE . $pluginSettings;
}
else {
$settingsFilePath = SYSTEM . 'settings.php';
}
if (!file_exists($settingsFilePath)) {
error("Plugin $plugin does not exist or does not have settings defined.");
return;
}
$settingsFile = require $settingsFilePath;
if (!is_array($settingsFile)) {
error("Cannot load settings file for plugin $plugin");
return;
}
$settingsKeyName = ($plugin == 'core' ? $plugin : $settingsFile['key']);
$title = ($plugin == 'core' ? 'Settings' : 'Plugin Settings - ' . $plugin);
$settingsParsed = Settings::display($settingsKeyName, $settingsFile['settings']);
$twig->display('admin.settings.html.twig', [
'settingsParsed' => $settingsParsed['content'],
'settings' => $settingsFile['settings'],
'script' => $settingsParsed['script'],
'settingsKeyName' => $settingsKeyName,
]);

View File

@@ -36,4 +36,3 @@ $twig->display('admin.statistics.html.twig', array(
'account_type' => (USE_ACCOUNT_NAME ? 'name' : 'number'), 'account_type' => (USE_ACCOUNT_NAME ? 'name' : 'number'),
'points' => $points 'points' => $points
)); ));
?>

View File

@@ -47,4 +47,3 @@ function version_revert($version)
$release = $version; $release = $version;
return $major . '.' . $minor . '.' . $release; return $major . '.' . $minor . '.' . $release;
}*/ }*/
?>

View File

@@ -8,10 +8,15 @@
* @link https://my-aac.org * @link https://my-aac.org
*/ */
defined('MYAAC') or die('Direct access not allowed!'); defined('MYAAC') or die('Direct access not allowed!');
use DeviceDetector\DeviceDetector;
use DeviceDetector\Parser\Client\Browser;
use DeviceDetector\Parser\OperatingSystem;
$title = 'Visitors'; $title = 'Visitors';
$use_datatable = true; $use_datatable = true;
if (!$config['visitors_counter']): ?> if (!setting('core.visitors_counter')): ?>
Visitors counter is disabled.<br/> Visitors counter is disabled.<br/>
You can enable it by editing this configurable in <b>config.local.php</b> file:<br/> You can enable it by editing this configurable in <b>config.local.php</b> file:<br/>
<p style="margin-left: 3em;"><b>$config['visitors_counter'] = true;</b></p> <p style="margin-left: 3em;"><b>$config['visitors_counter'] = true;</b></p>
@@ -20,18 +25,42 @@ if (!$config['visitors_counter']): ?>
endif; endif;
require SYSTEM . 'libs/visitors.php'; require SYSTEM . 'libs/visitors.php';
$visitors = new Visitors($config['visitors_counter_ttl']); $visitors = new Visitors(setting('core.visitors_counter_ttl'));
function compare($a, $b) function compare($a, $b): int {
{
return $a['lastvisit'] > $b['lastvisit'] ? -1 : 1; return $a['lastvisit'] > $b['lastvisit'] ? -1 : 1;
} }
$tmp = $visitors->getVisitors(); $tmp = $visitors->getVisitors();
usort($tmp, 'compare'); usort($tmp, 'compare');
foreach ($tmp as &$visitor) {
$userAgent = $visitor['user_agent'] ?? '';
if (!strlen($userAgent) || $userAgent == 'unknown') {
$browser = 'Unknown';
}
else {
$dd = new DeviceDetector($userAgent);
$dd->parse();
if ($dd->isBot()) {
$bot = $dd->getBot();
$message = '(Bot) %s, <a href="%s" target="_blank">%s</a>';
$browser = sprintf($message, $bot['category'], $bot['url'], $bot['name']);
}
else {
$osFamily = OperatingSystem::getOsFamily($dd->getOs('name'));
$browserFamily = Browser::getBrowserFamily($dd->getClient('name'));
$browser = $osFamily . ', ' . $browserFamily;
}
}
$visitor['browser'] = $browser;
}
$twig->display('admin.visitors.html.twig', array( $twig->display('admin.visitors.html.twig', array(
'config_visitors_counter_ttl' => $config['visitors_counter_ttl'], 'config_visitors_counter_ttl' => setting('core.visitors_counter_ttl'),
'visitors' => $tmp 'visitors' => $tmp
)); ));
?> ?>

View File

@@ -1,7 +1,10 @@
<?php <?php
$menus = [ return [
['name' => 'Dashboard', 'icon' => 'tachometer-alt', 'order' => 10, 'link' => 'dashboard'], ['name' => 'Dashboard', 'icon' => 'tachometer-alt', 'order' => 10, 'link' => 'dashboard'],
['name' => 'Settings', 'icon' => 'edit', 'order' => 19, 'link' =>
require ADMIN . 'includes/settings_menus.php'
],
['name' => 'News', 'icon' => 'newspaper', 'order' => 20, 'link' => ['name' => 'News', 'icon' => 'newspaper', 'order' => 20, 'link' =>
[ [
['name' => 'View', 'link' => 'news', 'icon' => 'list', 'order' => 10], ['name' => 'View', 'link' => 'news', 'icon' => 'list', 'order' => 10],
@@ -16,7 +19,7 @@ $menus = [
['name' => 'Add', 'link' => 'changelog&action=new', 'icon' => 'plus', 'order' => 20], ['name' => 'Add', 'link' => 'changelog&action=new', 'icon' => 'plus', 'order' => 20],
], ],
], ],
['name' => 'Mailer', 'icon' => 'envelope', 'order' => 40, 'link' => 'mailer', 'disabled' => !config('mail_enabled')], ['name' => 'Mailer', 'icon' => 'envelope', 'order' => 40, 'link' => 'mailer', 'disabled' => !setting('core.mail_enabled')],
['name' => 'Pages', 'icon' => 'book', 'order' => 50, 'link' => ['name' => 'Pages', 'icon' => 'book', 'order' => 50, 'link' =>
[ [
['name' => 'View', 'link' => 'pages', 'icon' => 'list', 'order' => 10], ['name' => 'View', 'link' => 'pages', 'icon' => 'list', 'order' => 10],

View File

@@ -2,6 +2,7 @@
<!doctype html> <!doctype html>
<html lang="en"> <html lang="en">
<head> <head>
<?php $hooks->trigger(HOOK_ADMIN_HEAD_START); ?>
<?php echo template_header(true); ?> <?php echo template_header(true); ?>
<title><?php echo (isset($title) ? $title . ' - ' : '') . $config['lua']['serverName'];?></title> <title><?php echo (isset($title) ? $title . ' - ' : '') . $config['lua']['serverName'];?></title>
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
@@ -16,8 +17,10 @@
<script src="<?php echo BASE_URL; ?>tools/js/respond.min.js"></script> <script src="<?php echo BASE_URL; ?>tools/js/respond.min.js"></script>
<![endif]--> <![endif]-->
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Source+Sans+Pro:300,400,600,700,300italic,400italic,600italic"> <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Source+Sans+Pro:300,400,600,700,300italic,400italic,600italic">
<?php $hooks->trigger(HOOK_ADMIN_HEAD_END); ?>
</head> </head>
<body class="sidebar-mini "> <body class="sidebar-mini ">
<?php $hooks->trigger(HOOK_ADMIN_BODY_START); ?>
<?php if ($logged && admin()) { ?> <?php if ($logged && admin()) { ?>
<div class="wrapper"> <div class="wrapper">
<nav class="main-header navbar navbar-expand navbar-white navbar-light"> <nav class="main-header navbar navbar-expand navbar-white navbar-light">
@@ -65,7 +68,7 @@
if (!$has_child) { ?> if (!$has_child) { ?>
<li class="nav-item"> <li class="nav-item">
<a class="nav-link<?php echo(strpos($menu['link'], $page) !== false ? ' active' : '') ?>" href="?p=<?php echo $menu['link'] ?>"> <a class="nav-link<?php echo(strpos($menu['link'], $page) !== false ? ' active' : '') ?>" href="?p=<?php echo $menu['link'] ?>">
<i class="nav-icon fas fa-<?php echo(isset($menu['icon']) ? $menu['icon'] : 'link') ?>"></i> <i class="nav-icon fas fa-<?php echo($menu['icon'] ?? 'link') ?>"></i>
<p><?php echo $menu['name'] ?></p> <p><?php echo $menu['name'] ?></p>
</a> </a>
</li> </li>
@@ -73,9 +76,9 @@
} else if ($has_child) { } else if ($has_child) {
$used_menu = null; $used_menu = null;
$nav_construct = ''; $nav_construct = '';
foreach ($menu['link'] as $category => $sub_menu) { foreach ($menu['link'] as $sub_category => $sub_menu) {
$nav_construct .= '<li class="nav-item"><a href="?p=' . $sub_menu['link'] . '" class="nav-link'; $nav_construct .= '<li class="nav-item"><a href="?p=' . $sub_menu['link'] . '" class="nav-link';
if ($page == $sub_menu['link']) { if ($_SERVER['QUERY_STRING'] == 'p=' . $sub_menu['link']) {
$nav_construct .= ' active'; $nav_construct .= ' active';
$used_menu = true; $used_menu = true;
} }
@@ -195,5 +198,6 @@ if ($logged && admin()) {
<script src="<?php echo BASE_URL; ?>tools/js/datatables.bs.min.js"></script> <script src="<?php echo BASE_URL; ?>tools/js/datatables.bs.min.js"></script>
<?php } ?> <?php } ?>
<script src="<?php echo BASE_URL; ?>tools/js/adminlte.min.js"></script> <script src="<?php echo BASE_URL; ?>tools/js/adminlte.min.js"></script>
<?php $hooks->trigger(HOOK_ADMIN_BODY_END); ?>
</body> </body>
</html> </html>

View File

@@ -13,4 +13,3 @@ if(!function_exists('phpinfo'))
die('phpinfo() disabled on this web server.'); die('phpinfo() disabled on this web server.');
phpinfo(); phpinfo();
?>

View File

@@ -0,0 +1,34 @@
<?php
const MYAAC_ADMIN = true;
require '../../common.php';
require SYSTEM . 'functions.php';
require SYSTEM . 'init.php';
require SYSTEM . 'login.php';
if(!admin()) {
http_response_code(500);
die('Access denied.');
}
if (!isset($_REQUEST['plugin'])) {
http_response_code(500);
die('Please enter plugin name.');
}
if (!isset($_POST['settings'])) {
http_response_code(500);
die('Please enter settings.');
}
$settings = Settings::getInstance();
$settings->save($_REQUEST['plugin'], $_POST['settings']);
$errors = $settings->getErrors();
if (count($errors) > 0) {
http_response_code(500);
die(implode('<br/>', $errors));
}
echo 'Saved at ' . date('H:i');

View File

@@ -26,8 +26,8 @@
if (version_compare(phpversion(), '7.2.5', '<')) die('PHP version 7.2.5 or higher is required.'); if (version_compare(phpversion(), '7.2.5', '<')) die('PHP version 7.2.5 or higher is required.');
const MYAAC = true; const MYAAC = true;
const MYAAC_VERSION = '0.9.0-dev'; const MYAAC_VERSION = '0.10.0-dev';
const DATABASE_VERSION = 33; const DATABASE_VERSION = 36;
const TABLE_PREFIX = 'myaac_'; const TABLE_PREFIX = 'myaac_';
define('START_TIME', microtime(true)); define('START_TIME', microtime(true));
define('MYAAC_OS', stripos(PHP_OS, 'WIN') === 0 ? 'WINDOWS' : (strtoupper(PHP_OS) === 'DARWIN' ? 'MAC' : 'LINUX')); define('MYAAC_OS', stripos(PHP_OS, 'WIN') === 0 ? 'WINDOWS' : (strtoupper(PHP_OS) === 'DARWIN' ? 'MAC' : 'LINUX'));
@@ -138,11 +138,25 @@ if(!IS_CLI) {
define('SERVER_URL', 'http' . (isset($_SERVER['HTTPS'][0]) && strtolower($_SERVER['HTTPS']) === 'on' ? 's' : '') . '://' . $baseHost); define('SERVER_URL', 'http' . (isset($_SERVER['HTTPS'][0]) && strtolower($_SERVER['HTTPS']) === 'on' ? 's' : '') . '://' . $baseHost);
define('BASE_URL', SERVER_URL . BASE_DIR . '/'); define('BASE_URL', SERVER_URL . BASE_DIR . '/');
define('ADMIN_URL', SERVER_URL . BASE_DIR . '/admin/'); define('ADMIN_URL', SERVER_URL . BASE_DIR . '/' . ADMIN_PANEL_FOLDER . '/');
//define('CURRENT_URL', BASE_URL . $_SERVER['REQUEST_URI']); //define('CURRENT_URL', BASE_URL . $_SERVER['REQUEST_URI']);
}
require SYSTEM . 'exception.php'; if (file_exists(BASE . 'config.local.php')) {
require BASE . 'config.local.php';
}
ini_set('log_errors', 1);
if(@$config['env'] === 'dev') {
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);
}
else {
ini_set('display_errors', 0);
ini_set('display_startup_errors', 0);
error_reporting(E_ALL & ~E_DEPRECATED & ~E_STRICT);
} }
$autoloadFile = VENDOR . 'autoload.php'; $autoloadFile = VENDOR . 'autoload.php';

View File

@@ -10,6 +10,10 @@
"composer/semver": "^3.2", "composer/semver": "^3.2",
"twig/twig": "^2.0", "twig/twig": "^2.0",
"erusev/parsedown": "^1.7", "erusev/parsedown": "^1.7",
"nikic/fast-route": "^1.3" "nikic/fast-route": "^1.3",
"matomo/device-detector": "^6.0"
},
"require-dev": {
"filp/whoops": "^2.15"
} }
} }

View File

@@ -1,326 +0,0 @@
<?php
/**
* This is MyAAC's Main Configuration file
*
* All the default values are kept here, you should not modify it but use
* a config.local.php file instead to override the settings from here.
*
* This is a piece of PHP code so PHP syntax applies!
* For boolean values please use true/false.
*
* Minimally 'server_path' directive have to be filled, other options are optional.
*
* @package MyAAC
* @author Slawkens <slawkens@gmail.com>
* @copyright 2019 MyAAC
* @link https://my-aac.org
*/
$config = array(
// directories & files
'server_path' => '', // path to the server directory (same directory where config file is located)
/**
* Environment Setting
*
* if you use this script on your live server - set to 'prod' (production)
* if you want to test and debug the script locally, or develop plugins, set to 'dev' (development)
* WARNING: on 'dev' cache is disabled, so site will be significantly slower !!!
* WARNING2: on 'dev' all PHP errors/warnings are displayed
* Recommended: 'prod' cause of speed (page load time is better)
*/
'env' => 'prod', // 'prod' for production and 'dev' for development
'template' => 'kathrine', // template used by website (kathrine, tibiacom)
'template_allow_change' => true, // allow users to choose their own template while browsing website?
'vocations_amount' => 4, // how much basic vocations your server got (without promotion)
// what client version are you using on this OT?
// used for the Downloads page and some templates aswell
'client' => 1098, // 954 = client 9.54
'session_prefix' => 'myaac_', // must be unique for every site on your server
'friendly_urls' => false, // mod_rewrite is required for this, it makes links looks more elegant to eye, and also are SEO friendly (example: https://my-aac.org/guilds/Testing instead of https://my-aac.org/?subtopic=guilds&name=Testing). Remember to rename .htaccess.dist to .htaccess
'gzip_output' => false, // gzip page content before sending it to the browser, uses less bandwidth but more cpu cycles
// gesior backward support (templates & pages)
// allows using gesior templates and pages with myaac
// might bring some performance when disabled
'backward_support' => true,
// head options (html)
'meta_description' => 'Tibia is a free massive multiplayer online role playing game (MMORPG).', // description of the site
'meta_keywords' => 'free online game, free multiplayer game, ots, open tibia server', // keywords list separated by commas
// footer
'footer' => ''/*'<br/>Your Server &copy; 2016. All rights reserved.'*/,
'language' => 'en', // default language (currently only 'en' available)
'language_allow_change' => false,
'visitors_counter' => true,
'visitors_counter_ttl' => 10, // how long visitor will be marked as online (in minutes)
'views_counter' => true,
// cache system. by default file cache is used
'cache_engine' => 'auto', // apc, apcu, eaccelerator, xcache, file, auto, or blank to disable.
'cache_prefix' => 'myaac_', // have to be unique if running more MyAAC instances on the same server (except file system cache)
// database details (leave blank for auto detect from config.lua)
'database_host' => '',
'database_port' => '', // leave blank to default 3306
'database_user' => '',
'database_password' => '',
'database_name' => '',
'database_log' => false, // should database queries be logged and saved into system/logs/database.log?
'database_socket' => '', // set if you want to connect to database through socket (example: /var/run/mysqld/mysqld.sock)
'database_persistent' => false, // use database permanent connection (like server), may speed up your site
// multiworld system (only TFS 0.3)
'multiworld' => false, // use multiworld system?
'worlds' => array( // list of worlds
//'1' => 'Your World Name',
//'2' => 'Your Second World Name'
),
// images
'outfit_images_url' => 'https://outfit-images.ots.me/outfit.php', // set to animoutfit.php for animated outfit
'outfit_images_wrong_looktypes' => [75, 126, 127, 266, 302], // this looktypes needs to have different margin-top and margin-left because they are wrong positioned
'item_images_url' => 'https://item-images.ots.me/1092/', // set to images/items if you host your own items in images folder
'item_images_extension' => '.gif',
// creatures
'creatures_images_url' => 'images/monsters/', // set to images/monsters if you host your own creatures in images folder
'creatures_images_extension' => '.gif',
'creatures_images_preview' => false, // set to true to allow picture previews for creatures
'creatures_items_url' => 'https://tibia.fandom.com/wiki/', // set to website which shows details about items.
'creatures_loot_percentage' => true, // set to true to show the loot tooltip percent
// account
'account_management' => true, // disable if you're using other method to manage users (fe. tfs account manager)
'account_login_by_email' => false, // use email instead of Account Name like in latest Tibia
'account_login_by_email_fallback' => false, // allow also additionally login by Account Name/Number (for users that might forget their email)
'account_create_auto_login' => false, // auto login after creating account?
'account_create_character_create' => true, // allow directly to create character on create account page?
'account_mail_verify' => false, // force users to confirm their email addresses when registering
'account_mail_confirmed_reward' => [ // reward users for confirming their E-Mails
// account_mail_verify needs to be enabled too
'premium_days' => 0,
'premium_points' => 0,
'coins' => 0,
'message' => 'You received %d %s for confirming your E-Mail address.' // example: You received 20 premium points for confirming your E-Mail address.
],
'account_mail_unique' => true, // email addresses cannot be duplicated? (one account = one email)
'account_mail_block_plus_sign' => true, // block email with '+' signs like test+box@gmail.com (help protect against spamming accounts)
'account_premium_days' => 0, // default premium days on new account
'account_premium_points' => 0, // default premium points on new account
'account_welcome_mail' => true, // send welcome email when user registers
'account_mail_change' => 2, // how many days user need to change email to account - block hackers
'account_country' => true, // user will be able to set country of origin when registering account, this information will be viewable in others places aswell
'account_country_recognize' => true, // should country of user be automatically recognized by his IP? This makes an external API call to http://ipinfo.io
'account_change_character_name' => false, // can user change their character name for premium points?
'account_change_character_name_points' => 30, // cost of name change
'account_change_character_sex' => false, // can user change their character sex for premium points?
'account_change_character_sex_points' => 30, // cost of sex change
'characters_per_account' => 10, // max. number of characters per account
// mail
'mail_enabled' => false, // is aac maker configured to send e-mails?
'mail_address' => 'no-reply@your-server.org', // server e-mail address (from:)
'mail_admin' => 'your-address@your-server.org', // admin email address, where mails from contact form will be sent
'mail_signature' => array( // signature that will be included at the end of every message sent using _mail function
'plain' => ""/*"--\nMy Server,\nhttp://www.myserver.com"*/,
'html' => ''/*'<br/>My Server,\n<a href="http://www.myserver.com">myserver.com</a>'*/
),
'smtp_enabled' => false, // send by smtp or mail function (set false if use mail function, set to true if you use GMail or Microsoft Outlook)
'smtp_host' => '', // mail host. smtp.gmail.com for GMail / smtp-mail.outlook.com for Microsoft Outlook
'smtp_port' => 25, // 25 (default) / 465 (ssl, GMail) / 587 (tls, Microsoft Outlook)
'smtp_auth' => true, // need authorization?
'smtp_user' => 'admin@example.org', // here your email username
'smtp_pass' => '',
'smtp_secure' => '', // What kind of encryption to use on the SMTP connection. Options: '', 'ssl' (GMail) or 'tls' (Microsoft Outlook)
'smtp_debug' => false, // set true to debug (you will see more info in error.log)
// Google reCAPTCHA (prevent spam bots)
'recaptcha_enabled' => false, // enable recaptcha verification code
'recaptcha_type' => 'v3', // 'v2-checkbox', 'v2-invisible', 'v3'
'recaptcha_site_key' => '', // get your own site and secret keys at https://www.google.com/recaptcha
'recaptcha_secret_key' => '',
// following option apply only for ReCaptcha v2-checkbox
'recaptcha_v2_theme' => 'light', // light, dark
// following option apply only for ReCaptcha v3
// min score for validation, between 0 - 1.0
// https://developers.google.com/recaptcha/docs/v3#interpreting_the_score
'recaptcha_v3_min_score' => 0.5,
//
'generate_new_reckey' => true, // let player generate new recovery key, he will receive e-mail with new rec key (not display on page, hacker can't generate rec key)
'generate_new_reckey_price' => 20, // price for new recovery key
'send_mail_when_change_password' => true, // send e-mail with new password when change password to account
'send_mail_when_generate_reckey' => true, // send e-mail with rec key (key is displayed on page anyway when generate)
// you may need to adjust this for older tfs versions
// by removing Community Manager
'account_types' => [
'None',
'Normal',
'Tutor',
'Senior Tutor',
'Gamemaster',
'Community Manager',
'God',
],
// genders (aka sex)
'genders' => array(
0 => 'Female',
1 => 'Male'
),
// new character config
'character_samples' => array( // vocations, format: ID_of_vocation => 'Name of Character to copy'
//0 => 'Rook Sample',
1 => 'Sorcerer Sample',
2 => 'Druid Sample',
3 => 'Paladin Sample',
4 => 'Knight Sample'
),
'use_character_sample_skills' => false,
// it must show limited number of players after using search in character page
'characters_search_limit' => 15,
// town list used when creating character
// won't be displayed if there is only one item (rookgaard for example)
'character_towns' => array(1),
// characters length
// This is the minimum and the maximum length that a player can create a character. It is highly recommend the maximum length to be 21.
'character_name_min_length' => 4,
'character_name_max_length' => 21,
'character_name_npc_check' => true,
// list of towns
// if you use TFS 1.3 with support for 'towns' table in database, then you can ignore this - it will be configured automatically (from MySQL database - Table - towns)
// otherwise it will try to load from your .OTBM map file
// if you don't see towns on website, then you need to fill this out
'towns' => array(
0 => 'No town',
1 => 'Sample town'
),
// guilds
'guild_management' => true, // enable guild management system on the site?
'guild_need_level' => 1, // min. level to form a guild
'guild_need_premium' => true, // require premium account to form a guild?
'guild_image_size_kb' => 80, // maximum size of the guild logo image in KB (kilobytes)
'guild_description_default' => 'New guild. Leader must edit this text :)',
'guild_description_chars_limit' => 1000, // limit of guild description
'guild_description_lines_limit' => 6, // limit of lines, if description has more lines it will be showed as long text, without 'enters'
'guild_motd_chars_limit' => 150, // limit of MOTD (message of the day) that is shown later in the game on the guild channel
// online page
'online_record' => true, // display players record?
'online_vocations' => false, // display vocation statistics?
'online_vocations_images' => false, // display vocation images?
'online_skulls' => false, // display skull images
'online_outfit' => true,
'online_afk' => false,
// support list page
'team_style' => 2, // 1/2 (1 - normal table, 2 - in boxes, grouped by group id)
'team_display_status' => true,
'team_display_lastlogin' => true,
'team_display_world' => false,
'team_display_outfit' => true,
// bans page
'bans_per_page' => 20,
// highscores page
'highscores_vocation_box' => true, // show 'Choose a vocation' box on the highscores (allowing peoples to sort highscores by vocation)?
'highscores_vocation' => true, // show player vocation under his nickname?
'highscores_frags' => false, // show 'Frags' tab (best fraggers on the server)?
'highscores_balance' => false, // show 'Balance' tab (richest players on the server)
'highscores_outfit' => true, // show player outfit?
'highscores_country_box' => false, // doesnt work yet! (not implemented)
'highscores_groups_hidden' => 3, // this group id and higher won't be shown on the highscores
'highscores_ids_hidden' => array(0), // this ids of players will be hidden on the highscores (should be ids of samples)
'highscores_per_page' => 100, // how many records per page on highscores
'highscores_cache_ttl' => 15, // how often to update highscores from database in minutes (default 15 minutes)
// characters page
'characters' => array( // what things to display on character view page (true/false in each option)
'level' => true,
'experience' => false,
'magic_level' => false,
'balance' => false,
'marriage_info' => true, // only 0.3
'outfit' => true,
'creation_date' => true,
'quests' => true,
'skills' => true,
'equipment' => true,
'frags' => false,
'deleted' => false, // should deleted characters from same account be still listed on the list of characters? When enabled it will show that character is "[DELETED]"
),
'quests' => array(
//'Some Quest' => 123,
//'Some Quest Two' => 456,
), // quests list (displayed in character view), name => storage
'signature_enabled' => true,
'signature_type' => 'tibian', // signature engine to use: tibian, mango, gesior
'signature_cache_time' => 5, // how long to store cached file (in minutes), default 5 minutes
'signature_browser_cache' => 60, // how long to cache by browser (in minutes), default 1 hour
// news page
'news_limit' => 5, // limit of news on the latest news page
'news_ticker_limit' => 5, // limit of news in tickers (mini news) (0 to disable)
'news_date_format' => 'j.n.Y', // check php manual date() function for more info about this
'news_author' => true, // show author of the news
// gifts/shop system
'gifts_system' => false,
// support/system
'bug_report' => true, // this configurable has no effect, its always enabled
// forum
'forum' => 'site', // link to the server forum, set to "site" if you want to use build in forum system, otherwise leave empty if you aren't going to use any forum
'forum_level_required' => 0, // level required to post, 0 to disable
'forum_post_interval' => 30, // in seconds
'forum_posts_per_page' => 20,
'forum_threads_per_page' => 20,
// uncomment to force use table for forum
//'forum_table_prefix' => 'z_', // what forum mysql table to use, z_ (for gesior old forum) or myaac_ (for myaac)
// last kills
'last_kills_limit' => 50, // max. number of deaths shown on the last kills page
// status, took automatically from config file if empty
'status_enabled' => true, // you can disable status checking by settings this to "false"
'status_ip' => '',
'status_port' => '',
'status_timeout' => 2.0, // how long to wait for the initial response from the server (default: 2 seconds)
// how often to connect to server and update status (default: every minute)
// if your status timeout in config.lua is bigger, that it will be used instead
// when server is offline, it will be checked every time web refreshes, ignoring this variable
'status_interval' => 60,
// admin panel
'admin_panel_modules' => 'statistics,web_status,server_status,lastlogin,created,points,coins,balance', // default - statistics,web_status,server_status,lastlogin,created,points,coins,balance
// other
'anonymous_usage_statistics' => true,
'email_lai_sec_interval' => 60, // time in seconds between e-mails to one account from lost account interface, block spam
'google_analytics_id' => '', // e.g.: UA-XXXXXXX-X
'experiencetable_columns' => 3, // how many columns to display in experience table page. * experiencetable_rows, 5 = 500 (will show up to 500 level)
'experiencetable_rows' => 200, // till how many levels in one column
'date_timezone' => 'Europe/Berlin', // more info at http://php.net/manual/en/timezones.php
'footer_show_load_time' => true, // display load time of the page in the footer
'npc' => array()
);

9
cypress.config.js Normal file
View File

@@ -0,0 +1,9 @@
const { defineConfig } = require("cypress");
module.exports = defineConfig({
e2e: {
setupNodeEvents(on, config) {
// implement node event listeners here
},
},
});

View File

@@ -0,0 +1,75 @@
describe('Install MyAAC', () => {
beforeEach(() => {
// Cypress starts out with a blank slate for each test
// so we must tell it to visit our website with the `cy.visit()` command.
// Since we want to visit the same URL at the start of all our tests,
// we include it in our beforeEach function so that it runs before each test
cy.visit(Cypress.env('URL'))
})
it('Go through installer', () => {
cy.visit(Cypress.env('URL') + '/install/?step=welcome')
cy.wait(1000)
cy.screenshot('install-welcome')
// step 1 - Welcome
cy.get('select[name="lang"]').select('en')
//cy.get('input[type=button]').contains('Next »').click()
cy.get('form').submit()
// step 2 - License
// just skip
cy.contains('GNU/GPL License');
cy.get('form').submit()
// step 3 - Requirements
cy.contains('Requirements check');
cy.get('#step').then(elem => {
elem.val('config');
});
cy.get('form').submit()
// step 4 - Configuration
cy.contains('Basic configuration');
cy.get('#vars_server_path').click().clear().type(Cypress.env('SERVER_PATH'))
cy.get('#vars_mail_admin').click().clear().type('noone@example.net')
cy.get('[type="checkbox"]').uncheck() // usage statistics uncheck
cy.wait(1000)
cy.get('form').submit()
// check if there is any error
// step 5 - Import Schema
cy.contains('Import MySQL schema');
// AAC is not installed yet, this message should not come
cy.contains('Seems AAC is already installed. Skipping importing MySQL schema..').should('not.exist')
cy.contains('[class="alert alert-success"]', 'Local configuration has been saved into file: config.local.php').should('be.visible')
cy.get('form').submit()
// step 6 - Admin Account
cy.get('#vars_email').click().clear().type('admin@my-aac.org')
cy.get('#vars_account').click().clear().type('admin')
cy.get('#vars_password').click().clear().type('test1234')
cy.get('#vars_password_confirm').click().clear().type('test1234')
cy.get('#vars_player_name').click().clear().type('Admin')
cy.get('form').submit()
cy.contains('[class="alert alert-success"]', 'Congratulations', { timeout: 30000 }).should('be.visible')
cy.screenshot('install-finish')
})
})

View File

@@ -0,0 +1,33 @@
describe('Create Account Page', () => {
beforeEach(() => {
// Cypress starts out with a blank slate for each test
// so we must tell it to visit our website with the `cy.visit()` command.
// Since we want to visit the same URL at the start of all our tests,
// we include it in our beforeEach function so that it runs before each test
cy.visit(Cypress.env('URL') + '/index.php/account/create')
})
it('Create Test Account', () => {
cy.screenshot('create-account-page')
cy.get('#account_input').type('tester')
cy.get('#email').type('tester@example.com')
cy.get('#password').type('test1234')
cy.get('#password2').type('test1234')
cy.get('#character_name').type('Slaw')
cy.get('#sex1').check()
cy.get('#vocation1').check()
cy.get('#accept_rules').check()
cy.get('#createaccount').submit()
// no errors please
cy.contains('The Following Errors Have Occurred:').should('not.exist')
// ss of post page
cy.screenshot('create-account-page-post')
})
})

View File

@@ -0,0 +1,5 @@
{
"name": "Using fixtures to represent data",
"email": "hello@cypress.io",
"body": "Fixtures are a great way to mock data for responses to routes"
}

View File

@@ -0,0 +1,25 @@
// ***********************************************
// This example commands.js shows you how to
// create various custom commands and overwrite
// existing commands.
//
// For more comprehensive examples of custom
// commands please read more here:
// https://on.cypress.io/custom-commands
// ***********************************************
//
//
// -- This is a parent command --
// Cypress.Commands.add('login', (email, password) => { ... })
//
//
// -- This is a child command --
// Cypress.Commands.add('drag', { prevSubject: 'element'}, (subject, options) => { ... })
//
//
// -- This is a dual command --
// Cypress.Commands.add('dismiss', { prevSubject: 'optional'}, (subject, options) => { ... })
//
//
// -- This will overwrite an existing command --
// Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... })

20
cypress/support/e2e.js Normal file
View File

@@ -0,0 +1,20 @@
// ***********************************************************
// This example support/e2e.js is processed and
// loaded automatically before your test files.
//
// This is a great place to put global configuration and
// behavior that modifies Cypress.
//
// You can change the location of this file or turn off
// automatically serving support files with the
// 'supportFile' configuration option.
//
// You can read more here:
// https://on.cypress.io/configuration
// ***********************************************************
// Import commands.js using ES2015 syntax:
import './commands'
// Alternatively you can use CommonJS syntax:
// require('./commands')

View File

@@ -56,22 +56,6 @@ if(preg_match("/^(.*)\.(gif|jpg|png|jpeg|tiff|bmp|css|js|less|map|html|zip|rar|g
exit; exit;
} }
if(file_exists(BASE . 'config.local.php')) {
require_once BASE . 'config.local.php';
}
ini_set('log_errors', 1);
if(config('env') === 'dev') {
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);
}
else {
ini_set('display_errors', 0);
ini_set('display_startup_errors', 0);
error_reporting(E_ALL & ~E_DEPRECATED & ~E_STRICT);
}
if((!isset($config['installed']) || !$config['installed']) && file_exists(BASE . 'install')) if((!isset($config['installed']) || !$config['installed']) && file_exists(BASE . 'install'))
{ {
header('Location: ' . BASE_URL . 'install/'); header('Location: ' . BASE_URL . 'install/');
@@ -100,13 +84,11 @@ $twig->addGlobal('status', $status);
require_once SYSTEM . 'router.php'; require_once SYSTEM . 'router.php';
require SYSTEM . 'migrate.php';
$hooks->trigger(HOOK_STARTUP); $hooks->trigger(HOOK_STARTUP);
// anonymous usage statistics // anonymous usage statistics
// sent only when user agrees // sent only when user agrees
if(isset($config['anonymous_usage_statistics']) && $config['anonymous_usage_statistics']) { if(setting('core.anonymous_usage_statistics')) {
$report_time = 30 * 24 * 60 * 60; // report one time per 30 days $report_time = 30 * 24 * 60 * 60; // report one time per 30 days
$should_report = true; $should_report = true;
@@ -139,17 +121,16 @@ if(isset($config['anonymous_usage_statistics']) && $config['anonymous_usage_stat
} }
} }
if($config['views_counter']) if(setting('core.views_counter'))
require_once SYSTEM . 'counter.php'; require_once SYSTEM . 'counter.php';
if($config['visitors_counter']) if(setting('core.visitors_counter')) {
{
require_once SYSTEM . 'libs/visitors.php'; require_once SYSTEM . 'libs/visitors.php';
$visitors = new Visitors($config['visitors_counter_ttl']); $visitors = new Visitors(setting('core.visitors_counter_ttl'));
} }
// backward support for gesior // backward support for gesior
if($config['backward_support']) { if(setting('core.backward_support')) {
define('INITIALIZED', true); define('INITIALIZED', true);
$SQL = $db; $SQL = $db;
$layout_header = template_header(); $layout_header = template_header();
@@ -165,7 +146,8 @@ if($config['backward_support']) {
$config['site'] = &$config; $config['site'] = &$config;
$config['server'] = &$config['lua']; $config['server'] = &$config['lua'];
$config['site']['shop_system'] = $config['gifts_system']; $config['site']['shop_system'] = setting('core.gifts_system');
$config['site']['gallery_page'] = true;
if(!isset($config['vdarkborder'])) if(!isset($config['vdarkborder']))
$config['vdarkborder'] = '#505050'; $config['vdarkborder'] = '#505050';
@@ -178,8 +160,9 @@ if($config['backward_support']) {
$config['site']['serverinfo_page'] = true; $config['site']['serverinfo_page'] = true;
$config['site']['screenshot_page'] = true; $config['site']['screenshot_page'] = true;
if($config['forum'] != '') $forumSetting = setting('core.forum');
$config['forum_link'] = (strtolower($config['forum']) === 'site' ? getLink('forum') : $config['forum']); if($forumSetting != '')
$config['forum_link'] = (strtolower($forumSetting) === 'site' ? getLink('forum') : $forumSetting);
foreach($status as $key => $value) foreach($status as $key => $value)
$config['status']['serverStatus_' . $key] = $value; $config['status']['serverStatus_' . $key] = $value;

View File

@@ -38,4 +38,3 @@ if(!isset($error) || !$error) {
$error = true; $error = true;
} }
} }
?>

View File

@@ -1,4 +1,4 @@
SET @myaac_database_version = 33; SET @myaac_database_version = 36;
CREATE TABLE `myaac_account_actions` CREATE TABLE `myaac_account_actions`
( (
@@ -203,6 +203,7 @@ CREATE TABLE `myaac_monsters` (
`mana` int(11) NOT NULL DEFAULT 0, `mana` int(11) NOT NULL DEFAULT 0,
`exp` int(11) NOT NULL, `exp` int(11) NOT NULL,
`health` int(11) NOT NULL, `health` int(11) NOT NULL,
`look` VARCHAR(255) NOT NULL DEFAULT '',
`speed_lvl` int(11) NOT NULL default 1, `speed_lvl` int(11) NOT NULL default 1,
`use_haste` tinyint(1) NOT NULL, `use_haste` tinyint(1) NOT NULL,
`voices` text NOT NULL, `voices` text NOT NULL,
@@ -302,6 +303,16 @@ CREATE TABLE `myaac_gallery`
INSERT INTO `myaac_gallery` (`id`, `ordering`, `comment`, `image`, `thumb`, `author`) VALUES (NULL, 1, 'Demon', 'images/gallery/demon.jpg', 'images/gallery/demon_thumb.gif', 'MyAAC'); INSERT INTO `myaac_gallery` (`id`, `ordering`, `comment`, `image`, `thumb`, `author`) VALUES (NULL, 1, 'Demon', 'images/gallery/demon.jpg', 'images/gallery/demon_thumb.gif', 'MyAAC');
CREATE TABLE `myaac_settings`
(
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` VARCHAR(255) NOT NULL DEFAULT '',
`key` VARCHAR(255) NOT NULL DEFAULT '',
`value` TEXT NOT NULL,
PRIMARY KEY (`id`),
KEY `key` (`key`)
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8;
CREATE TABLE `myaac_spells` CREATE TABLE `myaac_spells`
( (
`id` INT(11) NOT NULL AUTO_INCREMENT, `id` INT(11) NOT NULL AUTO_INCREMENT,
@@ -330,6 +341,7 @@ CREATE TABLE `myaac_visitors`
`ip` VARCHAR(45) NOT NULL, `ip` VARCHAR(45) NOT NULL,
`lastvisit` INT(11) NOT NULL DEFAULT 0, `lastvisit` INT(11) NOT NULL DEFAULT 0,
`page` VARCHAR(2048) NOT NULL, `page` VARCHAR(2048) NOT NULL,
`user_agent` VARCHAR(255) NOT NULL DEFAULT '',
UNIQUE (`ip`) UNIQUE (`ip`)
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8; ) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8;

View File

@@ -1,4 +1,4 @@
We have detected that you don't have access to write to the system/cache directory. Under linux you can fix it by using this two command, where first one should be enough (for apache):<br/><br/><span class="console">chown -R www-data.www-data /var/www/*</span><br/><span class="console">chmod -R 660 system/cache</span> We have detected that you don't have access to write to the system/cache directory. Under linux you can fix it by using this two command, where first one should be enough (for apache):<br/><br/><span class="console">chown -R www-data.www-data /var/www/*</span><br/><span class="console">chmod -R 760 system/cache</span>
<style type="text/css"> <style type="text/css">
.console { .console {

View File

@@ -12,9 +12,7 @@ require SYSTEM . 'functions.php';
require BASE . 'install/includes/functions.php'; require BASE . 'install/includes/functions.php';
require BASE . 'install/includes/locale.php'; require BASE . 'install/includes/locale.php';
require SYSTEM . 'clients.conf.php'; require SYSTEM . 'clients.conf.php';
require LIBS . 'settings.php';
if(file_exists(BASE . 'config.local.php'))
require BASE . 'config.local.php';
// ignore undefined index from Twig autoloader // ignore undefined index from Twig autoloader
$config['env'] = 'prod'; $config['env'] = 'prod';
@@ -26,13 +24,13 @@ $twig = new Twig_Environment($twig_loader, array(
)); ));
// load installation status // load installation status
$step = isset($_POST['step']) ? $_POST['step'] : 'welcome'; $step = $_REQUEST['step'] ?? 'welcome';
$install_status = array(); $install_status = array();
if(file_exists(CACHE . 'install.txt')) { if(file_exists(CACHE . 'install.txt')) {
$install_status = unserialize(file_get_contents(CACHE . 'install.txt')); $install_status = unserialize(file_get_contents(CACHE . 'install.txt'));
if(!isset($_POST['step'])) { if(!isset($_REQUEST['step'])) {
$step = isset($install_status['step']) ? $install_status['step'] : ''; $step = isset($install_status['step']) ? $install_status['step'] : '';
} }
} }
@@ -70,7 +68,7 @@ if($step == 'database') {
$key = str_replace('var_', '', $key); $key = str_replace('var_', '', $key);
if(in_array($key, array('account', 'password', 'password_confirm', 'email', 'player_name'))) { if(in_array($key, array('account', 'account_id', 'password', 'password_confirm', 'email', 'player_name'))) {
continue; continue;
} }
@@ -91,10 +89,6 @@ if($step == 'database') {
break; break;
} }
} }
else if($key == 'mail_admin' && !Validator::email($value)) {
$errors[] = $locale['step_config_mail_admin_error'];
break;
}
else if($key == 'timezone' && !in_array($value, DateTimeZone::listIdentifiers())) { else if($key == 'timezone' && !in_array($value, DateTimeZone::listIdentifiers())) {
$errors[] = $locale['step_config_timezone_error']; $errors[] = $locale['step_config_timezone_error'];
break; break;
@@ -110,14 +104,12 @@ if($step == 'database') {
} }
} }
else if($step == 'admin') { else if($step == 'admin') {
$config_failed = true; if(!file_exists(BASE . 'config.local.php') || !isset($config['installed']) || !$config['installed']) {
if(file_exists(BASE . 'config.local.php') && isset($config['installed']) && $config['installed'] && isset($_SESSION['saved'])) {
$config_failed = false;
}
if($config_failed) {
$step = 'database'; $step = 'database';
} }
else {
$_SESSION['saved'] = true;
}
} }
else if($step == 'finish') { else if($step == 'finish') {
$email = $_SESSION['var_email']; $email = $_SESSION['var_email'];

View File

@@ -5,4 +5,3 @@ $twig->display('install.license.html.twig', array(
'license' => file_get_contents(BASE . 'LICENSE'), 'license' => file_get_contents(BASE . 'LICENSE'),
'buttons' => next_buttons() 'buttons' => next_buttons()
)); ));
?>

View File

@@ -18,4 +18,3 @@ $twig->display('install.config.html.twig', array(
'errors' => isset($errors) ? $errors : null, 'errors' => isset($errors) ? $errors : null,
'buttons' => next_buttons() 'buttons' => next_buttons()
)); ));
?>

View File

@@ -11,16 +11,12 @@ if(!isset($_SESSION['var_server_path'])) {
} }
if(!$error) { if(!$error) {
$content = "<?php"; $configToSave = [
$content .= PHP_EOL;
$content .= '// place for your configuration directives, so you can later easily update myaac';
$content .= PHP_EOL;
$content .= '$config[\'installed\'] = true;';
$content .= PHP_EOL;
// by default, set env to prod // by default, set env to prod
// user can disable when he wants // user can disable when he wants
$content .= '$config[\'env\'] = \'prod\'; // dev or prod'; 'env' => 'prod',
$content .= PHP_EOL; ];
foreach($_SESSION as $key => $value) foreach($_SESSION as $key => $value)
{ {
if(strpos($key, 'var_') !== false) if(strpos($key, 'var_') !== false)
@@ -32,17 +28,14 @@ if(!$error) {
$value .= '/'; $value .= '/';
} }
if($key === 'var_usage') { if(!in_array($key, ['var_usage', 'var_date_timezone', 'var_client', 'var_account', 'var_account_id', 'var_password', 'var_password_confirm', 'var_step', 'var_email', 'var_player_name'], true)) {
$content .= '$config[\'anonymous_usage_statistics\'] = ' . ((int)$value == 1 ? 'true' : 'false') . ';'; $configToSave[str_replace('var_', '', $key)] = $value;
$content .= PHP_EOL;
}
else if(!in_array($key, array('var_account', 'var_account_id', 'var_password', 'var_step', 'var_email', 'var_player_name'), true)) {
$content .= '$config[\'' . str_replace('var_', '', $key) . '\'] = \'' . $value . '\';';
$content .= PHP_EOL;
} }
} }
} }
$configToSave['cache_prefix'] = 'myaac_' . generateRandomString(8, true, false, true);
require BASE . 'install/includes/config.php'; require BASE . 'install/includes/config.php';
if(!$error) { if(!$error) {
@@ -55,38 +48,42 @@ if(!$error) {
error($database_error); error($database_error);
} }
else { else {
if(!$db->hasTable('accounts')) {
$tmp = str_replace('$TABLE$', 'accounts', $locale['step_database_error_table']);
error($tmp);
$error = true;
}
if(!$db->hasTable('players')) {
$tmp = str_replace('$TABLE$', 'players', $locale['step_database_error_table']);
error($tmp);
$error = true;
}
if(!$db->hasTable('guilds')) {
$tmp = str_replace('$TABLE$', 'guilds', $locale['step_database_error_table']);
error($tmp);
$error = true;
}
if(!$error) {
$twig->display('install.installer.html.twig', array( $twig->display('install.installer.html.twig', array(
'url' => 'tools/5-database.php', 'url' => 'tools/5-database.php',
'message' => $locale['loading_spinner'] 'message' => $locale['loading_spinner']
)); ));
if(!$error) { $content = '';
if(!Validator::email($_SESSION['var_mail_admin'])) { $saved = Settings::saveConfig($configToSave, BASE . 'config.local.php', $content);
error($locale['step_config_mail_admin_error']);
$error = true;
}
$content .= '$config[\'session_prefix\'] = \'myaac_' . generateRandomString(8, true, false, true, false) . '_\';';
$content .= PHP_EOL;
$content .= '$config[\'cache_prefix\'] = \'myaac_' . generateRandomString(8, true, false, true, false) . '_\';';
$saved = true;
if(!$error) {
$saved = file_put_contents(BASE . 'config.local.php', $content);
}
if($saved) { if($saved) {
success($locale['step_database_config_saved']); success($locale['step_database_config_saved']);
if(!$error) {
$_SESSION['saved'] = true; $_SESSION['saved'] = true;
} }
}
else { else {
$_SESSION['config_content'] = $content; $_SESSION['config_content'] = $content;
unset($_SESSION['saved']); unset($_SESSION['saved']);
$locale['step_database_error_file'] = str_replace('$FILE$', '<b>' . BASE . 'config.local.php</b>', $locale['step_database_error_file']); $locale['step_database_error_file'] = str_replace('$FILE$', '<b>' . BASE . 'config.php</b>', $locale['step_database_error_file']);
warning($locale['step_database_error_file'] . '<br/> error($locale['step_database_error_file'] . '<br/>
<textarea cols="70" rows="10">' . $content . '</textarea>'); <textarea cols="70" rows="10">' . $content . '</textarea>');
} }
} }
@@ -98,7 +95,7 @@ if(!$error) {
<div class="text-center m-3"> <div class="text-center m-3">
<form action="<?php echo BASE_URL; ?>install/" method="post"> <form action="<?php echo BASE_URL; ?>install/" method="post">
<input type="hidden" name="step" id="step" value="admin" /> <input type="hidden" name="step" id="step" value="admin" />
<?php echo next_buttons(true, $error ? false : true); <?php echo next_buttons(true, !$error);
?> ?>
</form> </form>
</div> </div>

View File

@@ -8,7 +8,7 @@ if(isset($config['installed']) && $config['installed'] && !isset($_SESSION['save
else { else {
require SYSTEM . 'init.php'; require SYSTEM . 'init.php';
if(!$error) { if(!$error) {
if(USE_ACCOUNT_NAME) if(USE_ACCOUNT_NAME || USE_ACCOUNT_NUMBER)
$account = isset($_SESSION['var_account']) ? $_SESSION['var_account'] : null; $account = isset($_SESSION['var_account']) ? $_SESSION['var_account'] : null;
else else
$account_id = isset($_SESSION['var_account_id']) ? $_SESSION['var_account_id'] : null; $account_id = isset($_SESSION['var_account_id']) ? $_SESSION['var_account_id'] : null;
@@ -65,7 +65,6 @@ else {
$new_account->setPassword(encrypt($password)); $new_account->setPassword(encrypt($password));
$new_account->setEMail($email); $new_account->setEMail($email);
$new_account->unblock();
$new_account->save(); $new_account->save();
$new_account->setCustomField('created', time()); $new_account->setCustomField('created', time());
@@ -117,12 +116,30 @@ else {
} }
} }
$settings = Settings::getInstance();
foreach($_SESSION as $key => $value) {
if (in_array($key, ['var_usage', 'var_date_timezone', 'var_client'])) {
if ($key == 'var_usage') {
$key = 'anonymous_usage_statistics';
$value = ((int)$value == 1 ? 'true' : 'false');
} elseif ($key == 'var_date_timezone') {
$key = 'date_timezone';
} elseif ($key == 'var_client') {
$key = 'client';
}
$settings->updateInDatabase('core', $key, $value);
}
}
success('Settings saved.');
$twig->display('install.installer.html.twig', array( $twig->display('install.installer.html.twig', array(
'url' => 'tools/7-finish.php', 'url' => 'tools/7-finish.php',
'message' => $locale['importing_spinner'] 'message' => $locale['importing_spinner']
)); ));
if(!isset($_SESSION['installed'])) { if(!isset($_SESSION['installed'])) {
if (!array_key_exists('CI', getenv())) {
$report_url = 'https://my-aac.org/report_install.php?v=' . MYAAC_VERSION . '&b=' . urlencode(BASE_URL); $report_url = 'https://my-aac.org/report_install.php?v=' . MYAAC_VERSION . '&b=' . urlencode(BASE_URL);
if (function_exists('curl_version')) if (function_exists('curl_version'))
{ {
@@ -135,6 +152,8 @@ else {
else if (ini_get('allow_url_fopen') ) { else if (ini_get('allow_url_fopen') ) {
file_get_contents($report_url); file_get_contents($report_url);
} }
}
$_SESSION['installed'] = true; $_SESSION['installed'] = true;
} }

View File

@@ -4,7 +4,7 @@
<meta http-equiv="Content-Type" content="text/html; charset=<?php echo $locale['encoding']; ?>" /> <meta http-equiv="Content-Type" content="text/html; charset=<?php echo $locale['encoding']; ?>" />
<meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1">
<title>MyAAC - <?php echo $locale['installation']; ?></title> <title>MyAAC - <?php echo $locale['installation']; ?></title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta1/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-giJF6kkoqNQ00vy+HMDP7azOuL0xtbfIcaT9wjKHr8RbDVddVHyTfAAsrekwKmP1" crossorigin="anonymous"> <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-rbsA2VBKQhggwzxH7pPCaAqO46MgnOM80zW1RWuH61DGLwZJEdK2Kadq2F9CUG65" crossorigin="anonymous">
<link rel="stylesheet" type="text/css" href="template/style.css" /> <link rel="stylesheet" type="text/css" href="template/style.css" />
<script type="text/javascript" src="<?php echo BASE_URL; ?>tools/js/jquery.min.js"></script> <script type="text/javascript" src="<?php echo BASE_URL; ?>tools/js/jquery.min.js"></script>
</head> </head>
@@ -29,7 +29,7 @@
$progress = ($i == 6) ? 100 : $i * 16; $progress = ($i == 6) ? 100 : $i * 16;
} }
echo '<li' . ($step == $value ? ' class="list-group-item active"' : ' class="list-group-item"') . '>' . ++$i . '. ' . $locale['step_' . $value] . '</li>'; echo '<li class="list-group-item' . ($step == $value ? ' active' : '') . '">' . ++$i . '. ' . $locale['step_' . $value] . '</li>';
} }
?> ?>

View File

@@ -23,24 +23,6 @@ if(!$error) {
} }
} }
if(!$db->hasTable('accounts')) {
$locale['step_database_error_table'] = str_replace('$TABLE$', 'accounts', $locale['step_database_error_table']);
error($locale['step_database_error_table']);
return;
}
if(!$db->hasTable('players')) {
$locale['step_database_error_table'] = str_replace('$TABLE$', 'players', $locale['step_database_error_table']);
error($locale['step_database_error_table']);
return;
}
if(!$db->hasTable('guilds')) {
$locale['step_database_error_table'] = str_replace('$TABLE$', 'guilds', $locale['step_database_error_table']);
error($locale['step_database_error_table']);
return;
}
if($db->hasTable(TABLE_PREFIX . 'account_actions')) { if($db->hasTable(TABLE_PREFIX . 'account_actions')) {
$locale['step_database_error_table_exist'] = str_replace('$TABLE$', TABLE_PREFIX . 'account_actions', $locale['step_database_error_table_exist']); $locale['step_database_error_table_exist'] = str_replace('$TABLE$', TABLE_PREFIX . 'account_actions', $locale['step_database_error_table_exist']);
warning($locale['step_database_error_table_exist']); warning($locale['step_database_error_table_exist']);
@@ -73,13 +55,8 @@ else {
success($locale['step_database_adding_field'] . ' accounts.key...'); success($locale['step_database_adding_field'] . ' accounts.key...');
} }
if(!$db->hasColumn('accounts', 'blocked')) {
if(query("ALTER TABLE `accounts` ADD `blocked` TINYINT(1) NOT NULL DEFAULT FALSE COMMENT 'internal usage' AFTER `key`;"))
success($locale['step_database_adding_field'] . ' accounts.blocked...');
}
if(!$db->hasColumn('accounts', 'created')) { if(!$db->hasColumn('accounts', 'created')) {
if(query("ALTER TABLE `accounts` ADD `created` INT(11) NOT NULL DEFAULT 0 AFTER `" . ($db->hasColumn('accounts', 'group_id') ? 'group_id' : 'blocked') . "`;")) if(query("ALTER TABLE `accounts` ADD `created` INT(11) NOT NULL DEFAULT 0 AFTER `" . ($db->hasColumn('accounts', 'group_id') ? 'group_id' : 'key') . "`;"))
success($locale['step_database_adding_field'] . ' accounts.created...'); success($locale['step_database_adding_field'] . ' accounts.created...');
} }

View File

@@ -11,11 +11,11 @@ ini_set('max_execution_time', 300);
ob_implicit_flush(); ob_implicit_flush();
ob_end_flush(); ob_end_flush();
header('X-Accel-Buffering: no'); header('X-Accel-Buffering: no');
/*
if(isset($config['installed']) && $config['installed'] && !isset($_SESSION['saved'])) { if(isset($config['installed']) && $config['installed'] && !isset($_SESSION['saved'])) {
warning($locale['already_installed']); warning($locale['already_installed']);
return; return;
} }*/
require SYSTEM . 'init.php'; require SYSTEM . 'init.php';
@@ -51,13 +51,6 @@ DataLoader::load();
// update config.highscores_ids_hidden // update config.highscores_ids_hidden
require_once SYSTEM . 'migrations/20.php'; require_once SYSTEM . 'migrations/20.php';
$database_migration_20 = true;
$content = '';
if(!databaseMigration20($content)) {
$locale['step_database_error_file'] = str_replace('$FILE$', '<b>' . BASE . 'config.local.php</b>', $locale['step_database_error_file']);
warning($locale['step_database_error_file'] . '<br/>
<textarea cols="70" rows="10">' . $content . '</textarea>');
}
// add z_polls tables // add z_polls tables
require_once SYSTEM . 'migrations/22.php'; require_once SYSTEM . 'migrations/22.php';

View File

@@ -1,7 +1,5 @@
<?php <?php
require_once 'common.php'; require_once 'common.php';
require_once 'config.php';
require_once 'config.local.php';
require_once SYSTEM . 'functions.php'; require_once SYSTEM . 'functions.php';
require_once SYSTEM . 'init.php'; require_once SYSTEM . 'init.php';
require_once SYSTEM . 'status.php'; require_once SYSTEM . 'status.php';

View File

@@ -7,6 +7,23 @@ server {
# increase max file upload # increase max file upload
client_max_body_size 10M; client_max_body_size 10M;
# this is very important, be sure its in your nginx conf - it prevents access to logs etc.
location ~ /system {
deny all;
return 404;
}
# block .htaccess
location ~ /\.ht {
deny all;
}
# block git files and folders
location ~ /\.git {
return 404;
deny all;
}
location / { location / {
try_files $uri $uri/ /index.php; try_files $uri $uri/ /index.php;
} }
@@ -15,15 +32,6 @@ server {
include snippets/fastcgi-php.conf; include snippets/fastcgi-php.conf;
fastcgi_read_timeout 240; fastcgi_read_timeout 240;
fastcgi_pass unix:/var/run/php/php7.4-fpm.sock; fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;
# for ubuntu 22.04+ it will be php8.1-sock # for ubuntu 22.04+ it will be php8.1-fpm.sock
}
location ~ /\.ht {
deny all;
}
location /system {
deny all;
return 404;
} }
} }

1927
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

5
package.json Normal file
View File

@@ -0,0 +1,5 @@
{
"devDependencies": {
"cypress": "^12.12.0"
}
}

View File

@@ -1,11 +1,3 @@
<IfModule mod_autoindex.c> <IfModule mod_autoindex.c>
Options -Indexes Options -Indexes
</IfModule> </IfModule>
<IfVersion < 2.4>
order allow,deny
deny from all
</IfVersion>
<IfVersion >= 2.4>
Require all denied
</IfVersion>

View File

@@ -1,3 +1,3 @@
To play on {{ config.lua.serverName }} you need an account. To play on {{ config.lua.serverName }} you need an account.
All you have to do to create your new account is to enter an account {% if constant('USE_ACCOUNT_NAME') %}name{% else %}number{% endif %}, password{% if config.recaptcha_enabled %}, confirm reCAPTCHA{% endif %}{% if config.account_country %}, country{% endif %} and your email address. All you have to do to create your new account is to enter an account {% if constant('USE_ACCOUNT_NAME') %}name{% else %}number{% endif %}, password{% if config.account_country %}, country{% endif %} and your email address.
Also you have to agree to the terms presented below. If you have done so, your account {% if constant('USE_ACCOUNT_NAME') %}name{% else %}number{% endif %} will be shown on the following page and your account password will be sent to your email address along with further instructions. If you do not receive the email with your password, please check your spam filter.<br/><br/> Also you have to agree to the terms presented below. If you have done so, your account {% if constant('USE_ACCOUNT_NAME') %}name{% else %}number{% endif %} will be shown on the following page and your account password will be sent to your email address along with further instructions. If you do not receive the email with your password, please check your spam filter.<br/><br/>

View File

@@ -39,5 +39,6 @@
"redirect_from": "/redirectExample", "redirect_from": "/redirectExample",
"redirect_to": "account/manage" "redirect_to": "account/manage"
} }
} },
"settings": "plugins/your-plugin-folder/settings.php"
} }

View File

@@ -22,7 +22,7 @@ if [ $1 = "prepare" ]; then
mkdir -p tmp mkdir -p tmp
# get myaac from git archive # get myaac from git archive
git archive --format zip --output tmp/myaac.zip master git archive --format zip --output tmp/myaac.zip develop
cd tmp/ || exit cd tmp/ || exit
@@ -35,6 +35,11 @@ if [ $1 = "prepare" ]; then
unzip -q myaac.zip -d $dir unzip -q myaac.zip -d $dir
rm myaac.zip rm myaac.zip
cd $dir || exit
# dependencies
composer install --no-dev
echo "Now you can make changes to $dir. When you are ready, type 'release.sh pack'" echo "Now you can make changes to $dir. When you are ready, type 'release.sh pack'"
exit exit
fi fi

View File

@@ -1,206 +0,0 @@
<?php
namespace MyAAC;
$loader = new \MyAAC\Psr4AutoloaderClass;
// register the autoloader
$loader->register();
// register the base directories for the namespace prefix
$loader->addNamespace('Composer\Semver', LIBS . 'semver');
$loader->addNamespace('Twig', LIBS . 'Twig');
/**
* An example of a general-purpose implementation that includes the optional
* functionality of allowing multiple base directories for a single namespace
* prefix.
*
* Given a foo-bar package of classes in the file system at the following
* paths ...
*
* /path/to/packages/foo-bar/
* src/
* Baz.php # Foo\Bar\Baz
* Qux/
* Quux.php # Foo\Bar\Qux\Quux
* tests/
* BazTest.php # Foo\Bar\BazTest
* Qux/
* QuuxTest.php # Foo\Bar\Qux\QuuxTest
*
* ... add the path to the class files for the \Foo\Bar\ namespace prefix
* as follows:
*
* <?php
* // instantiate the loader
* $loader = new \Example\Psr4AutoloaderClass;
*
* // register the autoloader
* $loader->register();
*
* // register the base directories for the namespace prefix
* $loader->addNamespace('Foo\Bar', '/path/to/packages/foo-bar/src');
* $loader->addNamespace('Foo\Bar', '/path/to/packages/foo-bar/tests');
*
* The following line would cause the autoloader to attempt to load the
* \Foo\Bar\Qux\Quux class from /path/to/packages/foo-bar/src/Qux/Quux.php:
*
* <?php
* new \Foo\Bar\Qux\Quux;
*
* The following line would cause the autoloader to attempt to load the
* \Foo\Bar\Qux\QuuxTest class from /path/to/packages/foo-bar/tests/Qux/QuuxTest.php:
*
* <?php
* new \Foo\Bar\Qux\QuuxTest;
*/
class Psr4AutoloaderClass
{
/**
* An associative array where the key is a namespace prefix and the value
* is an array of base directories for classes in that namespace.
*
* @var array
*/
protected $prefixes = array();
/**
* Register loader with SPL autoloader stack.
*
* @return void
*/
public function register()
{
spl_autoload_register(array($this, 'loadClass'));
}
/**
* Adds a base directory for a namespace prefix.
*
* @param string $prefix The namespace prefix.
* @param string $base_dir A base directory for class files in the
* namespace.
* @param bool $prepend If true, prepend the base directory to the stack
* instead of appending it; this causes it to be searched first rather
* than last.
* @return void
*/
public function addNamespace($prefix, $base_dir, $prepend = false)
{
// normalize namespace prefix
$prefix = trim($prefix, '\\') . '\\';
// normalize the base directory with a trailing separator
$base_dir = rtrim($base_dir, DIRECTORY_SEPARATOR) . '/';
// initialize the namespace prefix array
if (isset($this->prefixes[$prefix]) === false) {
$this->prefixes[$prefix] = array();
}
// retain the base directory for the namespace prefix
if ($prepend) {
array_unshift($this->prefixes[$prefix], $base_dir);
} else {
array_push($this->prefixes[$prefix], $base_dir);
}
}
/**
* Loads the class file for a given class name.
*
* @param string $class The fully-qualified class name.
* @return mixed The mapped file name on success, or boolean false on
* failure.
*/
public function loadClass($class)
{
if (0 === strpos($class, 'Twig_')) {
$file = LIBS . 'Twig/' . str_replace(array('_', "\0"), array('/', ''), $class).'.php';
if((config('env') === 'dev') && !is_file($file)) {
return false;
}
require $file;
return false;
}
// the current namespace prefix
$prefix = $class;
// work backwards through the namespace names of the fully-qualified
// class name to find a mapped file name
while (false !== $pos = strrpos($prefix, '\\')) {
// retain the trailing namespace separator in the prefix
$prefix = substr($class, 0, $pos + 1);
// the rest is the relative class name
$relative_class = substr($class, $pos + 1);
// try to load a mapped file for the prefix and relative class
$mapped_file = $this->loadMappedFile($prefix, $relative_class);
if ($mapped_file) {
return $mapped_file;
}
// remove the trailing namespace separator for the next iteration
// of strrpos()
$prefix = rtrim($prefix, '\\');
}
// never found a mapped file
return false;
}
/**
* Load the mapped file for a namespace prefix and relative class.
*
* @param string $prefix The namespace prefix.
* @param string $relative_class The relative class name.
* @return mixed Boolean false if no mapped file can be loaded, or the
* name of the mapped file that was loaded.
*/
protected function loadMappedFile($prefix, $relative_class)
{
// are there any base directories for this namespace prefix?
if (isset($this->prefixes[$prefix]) === false) {
return false;
}
// look through base directories for this namespace prefix
foreach ($this->prefixes[$prefix] as $base_dir) {
// replace the namespace prefix with the base directory,
// replace namespace separators with directory separators
// in the relative class name, append with .php
$file = $base_dir
. str_replace('\\', '/', $relative_class)
. '.php';
// if the mapped file exists, require it
if ($this->requireFile($file)) {
// yes, we're done
return $file;
}
}
// never found it
return false;
}
/**
* If a file exists, require it from the file system.
*
* @param string $file The file to require.
* @return bool True if the file exists, false if not.
*/
protected function requireFile($file)
{
if (config('env') !== 'dev' || file_exists($file)) {
require $file;
return true;
}
return false;
}
}

View File

@@ -9,7 +9,30 @@
*/ */
defined('MYAAC') or die('Direct access not allowed!'); defined('MYAAC') or die('Direct access not allowed!');
class Player extends OTS_Player {} class Account extends OTS_Account {
class Guild extends OTS_Guild {} public function loadById($id) {
$this->load($id);
}
public function loadByName($name) {
$this->find($name);
}
}
class Player extends OTS_Player {
public function loadById($id) {
$this->load($id);
}
public function loadByName($name) {
$this->find($name);
}
}
class Guild extends OTS_Guild {
public function loadById($id) {
$this->load($id);
}
public function loadByName($name) {
$this->find($name);
}
}
class GuildRank extends OTS_GuildRank {} class GuildRank extends OTS_GuildRank {}
class House extends OTS_House {} class House extends OTS_House {}

103
system/compat/config.php Normal file
View File

@@ -0,0 +1,103 @@
<?php
$deprecatedConfig = [
'date_timezone',
'genders',
'template',
'template_allow_change',
'vocations_amount',
'vocations',
'client',
'session_prefix',
'friendly_urls',
'backward_support',
'charset',
'meta_description',
'meta_keywords',
'footer',
'database_encryption' => 'database_hash',
//'language',
'visitors_counter',
'visitors_counter_ttl',
'views_counter',
'outfit_images_url',
'outfit_images_wrong_looktypes',
'item_images_url',
'account_country',
'towns',
'quests',
'character_samples',
'character_towns',
'characters_per_account',
'characters_search_limit',
'news_author',
'news_limit',
'news_ticker_limit',
'news_date_format',
'highscores_groups_hidden',
'highscores_ids_hidden',
'online_record',
'online_vocations',
'online_vocations_images',
'online_skulls',
'online_outfit',
'online_afk',
'team_display_outfit' => 'team_outfit',
'team_display_status' => 'team_status',
'team_display_world' => 'team_world',
'team_display_lastlogin' => 'team_lastlogin',
'last_kills_limit',
'multiworld',
'forum',
'signature_enabled',
'signature_type',
'signature_cache_time',
'signature_browser_cache',
'gifts_system',
'status_enabled',
'status_ip',
'status_port',
'mail_enabled',
'account_login_by_email',
'account_login_by_email_fallback',
'account_mail_verify',
'account_create_character_create',
'account_change_character_name',
'account_change_character_name_points' => 'account_change_character_name_price',
'account_change_character_sex',
'account_change_character_sex_points' => 'account_change_character_name_price',
];
foreach ($deprecatedConfig as $key => $value) {
config(
[
(is_string($key) ? $key : $value),
setting('core.'.$value)
]
);
//var_dump($settings['core.'.$value]['value']);
}
$deprecatedConfigCharacters = [
'level',
'experience',
'magic_level',
'balance',
'marriage_info' => 'marriage',
'outfit',
'creation_date',
'quests',
'skills',
'equipment',
'frags',
'deleted',
];
$tmp = [];
foreach ($deprecatedConfigCharacters as $key => $value) {
$tmp[(is_string($key) ? $key : $value)] = setting('core.characters_'.$value);
}
config(['characters', $tmp]);
unset($tmp);

View File

@@ -10,6 +10,10 @@
defined('MYAAC') or die('Direct access not allowed!'); defined('MYAAC') or die('Direct access not allowed!');
switch($page) switch($page)
{ {
case 'adminpanel':
header('Location: ' . ADMIN_URL);
die;
case 'createaccount': case 'createaccount':
$page = 'account/create'; $page = 'account/create';
break; break;
@@ -30,6 +34,7 @@ switch($page)
$page = 'news'; $page = 'news';
break; break;
case 'archive':
case 'newsarchive': case 'newsarchive':
$page = 'news/archive'; $page = 'news/archive';
break; break;

View File

@@ -51,4 +51,3 @@ else
updateDatabaseConfig('views_counter', $views_counter); // update counter updateDatabaseConfig('views_counter', $views_counter); // update counter
} }
} }
?>

View File

@@ -9,7 +9,11 @@
*/ */
defined('MYAAC') or die('Direct access not allowed!'); defined('MYAAC') or die('Direct access not allowed!');
if(!isset($config['database_user'][0], $config['database_password'][0], $config['database_name'][0])) if (!isset($config['database_overwrite'])) {
$config['database_overwrite'] = false;
}
if(!$config['database_overwrite'] && !isset($config['database_user'][0], $config['database_password'][0], $config['database_name'][0]))
{ {
if(isset($config['lua']['sqlType'])) {// tfs 0.3 if(isset($config['lua']['sqlType'])) {// tfs 0.3
if(isset($config['lua']['mysqlHost'])) {// tfs 0.2 if(isset($config['lua']['mysqlHost'])) {// tfs 0.2

View File

@@ -1,4 +1,25 @@
<?php <?php
/**
* Exception handler
*
* @package MyAAC
* @author Slawkens <slawkens@gmail.com>
* @copyright 2023 MyAAC
* @link https://my-aac.org
*/
if (class_exists(\Whoops\Run::class)) {
$whoops = new \Whoops\Run;
if(IS_CLI) {
$whoops->pushHandler(new \Whoops\Handler\PlainTextHandler);
}
else {
$whoops->pushHandler(new \Whoops\Handler\PrettyPageHandler);
}
$whoops->register();
return;
}
require LIBS . 'SensitiveException.php'; require LIBS . 'SensitiveException.php';
@@ -23,6 +44,8 @@ function exception_handler($exception) {
$backtrace_formatted = nl2br($exception->getTraceAsString()); $backtrace_formatted = nl2br($exception->getTraceAsString());
$message = $message . "<br/><br/>File: {$exception->getFile()}<br/>Line: {$exception->getLine()}";
// display basic error message without template // display basic error message without template
// template is missing, why? probably someone deleted templates dir, or it wasn't downloaded right // template is missing, why? probably someone deleted templates dir, or it wasn't downloaded right
$template_file = SYSTEM . 'templates/exception.html.twig'; $template_file = SYSTEM . 'templates/exception.html.twig';

View File

@@ -7,12 +7,11 @@
* @copyright 2019 MyAAC * @copyright 2019 MyAAC
* @link https://my-aac.org * @link https://my-aac.org
*/ */
defined('MYAAC') or die('Direct access not allowed!');
use PHPMailer\PHPMailer\PHPMailer; use PHPMailer\PHPMailer\PHPMailer;
use Twig\Loader\ArrayLoader as Twig_ArrayLoader; use Twig\Loader\ArrayLoader as Twig_ArrayLoader;
defined('MYAAC') or die('Direct access not allowed!');
function message($message, $type, $return) function message($message, $type, $return)
{ {
if(IS_CLI) { if(IS_CLI) {
@@ -45,43 +44,37 @@ function error($message, $return = false) {
return message($message, ((defined('MYAAC_INSTALL') || defined('MYAAC_ADMIN')) ? 'danger' : 'error'), $return); return message($message, ((defined('MYAAC_INSTALL') || defined('MYAAC_ADMIN')) ? 'danger' : 'error'), $return);
} }
function longToIp($ip) function longToIp($ip): string
{ {
$exp = explode(".", long2ip($ip)); $exp = explode(".", long2ip($ip));
return $exp[3].".".$exp[2].".".$exp[1].".".$exp[0]; return $exp[3].".".$exp[2].".".$exp[1].".".$exp[0];
} }
function generateLink($url, $name, $blank = false) { function generateLink($url, $name, $blank = false): string {
return '<a href="' . $url . '"' . ($blank ? ' target="_blank"' : '') . '>' . $name . '</a>'; return '<a href="' . $url . '"' . ($blank ? ' target="_blank"' : '') . '>' . $name . '</a>';
} }
function getFullLink($page, $name, $blank = false) { function getFullLink($page, $name, $blank = false): string {
return generateLink(getLink($page), $name, $blank); return generateLink(getLink($page), $name, $blank);
} }
function getLink($page, $action = null) function getLink($page, $action = null): string {
{ return BASE_URL . (setting('core.friendly_urls') ? '' : 'index.php/') . $page . ($action ? '/' . $action : '');
global $config;
return BASE_URL . ($config['friendly_urls'] ? '' : 'index.php/') . $page . ($action ? '/' . $action : '');
} }
function internalLayoutLink($page, $action = null) {return getLink($page, $action);} function internalLayoutLink($page, $action = null): string {
return getLink($page, $action);
function getForumThreadLink($thread_id, $page = NULL)
{
global $config;
return BASE_URL . ($config['friendly_urls'] ? '' : 'index.php/') . 'forum/thread/' . (int)$thread_id . (isset($page) ? '/' . $page : '');
} }
function getForumBoardLink($board_id, $page = NULL) function getForumThreadLink($thread_id, $page = NULL): string {
{ return BASE_URL . (setting('core.friendly_urls') ? '' : 'index.php/') . 'forum/thread/' . (int)$thread_id . (isset($page) ? '/' . $page : '');
global $config;
return BASE_URL . ($config['friendly_urls'] ? '' : 'index.php/') . 'forum/board/' . (int)$board_id . (isset($page) ? '/' . $page : '');
} }
function getPlayerLink($name, $generate = true) function getForumBoardLink($board_id, $page = NULL): string {
{ return BASE_URL . (setting('core.friendly_urls') ? '' : 'index.php/') . 'forum/board/' . (int)$board_id . (isset($page) ? '/' . $page : '');
global $config; }
function getPlayerLink($name, $generate = true): string
{
if(is_numeric($name)) if(is_numeric($name))
{ {
$player = new OTS_Player(); $player = new OTS_Player();
@@ -90,25 +83,23 @@ function getPlayerLink($name, $generate = true)
$name = $player->getName(); $name = $player->getName();
} }
$url = BASE_URL . ($config['friendly_urls'] ? '' : 'index.php/') . 'characters/' . urlencode($name); $url = BASE_URL . (setting('core.friendly_urls') ? '' : 'index.php/') . 'characters/' . urlencode($name);
if(!$generate) return $url; if(!$generate) return $url;
return generateLink($url, $name); return generateLink($url, $name);
} }
function getMonsterLink($name, $generate = true) function getMonsterLink($name, $generate = true): string
{ {
global $config; $url = BASE_URL . (setting('core.friendly_urls') ? '' : 'index.php/') . 'creatures/' . urlencode($name);
$url = BASE_URL . ($config['friendly_urls'] ? '' : 'index.php/') . 'creatures/' . urlencode($name);
if(!$generate) return $url; if(!$generate) return $url;
return generateLink($url, $name); return generateLink($url, $name);
} }
function getHouseLink($name, $generate = true) function getHouseLink($name, $generate = true): string
{ {
global $db, $config; global $db;
if(is_numeric($name)) if(is_numeric($name))
{ {
@@ -118,25 +109,22 @@ function getHouseLink($name, $generate = true)
$name = $house->fetchColumn(); $name = $house->fetchColumn();
} }
$url = BASE_URL . ($config['friendly_urls'] ? '' : 'index.php/') . 'houses/' . urlencode($name); $url = BASE_URL . (setting('core.friendly_urls') ? '' : 'index.php/') . 'houses/' . urlencode($name);
if(!$generate) return $url; if(!$generate) return $url;
return generateLink($url, $name); return generateLink($url, $name);
} }
function getGuildLink($name, $generate = true) function getGuildLink($name, $generate = true): string
{ {
global $db, $config; if(is_numeric($name)) {
$name = getGuildNameById($name);
if(is_numeric($name)) if ($name === false) {
{ $name = 'Unknown';
$guild = $db->query( }
'SELECT `name` FROM `guilds` WHERE `id` = ' . (int)$name);
if($guild->rowCount() > 0)
$name = $guild->fetchColumn();
} }
$url = BASE_URL . ($config['friendly_urls'] ? '' : 'index.php/') . 'guilds/' . urlencode($name); $url = BASE_URL . (setting('core.friendly_urls') ? '' : 'index.php/') . 'guilds/' . urlencode($name);
if(!$generate) return $url; if(!$generate) return $url;
return generateLink($url, $name); return generateLink($url, $name);
@@ -182,7 +170,7 @@ function getItemRarity($chance) {
return ''; return '';
} }
function getFlagImage($country) function getFlagImage($country): string
{ {
if(!isset($country[0])) if(!isset($country[0]))
return ''; return '';
@@ -204,7 +192,7 @@ function getFlagImage($country)
* @param mixed $v Variable to check. * @param mixed $v Variable to check.
* @return bool Value boolean status. * @return bool Value boolean status.
*/ */
function getBoolean($v) function getBoolean($v): bool
{ {
if(is_bool($v)) { if(is_bool($v)) {
return $v; return $v;
@@ -227,7 +215,7 @@ function getBoolean($v)
* @param bool $special Should special characters by used? * @param bool $special Should special characters by used?
* @return string Generated string. * @return string Generated string.
*/ */
function generateRandomString($length, $lowCase = true, $upCase = false, $numeric = false, $special = false) function generateRandomString($length, $lowCase = true, $upCase = false, $numeric = false, $special = false): string
{ {
$characters = ''; $characters = '';
if($lowCase) if($lowCase)
@@ -467,7 +455,7 @@ function tickers()
* Types: head_start, head_end, body_start, body_end, center_top * Types: head_start, head_end, body_start, body_end, center_top
* *
*/ */
function template_place_holder($type) function template_place_holder($type): string
{ {
global $twig, $template_place_holders; global $twig, $template_place_holders;
$ret = ''; $ret = '';
@@ -491,7 +479,7 @@ function template_place_holder($type)
/** /**
* Returns <head> content to be used by templates. * Returns <head> content to be used by templates.
*/ */
function template_header($is_admin = false) function template_header($is_admin = false): string
{ {
global $title_full, $config, $twig; global $title_full, $config, $twig;
$charset = isset($config['charset']) ? $config['charset'] : 'utf-8'; $charset = isset($config['charset']) ? $config['charset'] : 'utf-8';
@@ -508,29 +496,32 @@ function template_header($is_admin = false)
/** /**
* Returns footer content to be used by templates. * Returns footer content to be used by templates.
*/ */
function template_footer() function template_footer(): string
{ {
global $config, $views_counter; global $views_counter;
$ret = ''; $ret = '';
if(admin()) if(admin()) {
$ret .= generateLink(ADMIN_URL, 'Admin Panel', true); $ret .= generateLink(ADMIN_URL, 'Admin Panel', true);
}
if($config['visitors_counter']) if(setting('core.visitors_counter')) {
{
global $visitors; global $visitors;
$amount = $visitors->getAmountVisitors(); $amount = $visitors->getAmountVisitors();
$ret .= '<br/>Currently there ' . ($amount > 1 ? 'are' : 'is') . ' ' . $amount . ' visitor' . ($amount > 1 ? 's' : '') . '.'; $ret .= '<br/>Currently there ' . ($amount > 1 ? 'are' : 'is') . ' ' . $amount . ' visitor' . ($amount > 1 ? 's' : '') . '.';
} }
if($config['views_counter']) if(setting('core.views_counter')) {
$ret .= '<br/>Page has been viewed ' . $views_counter . ' times.'; $ret .= '<br/>Page has been viewed ' . $views_counter . ' times.';
}
if(config('footer_show_load_time')) { if(setting('core.footer_load_time')) {
$ret .= '<br/>Load time: ' . round(microtime(true) - START_TIME, 4) . ' seconds.'; $ret .= '<br/>Load time: ' . round(microtime(true) - START_TIME, 4) . ' seconds.';
} }
if(isset($config['footer'][0])) $settingFooter = setting('core.footer');
$ret .= '<br/>' . $config['footer']; if(isset($settingFooter[0])) {
$ret .= '<br/>' . $settingFooter;
}
// please respect my work and help spreading the word, thanks! // please respect my work and help spreading the word, thanks!
return $ret . '<br/>' . base64_decode('UG93ZXJlZCBieSA8YSBocmVmPSJodHRwOi8vbXktYWFjLm9yZyIgdGFyZ2V0PSJfYmxhbmsiPk15QUFDLjwvYT4='); return $ret . '<br/>' . base64_decode('UG93ZXJlZCBieSA8YSBocmVmPSJodHRwOi8vbXktYWFjLm9yZyIgdGFyZ2V0PSJfYmxhbmsiPk15QUFDLjwvYT4=');
@@ -538,8 +529,8 @@ function template_footer()
function template_ga_code() function template_ga_code()
{ {
global $config, $twig; global $twig;
if(!isset($config['google_analytics_id'][0])) if(!isset(setting('core.google_analytics_id')[0]))
return ''; return '';
return $twig->render('google_analytics.html.twig'); return $twig->render('google_analytics.html.twig');
@@ -756,10 +747,10 @@ function get_browser_languages()
{ {
$ret = array(); $ret = array();
$acceptLang = $_SERVER['HTTP_ACCEPT_LANGUAGE']; if(empty($_SERVER['HTTP_ACCEPT_LANGUAGE']))
if(!isset($acceptLang[0]))
return $ret; return $ret;
$acceptLang = $_SERVER['HTTP_ACCEPT_LANGUAGE'];
$languages = strtolower($acceptLang); $languages = strtolower($acceptLang);
// $languages = 'pl,en-us;q=0.7,en;q=0.3 '; // $languages = 'pl,en-us;q=0.7,en;q=0.3 ';
// need to remove spaces from strings to avoid error // need to remove spaces from strings to avoid error
@@ -792,16 +783,21 @@ function get_templates()
* Generates list of installed plugins * Generates list of installed plugins
* @return array $plugins * @return array $plugins
*/ */
function get_plugins() function get_plugins($disabled = false): array
{ {
$ret = array(); $ret = [];
$path = PLUGINS; $path = PLUGINS;
foreach(scandir($path, 0) as $file) { foreach(scandir($path, SCANDIR_SORT_ASCENDING) as $file) {
$file_ext = pathinfo($file, PATHINFO_EXTENSION); $file_ext = pathinfo($file, PATHINFO_EXTENSION);
$file_name = pathinfo($file, PATHINFO_FILENAME); $file_name = pathinfo($file, PATHINFO_FILENAME);
if ($file === '.' || $file === '..' || $file === 'disabled' || $file === 'example.json' || $file_ext !== 'json' || is_dir($path . $file)) if ($file === '.' || $file === '..' || $file === 'example.json' || $file_ext !== 'json' || is_dir($path . $file)) {
continue; continue;
}
if (!$disabled && strpos($file, 'disabled.') !== false) {
continue;
}
$ret[] = str_replace('.json', '', $file_name); $ret[] = str_replace('.json', '', $file_name);
} }
@@ -819,7 +815,7 @@ function getWorldName($id)
/** /**
* Mailing users. * Mailing users.
* $config['mail_enabled'] have to be enabled. * Mailing has to be enabled in settings (in Admin Panel).
* *
* @param string $to Recipient email address. * @param string $to Recipient email address.
* @param string $subject Subject of the message. * @param string $subject Subject of the message.
@@ -831,8 +827,9 @@ function _mail($to, $subject, $body, $altBody = '', $add_html_tags = true)
{ {
global $mailer, $config; global $mailer, $config;
if (!config('mail_enabled')) { if (!setting('core.mail_enabled')) {
log_append('mailer-error.log', '_mail() function has been used, but config.mail_enabled is disabled.'); log_append('mailer-error.log', '_mail() function has been used, but Mail Support is disabled.');
return false;
} }
if(!$mailer) if(!$mailer)
@@ -844,47 +841,60 @@ function _mail($to, $subject, $body, $altBody = '', $add_html_tags = true)
$mailer->clearAllRecipients(); $mailer->clearAllRecipients();
} }
$signature_html = ''; $signature_html = setting('core.mail_signature_html');
if(isset($config['mail_signature']['html']))
$signature_html = $config['mail_signature']['html'];
if($add_html_tags && isset($body[0])) if($add_html_tags && isset($body[0]))
$tmp_body = '<html><head></head><body>' . $body . '<br/><br/>' . $signature_html . '</body></html>'; $tmp_body = '<html><head></head><body>' . $body . '<br/><br/>' . $signature_html . '</body></html>';
else else
$tmp_body = $body . '<br/><br/>' . $signature_html; $tmp_body = $body . '<br/><br/>' . $signature_html;
if($config['smtp_enabled']) define('MAIL_MAIL', 0);
define('MAIL_SMTP', 1);
$mailOption = setting('core.mail_option');
if($mailOption == MAIL_SMTP)
{ {
$mailer->isSMTP(); $mailer->isSMTP();
$mailer->Host = $config['smtp_host']; $mailer->Host = setting('core.smtp_host');
$mailer->Port = (int)$config['smtp_port']; $mailer->Port = setting('core.smtp_port');
$mailer->SMTPAuth = $config['smtp_auth']; $mailer->SMTPAuth = setting('core.smtp_auth');
$mailer->Username = $config['smtp_user']; $mailer->Username = setting('core.smtp_user');
$mailer->Password = $config['smtp_pass']; $mailer->Password = setting('core.smtp_pass');
$mailer->SMTPSecure = isset($config['smtp_secure']) ? $config['smtp_secure'] : '';
define('SMTP_SECURITY_NONE', 0);
define('SMTP_SECURITY_SSL', 1);
define('SMTP_SECURITY_TLS', 2);
$security = setting('core.smtp_security');
$tmp = '';
if ($security === SMTP_SECURITY_SSL) {
$tmp = 'ssl';
}
else if ($security == SMTP_SECURITY_TLS) {
$tmp = 'tls';
}
$mailer->SMTPSecure = $tmp;
} }
else { else {
$mailer->isMail(); $mailer->isMail();
} }
$mailer->isHTML(isset($body[0]) > 0); $mailer->isHTML(isset($body[0]) > 0);
$mailer->From = $config['mail_address']; $mailer->From = setting('core.mail_address');
$mailer->Sender = $config['mail_address']; $mailer->Sender = setting('core.mail_address');
$mailer->CharSet = 'utf-8'; $mailer->CharSet = 'utf-8';
$mailer->FromName = $config['lua']['serverName']; $mailer->FromName = $config['lua']['serverName'];
$mailer->Subject = $subject; $mailer->Subject = $subject;
$mailer->addAddress($to); $mailer->addAddress($to);
$mailer->Body = $tmp_body; $mailer->Body = $tmp_body;
if(config('smtp_debug')) { if(setting('core.smtp_debug')) {
$mailer->SMTPDebug = 2; $mailer->SMTPDebug = 2;
$mailer->Debugoutput = 'echo'; $mailer->Debugoutput = 'echo';
} }
$signature_plain = ''; $signature_plain = setting('core.mail_signature_plain');
if(isset($config['mail_signature']['plain']))
$signature_plain = $config['mail_signature']['plain'];
if(isset($altBody[0])) { if(isset($altBody[0])) {
$mailer->AltBody = $altBody . $signature_plain; $mailer->AltBody = $altBody . $signature_plain;
} }
@@ -926,8 +936,8 @@ function load_config_lua($filename)
$config_file = $filename; $config_file = $filename;
if(!@file_exists($config_file)) if(!@file_exists($config_file))
{ {
log_append('error.log', '[load_config_file] Fatal error: Cannot load config.lua (' . $filename . '). Error: ' . print_r(error_get_last(), true)); log_append('error.log', '[load_config_file] Fatal error: Cannot load config.lua (' . $filename . ').');
throw new RuntimeException('ERROR: Cannot find ' . $filename . ' file. More info in system/logs/error.log'); throw new RuntimeException('ERROR: Cannot find ' . $filename . ' file.');
} }
$result = array(); $result = array();
@@ -1044,7 +1054,7 @@ function getTopPlayers($limit = 5) {
$deleted = 'deletion'; $deleted = 'deletion';
$is_tfs10 = $db->hasTable('players_online'); $is_tfs10 = $db->hasTable('players_online');
$players = $db->query('SELECT `id`, `name`, `level`, `vocation`, `experience`, `looktype`' . ($db->hasColumn('players', 'lookaddons') ? ', `lookaddons`' : '') . ', `lookhead`, `lookbody`, `looklegs`, `lookfeet`' . ($is_tfs10 ? '' : ', `online`') . ' FROM `players` WHERE `group_id` < ' . config('highscores_groups_hidden') . ' AND `id` NOT IN (' . implode(', ', config('highscores_ids_hidden')) . ') AND `' . $deleted . '` = 0 AND `account_id` != 1 ORDER BY `experience` DESC LIMIT ' . (int)$limit)->fetchAll(); $players = $db->query('SELECT `id`, `name`, `level`, `vocation`, `experience`, `looktype`' . ($db->hasColumn('players', 'lookaddons') ? ', `lookaddons`' : '') . ', `lookhead`, `lookbody`, `looklegs`, `lookfeet`' . ($is_tfs10 ? '' : ', `online`') . ' FROM `players` WHERE `group_id` < ' . setting('core.highscores_groups_hidden') . ' AND `id` NOT IN (' . implode(', ', setting('core.highscores_ids_hidden')) . ') AND `' . $deleted . '` = 0 AND `account_id` != 1 ORDER BY `experience` DESC LIMIT ' . (int)$limit)->fetchAll();
if($is_tfs10) { if($is_tfs10) {
foreach($players as &$player) { foreach($players as &$player) {
@@ -1097,6 +1107,9 @@ function deleteDirectory($dir, $ignore = array(), $contentOnly = false) {
function config($key) { function config($key) {
global $config; global $config;
if (is_array($key)) { if (is_array($key)) {
if (is_null($key[1])) {
unset($config[$key[0]]);
}
return $config[$key[0]] = $key[1]; return $config[$key[0]] = $key[1];
} }
@@ -1112,6 +1125,21 @@ function configLua($key) {
return @$config['lua'][$key]; return @$config['lua'][$key];
} }
function setting($key)
{
$settings = Settings::getInstance();
if (is_array($key)) {
if (is_null($key[1])) {
unset($settings[$key[0]]);
}
return $settings[$key[0]] = $key[1];
}
return $settings[$key]['value'];
}
function clearCache() function clearCache()
{ {
require_once LIBS . 'news.php'; require_once LIBS . 'news.php';
@@ -1189,7 +1217,7 @@ function getCustomPageInfo($page)
return null; return null;
} }
function getCustomPage($page, &$success) function getCustomPage($page, &$success): string
{ {
global $db, $twig, $title, $ignore, $logged_access; global $db, $twig, $title, $ignore, $logged_access;
@@ -1480,8 +1508,8 @@ function right($str, $length) {
} }
function getCreatureImgPath($creature){ function getCreatureImgPath($creature){
$creature_path = config('creatures_images_url'); $creature_path = config('monsters_images_url');
$creature_gfx_name = trim(strtolower($creature)) . config('creatures_images_extension'); $creature_gfx_name = trim(strtolower($creature)) . config('monsters_images_extension');
if (!file_exists($creature_path . $creature_gfx_name)) { if (!file_exists($creature_path . $creature_gfx_name)) {
$creature_gfx_name = str_replace(" ", "", $creature_gfx_name); $creature_gfx_name = str_replace(" ", "", $creature_gfx_name);
if (file_exists($creature_path . $creature_gfx_name)) { if (file_exists($creature_path . $creature_gfx_name)) {
@@ -1544,6 +1572,47 @@ function escapeHtml($html) {
return htmlentities($html, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8'); return htmlentities($html, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8');
} }
function getGuildNameById($id)
{
global $db;
$guild = $db->query('SELECT `name` FROM `guilds` WHERE `id` = ' . (int)$id);
if($guild->rowCount() > 0) {
return $guild->fetchColumn();
}
return false;
}
function getGuildLogoById($id)
{
global $db;
$logo = 'default.gif';
$query = $db->query('SELECT `logo_name` FROM `guilds` WHERE `id` = ' . (int)$id);
if ($query->rowCount() == 1) {
$query = $query->fetch(PDO::FETCH_ASSOC);
$guildLogo = $query['logo_name'];
if (!empty($guildLogo) && file_exists(GUILD_IMAGES_DIR . $guildLogo)) {
$logo = $guildLogo;
}
}
return BASE_URL . GUILD_IMAGES_DIR . $logo;
}
function displayErrorBoxWithBackButton($errors, $action = null) {
global $twig;
$twig->display('error_box.html.twig', ['errors' => $errors]);
$twig->display('account.back_button.html.twig', [
'action' => $action ?: getLink('')
]);
}
// validator functions // validator functions
require_once LIBS . 'validator.php'; require_once LIBS . 'validator.php';
require_once SYSTEM . 'compat/base.php'; require_once SYSTEM . 'compat/base.php';

View File

@@ -30,6 +30,7 @@ define('HOOK_CHARACTERS_AFTER_CHARACTERS', ++$i);
define('HOOK_LOGIN', ++$i); define('HOOK_LOGIN', ++$i);
define('HOOK_LOGIN_ATTEMPT', ++$i); define('HOOK_LOGIN_ATTEMPT', ++$i);
define('HOOK_LOGOUT', ++$i); define('HOOK_LOGOUT', ++$i);
define('HOOK_ACCOUNT_CHANGE_PASSWORD_POST', ++$i);
define('HOOK_ACCOUNT_CREATE_BEFORE_FORM', ++$i); define('HOOK_ACCOUNT_CREATE_BEFORE_FORM', ++$i);
define('HOOK_ACCOUNT_CREATE_BEFORE_BOXES', ++$i); define('HOOK_ACCOUNT_CREATE_BEFORE_BOXES', ++$i);
define('HOOK_ACCOUNT_CREATE_BETWEEN_BOXES_1', ++$i); define('HOOK_ACCOUNT_CREATE_BETWEEN_BOXES_1', ++$i);
@@ -39,8 +40,8 @@ define('HOOK_ACCOUNT_CREATE_BEFORE_ACCOUNT', ++$i);
define('HOOK_ACCOUNT_CREATE_AFTER_ACCOUNT', ++$i); define('HOOK_ACCOUNT_CREATE_AFTER_ACCOUNT', ++$i);
define('HOOK_ACCOUNT_CREATE_AFTER_EMAIL', ++$i); define('HOOK_ACCOUNT_CREATE_AFTER_EMAIL', ++$i);
define('HOOK_ACCOUNT_CREATE_AFTER_COUNTRY', ++$i); define('HOOK_ACCOUNT_CREATE_AFTER_COUNTRY', ++$i);
define('HOOK_ACCOUNT_CREATE_AFTER_PASSWORD', ++$i);
define('HOOK_ACCOUNT_CREATE_AFTER_PASSWORDS', ++$i); define('HOOK_ACCOUNT_CREATE_AFTER_PASSWORDS', ++$i);
define('HOOK_ACCOUNT_CREATE_AFTER_RECAPTCHA', ++$i);
define('HOOK_ACCOUNT_CREATE_BEFORE_CHARACTER_NAME', ++$i); define('HOOK_ACCOUNT_CREATE_BEFORE_CHARACTER_NAME', ++$i);
define('HOOK_ACCOUNT_CREATE_AFTER_CHARACTER_NAME', ++$i); define('HOOK_ACCOUNT_CREATE_AFTER_CHARACTER_NAME', ++$i);
define('HOOK_ACCOUNT_CREATE_AFTER_SEX', ++$i); define('HOOK_ACCOUNT_CREATE_AFTER_SEX', ++$i);
@@ -48,11 +49,34 @@ define('HOOK_ACCOUNT_CREATE_AFTER_VOCATION', ++$i);
define('HOOK_ACCOUNT_CREATE_AFTER_TOWNS', ++$i); define('HOOK_ACCOUNT_CREATE_AFTER_TOWNS', ++$i);
define('HOOK_ACCOUNT_CREATE_BEFORE_SUBMIT_BUTTON', ++$i); define('HOOK_ACCOUNT_CREATE_BEFORE_SUBMIT_BUTTON', ++$i);
define('HOOK_ACCOUNT_CREATE_AFTER_FORM', ++$i); define('HOOK_ACCOUNT_CREATE_AFTER_FORM', ++$i);
define('HOOK_ACCOUNT_CREATE_AFTER_SUBMIT', ++$i); define('HOOK_ACCOUNT_CREATE_POST', ++$i);
define('HOOK_ACCOUNT_LOGIN_BEFORE_PAGE', ++$i);
define('HOOK_ACCOUNT_LOGIN_BEFORE_ACCOUNT', ++$i);
define('HOOK_ACCOUNT_LOGIN_AFTER_ACCOUNT', ++$i);
define('HOOK_ACCOUNT_LOGIN_BEFORE_PASSWORD', ++$i);
define('HOOK_ACCOUNT_LOGIN_AFTER_PASSWORD', ++$i);
define('HOOK_ACCOUNT_LOGIN_AFTER_REMEMBER_ME', ++$i);
define('HOOK_ACCOUNT_LOGIN_AFTER_PAGE', ++$i);
define('HOOK_ACCOUNT_LOGIN_POST', ++$i);
define('HOOK_ADMIN_HEAD_END', ++$i);
define('HOOK_ADMIN_HEAD_START', ++$i);
define('HOOK_ADMIN_BODY_START', ++$i);
define('HOOK_ADMIN_BODY_END', ++$i);
define('HOOK_ADMIN_BEFORE_PAGE', ++$i);
define('HOOK_ADMIN_MENU', ++$i); define('HOOK_ADMIN_MENU', ++$i);
define('HOOK_ADMIN_LOGIN_AFTER_ACCOUNT', ++$i);
define('HOOK_ADMIN_LOGIN_AFTER_PASSWORD', ++$i);
define('HOOK_ADMIN_LOGIN_AFTER_SIGN_IN', ++$i);
define('HOOK_ADMIN_ACCOUNTS_SAVE_POST', ++$i);
define('HOOK_EMAIL_CONFIRMED', ++$i); define('HOOK_EMAIL_CONFIRMED', ++$i);
define('HOOK_FIRST', HOOK_STARTUP); define('HOOK_GUILDS_BEFORE_GUILD_HEADER', ++$i);
define('HOOK_LAST', HOOK_EMAIL_CONFIRMED); define('HOOK_GUILDS_AFTER_GUILD_HEADER', ++$i);
define('HOOK_GUILDS_AFTER_GUILD_INFORMATION', ++$i);
define('HOOK_GUILDS_AFTER_GUILD_MEMBERS', ++$i);
define('HOOK_GUILDS_AFTER_INVITED_CHARACTERS', ++$i);
const HOOK_FIRST = HOOK_STARTUP;
define('HOOK_LAST', $i);
require_once LIBS . 'plugins.php'; require_once LIBS . 'plugins.php';
class Hook class Hook

View File

@@ -9,22 +9,24 @@
*/ */
defined('MYAAC') or die('Direct access not allowed!'); defined('MYAAC') or die('Direct access not allowed!');
// load configuration
require_once BASE . 'config.php';
if(file_exists(BASE . 'config.local.php')) // user customizations
require BASE . 'config.local.php';
if(!isset($config['installed']) || !$config['installed']) { if(!isset($config['installed']) || !$config['installed']) {
throw new RuntimeException('MyAAC has not been installed yet or there was error during installation. Please install again.'); throw new RuntimeException('MyAAC has not been installed yet or there was error during installation. Please install again.');
} }
date_default_timezone_set($config['date_timezone']); if(config('env') === 'dev') {
require SYSTEM . 'exception.php';
}
if(empty($config['server_path'])) {
throw new RuntimeException('Server Path has been not set. Go to config.php and set it.');
}
// take care of trailing slash at the end // take care of trailing slash at the end
if($config['server_path'][strlen($config['server_path']) - 1] !== '/') if($config['server_path'][strlen($config['server_path']) - 1] !== '/')
$config['server_path'] .= '/'; $config['server_path'] .= '/';
// enable gzip compression if supported by the browser // enable gzip compression if supported by the browser
if($config['gzip_output'] && isset($_SERVER['HTTP_ACCEPT_ENCODING']) && strpos($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip') !== false && function_exists('ob_gzhandler')) if(isset($config['gzip_output']) && $config['gzip_output'] && isset($_SERVER['HTTP_ACCEPT_ENCODING']) && strpos($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip') !== false && function_exists('ob_gzhandler'))
ob_start('ob_gzhandler'); ob_start('ob_gzhandler');
// cache // cache
@@ -92,9 +94,6 @@ if(isset($config['lua']['servername']))
if(isset($config['lua']['houserentperiod'])) if(isset($config['lua']['houserentperiod']))
$config['lua']['houseRentPeriod'] = $config['lua']['houserentperiod']; $config['lua']['houseRentPeriod'] = $config['lua']['houserentperiod'];
if($config['item_images_url'][strlen($config['item_images_url']) - 1] !== '/')
$config['item_images_url'] .= '/';
// localize data/ directory based on data directory set in config.lua // localize data/ directory based on data directory set in config.lua
foreach(array('dataDirectory', 'data_directory', 'datadir') as $key) { foreach(array('dataDirectory', 'data_directory', 'datadir') as $key) {
if(!isset($config['lua'][$key][0])) { if(!isset($config['lua'][$key][0])) {
@@ -118,51 +117,34 @@ if(!isset($foundValue)) {
$config['data_path'] = $foundValue; $config['data_path'] = $foundValue;
unset($foundValue); unset($foundValue);
// new config values for compability
if(!isset($config['highscores_ids_hidden']) || count($config['highscores_ids_hidden']) == 0) {
$config['highscores_ids_hidden'] = array(0);
}
$config['account_create_character_create'] = config('account_create_character_create') && (!config('mail_enabled') || !config('account_mail_verify'));
// POT // POT
require_once SYSTEM . 'libs/pot/OTS.php'; require_once SYSTEM . 'libs/pot/OTS.php';
$ots = POT::getInstance(); $ots = POT::getInstance();
require_once SYSTEM . 'database.php'; require_once SYSTEM . 'database.php';
// execute migrations
require SYSTEM . 'migrate.php';
// settings
require_once LIBS . 'Settings.php';
$settings = Settings::getInstance();
$settings->load();
// deprecated config values
require_once SYSTEM . 'compat/config.php';
date_default_timezone_set(setting('core.date_timezone'));
$config['account_create_character_create'] = config('account_create_character_create') && (!setting('core.mail_enabled') || !config('account_mail_verify'));
$settingsItemImagesURL = setting('core.item_images_url');
if($settingsItemImagesURL[strlen($settingsItemImagesURL) - 1] !== '/') {
setting(['core.item_images_url', $settingsItemImagesURL . '/']);
}
define('USE_ACCOUNT_NAME', $db->hasColumn('accounts', 'name')); define('USE_ACCOUNT_NAME', $db->hasColumn('accounts', 'name'));
define('USE_ACCOUNT_NUMBER', $db->hasColumn('accounts', 'number')); define('USE_ACCOUNT_NUMBER', $db->hasColumn('accounts', 'number'));
define('USE_ACCOUNT_SALT', $db->hasColumn('accounts', 'salt')); define('USE_ACCOUNT_SALT', $db->hasColumn('accounts', 'salt'));
// load vocation names
$tmp = '';
if($cache->enabled() && $cache->fetch('vocations', $tmp)) {
$config['vocations'] = unserialize($tmp);
}
else {
if(!class_exists('DOMDocument')) {
throw new RuntimeException('Please install PHP xml extension. MyAAC will not work without it.');
}
$vocations = new DOMDocument();
$file = $config['data_path'] . 'XML/vocations.xml';
if(!@file_exists($file))
$file = $config['data_path'] . 'vocations.xml';
if(!$vocations->load($file))
throw new RuntimeException('ERROR: Cannot load <i>vocations.xml</i> - the file is malformed. Check the file with xml syntax validator.');
$config['vocations'] = array();
foreach($vocations->getElementsByTagName('vocation') as $vocation) {
$id = $vocation->getAttribute('id');
$config['vocations'][$id] = $vocation->getAttribute('name');
}
if($cache->enabled()) {
$cache->set('vocations', serialize($config['vocations']), 120);
}
}
unset($tmp, $id, $vocation);
require LIBS . 'Towns.php'; require LIBS . 'Towns.php';
Towns::load(); Towns::load();

View File

@@ -58,4 +58,3 @@ function outputItem($id = 100, $count = 1)
$file_name = Items_Images::$outputDir . $file_name . '.gif'; $file_name = Items_Images::$outputDir . $file_name . '.gif';
readfile($file_name); readfile($file_name);
} }
?>

View File

@@ -18,8 +18,8 @@ class CreateCharacter
*/ */
public function checkName($name, &$errors) public function checkName($name, &$errors)
{ {
$minLength = config('character_name_min_length'); $minLength = setting('core.create_character_name_min_length');
$maxLength = config('character_name_max_length'); $maxLength = setting('core.create_character_name_max_length');
if(empty($name)) { if(empty($name)) {
$errors['name'] = 'Please enter a name for your character!'; $errors['name'] = 'Please enter a name for your character!';
@@ -138,7 +138,7 @@ class CreateCharacter
if(empty($errors)) if(empty($errors))
{ {
$number_of_players_on_account = $account->getPlayersList(false)->count(); $number_of_players_on_account = $account->getPlayersList(true)->count();
if($number_of_players_on_account >= config('characters_per_account')) if($number_of_players_on_account >= config('characters_per_account'))
$errors[] = 'You have too many characters on your account <b>('.$number_of_players_on_account.'/'.config('characters_per_account').')</b>!'; $errors[] = 'You have too many characters on your account <b>('.$number_of_players_on_account.'/'.config('characters_per_account').')</b>!';
} }
@@ -149,7 +149,7 @@ class CreateCharacter
$char_to_copy = new OTS_Player(); $char_to_copy = new OTS_Player();
$char_to_copy->find($char_to_copy_name); $char_to_copy->find($char_to_copy_name);
if(!$char_to_copy->isLoaded()) if(!$char_to_copy->isLoaded())
$errors[] = 'Wrong characters configuration. Try again or contact with admin. ADMIN: Edit file config.php and set valid characters to copy names. Character to copy: <b>'.$char_to_copy_name.'</b> doesn\'t exist.'; $errors[] = 'Wrong characters configuration. Try again or contact with admin. ADMIN: Go to Admin Panel -> Settings -> Create Character and set valid characters to copy names. Character to copy: <b>'.$char_to_copy_name.'</b> doesn\'t exist.';
} }
if(!empty($errors)) { if(!empty($errors)) {
@@ -195,7 +195,7 @@ class CreateCharacter
for($skill = POT::SKILL_FIRST; $skill <= POT::SKILL_LAST; $skill++) { for($skill = POT::SKILL_FIRST; $skill <= POT::SKILL_LAST; $skill++) {
$value = 10; $value = 10;
if (config('use_character_sample_skills')) { if (setting('core.use_character_sample_skills')) {
$value = $char_to_copy->getSkill($skill); $value = $char_to_copy->getSkill($skill);
} }
@@ -239,23 +239,25 @@ class CreateCharacter
} }
if($db->hasTable('player_skills')) { if($db->hasTable('player_skills')) {
for($i=0; $i<7; $i++) { for($skill = POT::SKILL_FIRST; $skill <= POT::SKILL_LAST; $skill++) {
$value = 10; $value = 10;
if (config('use_character_sample_skills')) { if (setting('core.use_character_sample_skills')) {
$value = $char_to_copy->getSkill($i); $value = $char_to_copy->getSkill($skill);
} }
$skillExists = $db->query('SELECT `skillid` FROM `player_skills` WHERE `player_id` = ' . $player->getId() . ' AND `skillid` = ' . $i); $skillExists = $db->query('SELECT `skillid` FROM `player_skills` WHERE `player_id` = ' . $player->getId() . ' AND `skillid` = ' . $skill);
if($skillExists->rowCount() <= 0) { if($skillExists->rowCount() <= 0) {
$db->query('INSERT INTO `player_skills` (`player_id`, `skillid`, `value`, `count`) VALUES ('.$player->getId().', '.$i.', ' . $value . ', 0)'); $db->query('INSERT INTO `player_skills` (`player_id`, `skillid`, `value`, `count`) VALUES ('.$player->getId().', '.$skill.', ' . $value . ', 0)');
} }
} }
} }
if ($db->hasTable('player_items') && $db->hasColumn('player_items', 'pid') && $db->hasColumn('player_items', 'sid') && $db->hasColumn('player_items', 'itemtype')) {
$loaded_items_to_copy = $db->query("SELECT * FROM player_items WHERE player_id = ".$char_to_copy->getId().""); $loaded_items_to_copy = $db->query("SELECT * FROM player_items WHERE player_id = ".$char_to_copy->getId()."");
foreach($loaded_items_to_copy as $save_item) { foreach($loaded_items_to_copy as $save_item) {
$blob = $db->quote($save_item['attributes']); $blob = $db->quote($save_item['attributes']);
$db->query("INSERT INTO `player_items` (`player_id` ,`pid` ,`sid` ,`itemtype`, `count`, `attributes`) VALUES ('".$player->getId()."', '".$save_item['pid']."', '".$save_item['sid']."', '".$save_item['itemtype']."', '".$save_item['count']."', $blob);"); $db->query("INSERT INTO `player_items` (`player_id` ,`pid` ,`sid` ,`itemtype`, `count`, `attributes`) VALUES ('".$player->getId()."', '".$save_item['pid']."', '".$save_item['sid']."', '".$save_item['itemtype']."', '".$save_item['count']."', $blob);");
} }
}
global $twig; global $twig;
$twig->display('success.html.twig', array( $twig->display('success.html.twig', array(

View File

@@ -1,84 +0,0 @@
<?php
class GoogleReCAPTCHA
{
private static $errorMessage = '';
private static $errorType;
const ERROR_MISSING_RESPONSE = 1;
const ERROR_INVALID_ACTION = 2;
const ERROR_LOW_SCORE = 3;
const ERROR_NO_SUCCESS = 4;
public static function verify($action = '')
{
if (!isset($_POST['g-recaptcha-response']) || empty($_POST['g-recaptcha-response'])) {
self::$errorType = self::ERROR_MISSING_RESPONSE;
self::$errorMessage = "Please confirm that you're not a robot.";
return false;
}
$recaptchaApiUrl = 'https://www.google.com/recaptcha/api/siteverify';
$secretKey = config('recaptcha_secret_key');
$recaptchaResponse = $_POST['g-recaptcha-response'];
$ip = $_SERVER['REMOTE_ADDR'];
$params = 'secret='.$secretKey.'&response='.$recaptchaResponse.'&remoteip='.$ip;
if (function_exists('curl_version')) {
$curl_connection = curl_init($recaptchaApiUrl);
curl_setopt($curl_connection, CURLOPT_CONNECTTIMEOUT, 5);
curl_setopt($curl_connection, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl_connection, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($curl_connection, CURLOPT_FOLLOWLOCATION, 0);
curl_setopt($curl_connection, CURLOPT_POSTFIELDS, $params);
$response = curl_exec($curl_connection);
curl_close($curl_connection);
} else {
$response = file_get_contents($recaptchaApiUrl . '?' . $params);
}
$json = json_decode($response);
$recaptchaType = config('recaptcha_type');
if ($recaptchaType === 'v3') { // score based
//log_append('recaptcha.log', 'recaptcha_score: ' . $json->score . ', action:' . $json->action);
if (!isset($json->action) || $json->action !== $action) {
self::$errorType = self::ERROR_INVALID_ACTION;
self::$errorMessage = 'Google ReCaptcha returned invalid action.';
return false;
}
if (!isset($json->score) || $json->score < config('recaptcha_v3_min_score')) {
self::$errorType = self::ERROR_LOW_SCORE;
self::$errorMessage = 'Your Google ReCaptcha score was too low.';
return false;
}
}
if (!isset($json->success) || !$json->success) {
self::$errorType = self::ERROR_NO_SUCCESS;
self::$errorMessage = "Please confirm that you're not a robot.";
return false;
}
return true;
}
/**
* @return string
*/
public static function getErrorMessage() {
return self::$errorMessage;
}
/**
* @return int
*/
public static function getErrorType() {
return self::$errorType;
}
}

598
system/libs/Settings.php Normal file
View File

@@ -0,0 +1,598 @@
<?php
/**
* CreateCharacter
*
* @package MyAAC
* @author Slawkens <slawkens@gmail.com>
* @copyright 2020 MyAAC
* @link https://my-aac.org
*/
class Settings implements ArrayAccess
{
static private $instance;
private $settingsFile = [];
private $settingsDatabase = [];
private $cache = [];
private $valuesAsked = [];
private $errors = [];
/**
* @return Settings
*/
public static function getInstance(): Settings
{
if (!self::$instance) {
self::$instance = new self();
}
return self::$instance;
}
public function load()
{
$cache = Cache::getInstance();
if ($cache->enabled()) {
$tmp = '';
if ($cache->fetch('settings', $tmp)) {
$this->settingsDatabase = unserialize($tmp);
return;
}
}
global $db;
$settings = $db->query('SELECT * FROM `' . TABLE_PREFIX . 'settings`');
if($settings->rowCount() > 0) {
foreach ($settings->fetchAll(PDO::FETCH_ASSOC) as $setting) {
$this->settingsDatabase[$setting['name']][$setting['key']] = $setting['value'];
}
}
if ($cache->enabled()) {
$cache->set('settings', serialize($this->settingsDatabase), 600);
}
}
public function save($pluginName, $values) {
global $db;
if (!isset($this->settingsFile[$pluginName])) {
throw new RuntimeException('Error on save settings: plugin does not exist');
}
$settings = $this->settingsFile[$pluginName];
if (isset($settings['callbacks']['beforeSave'])) {
if (!$settings['callbacks']['beforeSave']($settings, $values)) {
return false;
}
}
$this->errors = [];
$db->query('DELETE FROM `' . TABLE_PREFIX . 'settings` WHERE `name` = ' . $db->quote($pluginName) . ';');
foreach ($values as $key => $value) {
$errorMessage = '';
if (isset($settings['settings'][$key]['callbacks']['beforeSave']) && !$settings['settings'][$key]['callbacks']['beforeSave']($key, $value, $errorMessage)) {
$this->errors[] = $errorMessage;
continue;
}
try {
$db->insert(TABLE_PREFIX . 'settings', ['name' => $pluginName, 'key' => $key, 'value' => $value]);
} catch (PDOException $error) {
$this->errors[] = 'Error while saving setting (' . $pluginName . ' - ' . $key . '): ' . $error->getMessage();
}
}
$cache = Cache::getInstance();
if ($cache->enabled()) {
$cache->delete('settings');
}
return true;
}
public function updateInDatabase($pluginName, $key, $value)
{
global $db;
$db->update(TABLE_PREFIX . 'settings', ['value' => $value], ['name' => $pluginName, 'key' => $key]);
}
public function deleteFromDatabase($pluginName, $key = null)
{
global $db;
if (!isset($key)) {
$db->delete(TABLE_PREFIX . 'settings', ['name' => $pluginName], -1);
}
else {
$db->delete(TABLE_PREFIX . 'settings', ['name' => $pluginName, 'key' => $key]);
}
}
public static function display($plugin, $settings): array
{
global $db;
$query = 'SELECT `key`, `value` FROM `' . TABLE_PREFIX . 'settings` WHERE `name` = ' . $db->quote($plugin) . ';';
$query = $db->query($query);
$settingsDb = [];
if($query->rowCount() > 0) {
foreach($query->fetchAll(PDO::FETCH_ASSOC) as $value) {
$settingsDb[$value['key']] = $value['value'];
}
}
$config = [];
require BASE . 'config.local.php';
foreach ($config as $key => $value) {
if (is_bool($value)) {
$settingsDb[$key] = $value ? 'true' : 'false';
}
else {
$settingsDb[$key] = (string)$value;
}
}
$javascript = '';
ob_start();
?>
<ul class="nav nav-tabs" id="myTab">
<?php
$i = 0;
foreach($settings as $setting) {
if (isset($setting['script'])) {
$javascript .= $setting['script'] . PHP_EOL;
}
if ($setting['type'] === 'category') {
?>
<li class="nav-item">
<a class="nav-link<?= ($i === 0 ? ' active' : ''); ?>" id="home-tab-<?= $i++; ?>" data-toggle="tab" href="#tab-<?= str_replace(' ', '', $setting['title']); ?>" type="button"><?= $setting['title']; ?></a>
</li>
<?php
}
}
?>
</ul>
<div class="tab-content" id="tab-content">
<?php
$checkbox = function ($key, $type, $value) {
echo '<label><input type="radio" id="' . $key . '_' . ($type ? 'yes' : 'no') . '" name="settings[' . $key . ']" value="' . ($type ? 'true' : 'false') . '" ' . ($value === $type ? 'checked' : '') . '/>' . ($type ? 'Yes' : 'No') . '</label> ';
};
$i = 0;
$j = 0;
foreach($settings as $key => $setting) {
if ($setting['type'] === 'category') {
if ($j++ !== 0) { // close previous category
echo '</tbody></table></div>';
}
?>
<div class="tab-pane fade show<?= ($j === 1 ? ' active' : ''); ?>" id="tab-<?= str_replace(' ', '', $setting['title']); ?>">
<?php
continue;
}
if ($setting['type'] === 'section') {
if ($i++ !== 0) { // close previous section
echo '</tbody></table>';
}
?>
<h3 id="row_<?= $key ?>" style="text-align: center"><strong><?= $setting['title']; ?></strong></h3>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th style="width: 13%">Name</th>
<th style="width: 30%">Value</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<?php
continue;
}
if (!isset($setting['hidden']) || !$setting['hidden']) {
?>
<tr id="row_<?= $key ?>">
<td><label for="<?= $key ?>" class="control-label"><?= $setting['name'] ?></label></td>
<td>
<?php
}
if (isset($setting['hidden']) && $setting['hidden']) {
$value = '';
if ($setting['type'] === 'boolean') {
$value = ($setting['default'] ? 'true' : 'false');
}
else if (in_array($setting['type'], ['text', 'number', 'email', 'password', 'textarea'])) {
$value = $setting['default'];
}
else if ($setting['type'] === 'options') {
$value = $setting['options'][$setting['default']];
}
echo '<input type="hidden" name="settings[' . $key . ']" value="' . $value . '" id="' . $key . '"';
}
else if ($setting['type'] === 'boolean') {
if(isset($settingsDb[$key])) {
if($settingsDb[$key] === 'true') {
$value = true;
}
else {
$value = false;
}
}
else {
$value = ($setting['default'] ?? false);
}
$checkbox($key, true, $value);
$checkbox($key, false, $value);
}
else if (in_array($setting['type'], ['text', 'number', 'email', 'password'])) {
if ($setting['type'] === 'number') {
$min = (isset($setting['min']) ? ' min="' . $setting['min'] . '"' : '');
$max = (isset($setting['max']) ? ' max="' . $setting['max'] . '"' : '');
$step = (isset($setting['step']) ? ' step="' . $setting['step'] . '"' : '');
}
else {
$min = $max = $step = '';
}
echo '<input class="form-control" type="' . $setting['type'] . '" name="settings[' . $key . ']" value="' . ($settingsDb[$key] ?? ($setting['default'] ?? '')) . '" id="' . $key . '"' . $min . $max . $step . '/>';
}
else if($setting['type'] === 'textarea') {
$value = ($settingsDb[$key] ?? ($setting['default'] ?? ''));
$valueWithSpaces = array_map('trim', preg_split('/\r\n|\r|\n/', trim($value)));
$rows = count($valueWithSpaces);
if ($rows < 2) {
$rows = 2; // always min 2 rows for textarea
}
echo '<textarea class="form-control" rows="' . $rows . '" name="settings[' . $key . ']" id="' . $key . '">' . $value . '</textarea>';
}
else if ($setting['type'] === 'options') {
if ($setting['options'] === '$templates') {
$templates = [];
foreach (get_templates() as $value) {
$templates[$value] = $value;
}
$setting['options'] = $templates;
}
else if($setting['options'] === '$clients') {
$clients = [];
foreach((array)config('clients') as $client) {
$client_version = (string)($client / 100);
if(strpos($client_version, '.') === false)
$client_version .= '.0';
$clients[$client] = $client_version;
}
$setting['options'] = $clients;
}
else if ($setting['options'] == '$timezones') {
$timezones = [];
foreach (DateTimeZone::listIdentifiers() as $value) {
$timezones[$value] = $value;
}
$setting['options'] = $timezones;
}
else {
if (is_string($setting['options'])) {
$setting['options'] = explode(',', $setting['options']);
foreach ($setting['options'] as &$option) {
$option = trim($option);
}
}
}
echo '<select class="form-control" name="settings[' . $key . ']" id="' . $key . '">';
foreach ($setting['options'] as $value => $option) {
$compareTo = ($settingsDb[$key] ?? ($setting['default'] ?? ''));
if($value === 'true') {
$selected = $compareTo === true;
}
else if($value === 'false') {
$selected = $compareTo === false;
}
else {
$selected = $compareTo == $value;
}
echo '<option value="' . $value . '" ' . ($selected ? 'selected' : '') . '>' . $option . '</option>';
}
echo '</select>';
}
if (!isset($setting['hidden']) || !$setting['hidden']) {
?>
</td>
<td>
<div class="well setting-default"><?php
echo ($setting['desc'] ?? '');
echo '<br/>';
echo '<strong>Default:</strong> ';
if ($setting['type'] === 'boolean') {
echo ($setting['default'] ? 'Yes' : 'No');
}
else if (in_array($setting['type'], ['text', 'number', 'email', 'password', 'textarea'])) {
echo $setting['default'];
}
else if ($setting['type'] === 'options') {
if (!empty($setting['default'])) {
echo $setting['options'][$setting['default']];
}
}
?></div>
</td>
</tr>
<?php
}
}
?>
</tbody>
</table>
</div>
</div>
<div class="box-footer">
<button name="save" type="submit" class="btn btn-primary">Save</button>
</div>
<?php
return ['content' => ob_get_clean(), 'script' => $javascript];
}
#[\ReturnTypeWillChange]
public function offsetSet($offset, $value)
{
if (is_null($offset)) {
throw new \RuntimeException("Settings: You cannot set empty offset with value: $value!");
}
$this->loadPlugin($offset);
$pluginKeyName = $this->valuesAsked['pluginKeyName'];
$key = $this->valuesAsked['key'];
// remove whole plugin settings
if (!isset($value)) {
$this->offsetUnset($offset);
$this->deleteFromDatabase($pluginKeyName, $key);
return;
}
$this->settingsDatabase[$pluginKeyName][$key] = $value;
$this->updateInDatabase($pluginKeyName, $key, $value);
}
#[\ReturnTypeWillChange]
public function offsetExists($offset): bool
{
$this->loadPlugin($offset);
$pluginKeyName = $this->valuesAsked['pluginKeyName'];
$key = $this->valuesAsked['key'];
// remove specified plugin settings (all)
if(is_null($key)) {
return isset($this->settingsDatabase[$offset]);
}
return isset($this->settingsDatabase[$pluginKeyName][$key]);
}
#[\ReturnTypeWillChange]
public function offsetUnset($offset)
{
$this->loadPlugin($offset);
$pluginKeyName = $this->valuesAsked['pluginKeyName'];
$key = $this->valuesAsked['key'];
if (isset($this->cache[$offset])) {
unset($this->cache[$offset]);
}
// remove specified plugin settings (all)
if(!isset($key)) {
unset($this->settingsFile[$pluginKeyName]);
unset($this->settingsDatabase[$pluginKeyName]);
$this->deleteFromDatabase($pluginKeyName);
return;
}
unset($this->settingsFile[$pluginKeyName]['settings'][$key]);
unset($this->settingsDatabase[$pluginKeyName][$key]);
$this->deleteFromDatabase($pluginKeyName, $key);
}
/**
* Get settings
* Usage: $setting['plugin_name.key']
* Example: $settings['shop_system.paypal_email']
*
* @param mixed $offset
* @return array|mixed
*/
#[\ReturnTypeWillChange]
public function offsetGet($offset)
{
// try cache hit
if(isset($this->cache[$offset])) {
return $this->cache[$offset];
}
$this->loadPlugin($offset);
$pluginKeyName = $this->valuesAsked['pluginKeyName'];
$key = $this->valuesAsked['key'];
// return specified plugin settings (all)
if(!isset($key)) {
if (!isset($this->settingsFile[$pluginKeyName]['settings'])) {
throw new RuntimeException('Unknown plugin settings: ' . $pluginKeyName);
}
return $this->settingsFile[$pluginKeyName]['settings'];
}
$ret = [];
if(isset($this->settingsFile[$pluginKeyName]['settings'][$key])) {
$ret = $this->settingsFile[$pluginKeyName]['settings'][$key];
}
if(isset($this->settingsDatabase[$pluginKeyName][$key])) {
$value = $this->settingsDatabase[$pluginKeyName][$key];
$ret['value'] = $value;
}
else {
$ret['value'] = $this->settingsFile[$pluginKeyName]['settings'][$key]['default'];
}
if(isset($ret['type'])) {
switch($ret['type']) {
case 'boolean':
$ret['value'] = getBoolean($ret['value']);
break;
case 'number':
if (!isset($ret['step']) || (int)$ret['step'] == 1) {
$ret['value'] = (int)$ret['value'];
}
break;
default:
break;
}
}
if (isset($ret['callbacks']['get'])) {
$ret['value'] = $ret['callbacks']['get']($ret['value']);
}
$this->cache[$offset] = $ret;
return $ret;
}
private function updateValuesAsked($offset)
{
$pluginKeyName = $offset;
if (strpos($offset, '.')) {
$explode = explode('.', $offset, 2);
$pluginKeyName = $explode[0];
$key = $explode[1];
$this->valuesAsked = ['pluginKeyName' => $pluginKeyName, 'key' => $key];
}
else {
$this->valuesAsked = ['pluginKeyName' => $pluginKeyName, 'key' => null];
}
}
private function loadPlugin($offset)
{
$this->updateValuesAsked($offset);
$pluginKeyName = $this->valuesAsked['pluginKeyName'];
$key = $this->valuesAsked['key'];
if (!isset($this->settingsFile[$pluginKeyName])) {
if ($pluginKeyName === 'core') {
$settingsFilePath = SYSTEM . 'settings.php';
} else {
//$pluginSettings = Plugins::getPluginSettings($pluginKeyName);
$settings = Plugins::getAllPluginsSettings();
if (!isset($settings[$pluginKeyName])) {
warning("Setting $pluginKeyName does not exist or does not have settings defined.");
return;
}
$settingsFilePath = BASE . $settings[$pluginKeyName]['settingsFilename'];
}
if (!file_exists($settingsFilePath)) {
throw new \RuntimeException('Failed to load settings file for plugin: ' . $pluginKeyName);
}
$this->settingsFile[$pluginKeyName] = require $settingsFilePath;
}
}
public static function saveConfig($config, $filename, &$content = '')
{
$content = "<?php" . PHP_EOL .
"\$config['installed'] = true;" . PHP_EOL;
foreach ($config as $key => $value) {
$content .= "\$config['$key'] = ";
$content .= var_export($value, true);
$content .= ';' . PHP_EOL;
}
$success = file_put_contents($filename, $content);
// we saved new config.php, need to revalidate cache (only if opcache is enabled)
if (function_exists('opcache_invalidate')) {
opcache_invalidate($filename);
}
return $success;
}
public static function testDatabaseConnection($config): bool
{
$user = null;
$password = null;
$dns = [];
if( isset($config['database_name']) ) {
$dns[] = 'dbname=' . $config['database_name'];
}
if( isset($config['database_user']) ) {
$user = $config['database_user'];
}
if( isset($config['database_password']) ) {
$password = $config['database_password'];
}
if( isset($config['database_host']) ) {
$dns[] = 'host=' . $config['database_host'];
}
if( isset($config['database_port']) ) {
$dns[] = 'port=' . $config['database_port'];
}
try {
$connectionTest = new PDO('mysql:' . implode(';', $dns), $user, $password);
$connectionTest->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
}
catch(PDOException $error) {
error('MySQL connection failed. Settings has been reverted.');
error($error->getMessage());
return false;
}
return true;
}
public function getErrors() {
return $this->errors;
}
}

View File

@@ -110,4 +110,21 @@ class Cache
* @return bool * @return bool
*/ */
public function enabled() {return false;} public function enabled() {return false;}
public static function remember($key, $ttl, $callback)
{
$cache = self::getInstance();
if(!$cache->enabled()) {
return $callback();
}
$value = null;
if ($cache->fetch($key, $value)) {
return unserialize($value);
}
$value = $callback();
$cache->set($key, serialize($value),$ttl);
return $value;
}
} }

View File

@@ -82,6 +82,9 @@ class Creatures {
$armor = $monster->getArmor(); $armor = $monster->getArmor();
$defensev = $monster->getDefense(); $defensev = $monster->getDefense();
//load look
$look = $monster->getLook();
//load monster flags //load monster flags
$flags = $monster->getFlags(); $flags = $monster->getFlags();
if(!isset($flags['summonable'])) if(!isset($flags['summonable']))
@@ -147,6 +150,7 @@ class Creatures {
'armor' => $armor, 'armor' => $armor,
'race' => $race, 'race' => $race,
'loot' => json_encode($loot), 'loot' => json_encode($loot),
'look' => json_encode($look),
'summons' => json_encode($summons) 'summons' => json_encode($summons)
)); ));

View File

@@ -41,4 +41,3 @@ class Data
return $db->update($this->table, $data, $where); return $db->update($this->table, $data, $where);
} }
} }
?>

View File

@@ -10,7 +10,7 @@
*/ */
defined('MYAAC') or die('Direct access not allowed!'); defined('MYAAC') or die('Direct access not allowed!');
$configForumTablePrefix = config('forum_table_prefix'); $configForumTablePrefix = setting('core.forum_table_prefix');
if(null !== $configForumTablePrefix && !empty(trim($configForumTablePrefix))) { if(null !== $configForumTablePrefix && !empty(trim($configForumTablePrefix))) {
if(!in_array($configForumTablePrefix, array('myaac_', 'z_'))) { if(!in_array($configForumTablePrefix, array('myaac_', 'z_'))) {
throw new RuntimeException('Invalid value for forum_table_prefix in config.php. Can be only: "myaac_" or "z_".'); throw new RuntimeException('Invalid value for forum_table_prefix in config.php. Can be only: "myaac_" or "z_".');
@@ -47,7 +47,7 @@ class Forum
return return
$db->query( $db->query(
'SELECT `id` FROM `players` WHERE `account_id` = ' . $db->quote($account->getId()) . 'SELECT `id` FROM `players` WHERE `account_id` = ' . $db->quote($account->getId()) .
' AND `level` >= ' . $db->quote($config['forum_level_required']) . ' AND `level` >= ' . $db->quote(setting('core.forum_level_required')) .
' LIMIT 1')->rowCount() > 0; ' LIMIT 1')->rowCount() > 0;
} }

View File

@@ -10,7 +10,7 @@
*/ */
defined('MYAAC') or die('Direct access not allowed!'); defined('MYAAC') or die('Direct access not allowed!');
function is_sub_dir($path = NULL, $parent_folder = SITE_PATH) { function is_sub_dir($path = NULL, $parent_folder = BASE) {
//Get directory path minus last folder //Get directory path minus last folder
$dir = dirname($path); $dir = dirname($path);
@@ -41,9 +41,9 @@ function is_sub_dir($path = NULL, $parent_folder = SITE_PATH) {
use Composer\Semver\Semver; use Composer\Semver\Semver;
class Plugins { class Plugins {
private static $warnings = array(); private static $warnings = [];
private static $error = null; private static $error = null;
private static $plugin_json = array(); private static $plugin_json = [];
public static function getRoutes() public static function getRoutes()
{ {
@@ -56,22 +56,8 @@ class Plugins {
} }
$routes = []; $routes = [];
foreach(get_plugins() as $filename) { foreach(self::getAllPluginsJson() as $plugin) {
$string = file_get_contents(PLUGINS . $filename . '.json'); $warningPreTitle = 'Plugin: ' . $plugin['name'] . ' - ';
$string = self::removeComments($string);
$plugin = json_decode($string, true);
self::$plugin_json = $plugin;
if ($plugin == null) {
self::$warnings[] = 'Cannot load ' . $filename . '.json. File might be not a valid json code.';
continue;
}
if(isset($plugin['enabled']) && !getBoolean($plugin['enabled'])) {
self::$warnings[] = 'Skipping ' . $filename . '... The plugin is disabled.';
continue;
}
$warningPreTitle = 'Plugin: ' . $filename . ' - ';
if (isset($plugin['routes'])) { if (isset($plugin['routes'])) {
foreach ($plugin['routes'] as $_name => $info) { foreach ($plugin['routes'] as $_name => $info) {
@@ -80,7 +66,8 @@ class Plugins {
if ($method !== '*') { if ($method !== '*') {
$methods = is_string($method) ? explode(',', $info['method']) : $method; $methods = is_string($method) ? explode(',', $info['method']) : $method;
foreach ($methods as $method) { foreach ($methods as $method) {
if (!in_array($method, ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'HEAD'])) { $method = strtolower($method);
if (!in_array($method, ['get', 'post', 'put', 'patch', 'delete', 'head'])) {
self::$warnings[] = $warningPreTitle . 'Not allowed method ' . $method . '... Disabling this route...'; self::$warnings[] = $warningPreTitle . 'Not allowed method ' . $method . '... Disabling this route...';
} }
} }
@@ -161,28 +148,14 @@ class Plugins {
} }
$hooks = []; $hooks = [];
foreach(get_plugins() as $filename) { foreach(self::getAllPluginsJson() as $plugin) {
$string = file_get_contents(PLUGINS . $filename . '.json');
$string = self::removeComments($string);
$plugin = json_decode($string, true);
self::$plugin_json = $plugin;
if ($plugin == null) {
self::$warnings[] = 'Cannot load ' . $filename . '.json. File might be not a valid json code.';
continue;
}
if(isset($plugin['enabled']) && !getBoolean($plugin['enabled'])) {
self::$warnings[] = 'Skipping ' . $filename . '... The plugin is disabled.';
continue;
}
if (isset($plugin['hooks'])) { if (isset($plugin['hooks'])) {
foreach ($plugin['hooks'] as $_name => $info) { foreach ($plugin['hooks'] as $_name => $info) {
if (defined('HOOK_'. $info['type'])) { if (defined('HOOK_'. $info['type'])) {
$hook = constant('HOOK_'. $info['type']); $hook = constant('HOOK_'. $info['type']);
$hooks[] = ['name' => $_name, 'type' => $hook, 'file' => $info['file']]; $hooks[] = ['name' => $_name, 'type' => $hook, 'file' => $info['file']];
} else { } else {
self::$warnings[] = 'Plugin: ' . $filename . '. Unknown event type: ' . $info['type']; self::$warnings[] = 'Plugin: ' . $plugin['name'] . '. Unknown event type: ' . $info['type'];
} }
} }
} }
@@ -195,7 +168,108 @@ class Plugins {
return $hooks; return $hooks;
} }
public static function install($file) { public static function getAllPluginsSettings()
{
$cache = Cache::getInstance();
if ($cache->enabled()) {
$tmp = '';
if ($cache->fetch('plugins_settings', $tmp)) {
return unserialize($tmp);
}
}
$settings = [];
foreach (self::getAllPluginsJson() as $plugin) {
if (isset($plugin['settings'])) {
$settingsFile = require BASE . $plugin['settings'];
if (!isset($settingsFile['key'])) {
warning("Settings file for plugin - {$plugin['name']} does not contain 'key' field");
continue;
}
$settings[$settingsFile['key']] = ['pluginFilename' => $plugin['filename'], 'settingsFilename' => $plugin['settings']];
}
}
if ($cache->enabled()) {
$cache->set('plugins_settings', serialize($settings), 600); // cache for 10 minutes
}
return $settings;
}
public static function getAllPluginsJson($disabled = false)
{
$cache = Cache::getInstance();
if ($cache->enabled()) {
$tmp = '';
if ($cache->fetch('plugins', $tmp)) {
return unserialize($tmp);
}
}
$plugins = [];
foreach (get_plugins($disabled) as $filename) {
$plugin = self::getPluginJson($filename);
if (!$plugin) {
continue;
}
$plugin['filename'] = $filename;
$plugins[] = $plugin;
}
if ($cache->enabled()) {
$cache->set('plugins', serialize($plugins), 600); // cache for 10 minutes
}
return $plugins;
}
public static function getPluginSettings($filename)
{
$plugin_json = self::getPluginJson($filename);
if (!$plugin_json) {
return false;
}
if (!isset($plugin_json['settings']) || !file_exists(BASE . $plugin_json['settings'])) {
return false;
}
return $plugin_json['settings'];
}
public static function getPluginJson($filename = null)
{
if(!isset($filename)) {
return self::$plugin_json;
}
$pathToPlugin = PLUGINS . $filename . '.json';
if (!file_exists($pathToPlugin)) {
self::$warnings[] = "Cannot load $filename.json. File doesn't exist.";
return false;
}
$string = file_get_contents($pathToPlugin);
$plugin_json = json_decode($string, true);
if ($plugin_json == null) {
self::$warnings[] = "Cannot load $filename.json. File might be not a valid json code.";
return false;
}
if (isset($plugin_json['enabled']) && !getBoolean($plugin_json['enabled'])) {
self::$warnings[] = 'Skipping ' . $filename . '... The plugin is disabled.';
return false;
}
return $plugin_json;
}
public static function install($file): bool
{
global $db; global $db;
if(!\class_exists('ZipArchive')) { if(!\class_exists('ZipArchive')) {
@@ -234,8 +308,13 @@ class Plugins {
return false; return false;
} }
$pluginFilename = str_replace('.json', '', basename($json_file));
if (self::existDisabled($pluginFilename)) {
success('The plugin already existed, but was disabled. It has been enabled again and will be now reinstalled.');
self::enable($pluginFilename);
}
$string = file_get_contents($file_name); $string = file_get_contents($file_name);
$string = self::removeComments($string);
$plugin_json = json_decode($string, true); $plugin_json = json_decode($string, true);
self::$plugin_json = $plugin_json; self::$plugin_json = $plugin_json;
if ($plugin_json == null) { if ($plugin_json == null) {
@@ -435,7 +514,45 @@ class Plugins {
return false; return false;
} }
public static function uninstall($plugin_name) public static function isEnabled($pluginFileName): bool
{
$filenameJson = $pluginFileName . '.json';
return !is_file(PLUGINS . 'disabled.' . $filenameJson) && is_file(PLUGINS . $filenameJson);
}
public static function existDisabled($pluginFileName): bool
{
$filenameJson = $pluginFileName . '.json';
return is_file(PLUGINS . 'disabled.' . $filenameJson);
}
public static function enable($pluginFileName): bool {
return self::enableDisable($pluginFileName, true);
}
public static function disable($pluginFileName): bool {
return self::enableDisable($pluginFileName, false);
}
private static function enableDisable($pluginFileName, $enable): bool
{
$filenameJson = $pluginFileName . '.json';
$fileExist = is_file(PLUGINS . ($enable ? 'disabled.' : '') . $filenameJson);
if (!$fileExist) {
self::$error = 'Cannot ' . ($enable ? 'enable' : 'disable') . ' plugin: ' . $pluginFileName . '. File does not exist.';
return false;
}
$result = rename(PLUGINS . ($enable ? 'disabled.' : '') . $filenameJson, PLUGINS . ($enable ? '' : 'disabled.') . $filenameJson);
if (!$result) {
self::$error = 'Cannot ' . ($enable ? 'enable' : 'disable') . ' plugin: ' . $pluginFileName . '. Permission problem.';
return false;
}
return true;
}
public static function uninstall($plugin_name): bool
{ {
$filename = BASE . 'plugins/' . $plugin_name . '.json'; $filename = BASE . 'plugins/' . $plugin_name . '.json';
if(!file_exists($filename)) { if(!file_exists($filename)) {
@@ -443,9 +560,8 @@ class Plugins {
return false; return false;
} }
$string = file_get_contents($filename); $string = file_get_contents($filename);
$string = self::removeComments($string);
$plugin_info = json_decode($string, true); $plugin_info = json_decode($string, true);
if($plugin_info == false) { if(!$plugin_info) {
self::$error = 'Cannot load plugin info ' . $plugin_name . '.json'; self::$error = 'Cannot load plugin info ' . $plugin_name . '.json';
return false; return false;
} }
@@ -492,7 +608,8 @@ class Plugins {
return false; return false;
} }
public static function is_installed($plugin_name, $version) { public static function is_installed($plugin_name, $version): bool
{
$filename = BASE . 'plugins/' . $plugin_name . '.json'; $filename = BASE . 'plugins/' . $plugin_name . '.json';
if(!file_exists($filename)) { if(!file_exists($filename)) {
return false; return false;
@@ -500,7 +617,7 @@ class Plugins {
$string = file_get_contents($filename); $string = file_get_contents($filename);
$plugin_info = json_decode($string, true); $plugin_info = json_decode($string, true);
if($plugin_info == false) { if(!$plugin_info) {
return false; return false;
} }
@@ -523,26 +640,6 @@ class Plugins {
return self::$error; return self::$error;
} }
public static function getPluginJson() {
return self::$plugin_json;
}
public static function removeComments($string) {
$string = preg_replace('!/\*.*?\*/!s', '', $string);
$string = preg_replace('/\n\s*\n/', "\n", $string);
// Removes multi-line comments and does not create
// a blank line, also treats white spaces/tabs
$string = preg_replace('!^[ \t]*/\*.*?\*/[ \t]*[\r\n]!s', '', $string);
// Removes single line '//' comments, treats blank characters
$string = preg_replace('![ \t]*//.*[ \t]*[\r\n]!', '', $string);
// Strip blank lines
$string = preg_replace("/(^[\r\n]*|[\r\n]+)[\s\t]*[\r\n]+/", "\n", $string);
return $string;
}
/** /**
* Install menus * Install menus
* Helper function for plugins * Helper function for plugins

View File

@@ -32,5 +32,3 @@ class E_OTS_ErrorCode extends Exception
} }
/**#@-*/ /**#@-*/
?>

View File

@@ -36,5 +36,3 @@ class E_OTS_Generic extends E_OTS_ErrorCode
} }
/**#@-*/ /**#@-*/
?>

View File

@@ -22,5 +22,3 @@ class E_OTS_NotAContainer extends Exception
} }
/**#@-*/ /**#@-*/
?>

View File

@@ -32,5 +32,3 @@ class E_OTS_OTBMError extends E_OTS_ErrorCode
} }
/**#@-*/ /**#@-*/
?>

View File

@@ -22,5 +22,3 @@ class E_OTS_ReadOnly extends Exception
} }
/**#@-*/ /**#@-*/
?>

View File

@@ -37,5 +37,3 @@ interface IOTS_Cipher
} }
/**#@-*/ /**#@-*/
?>

View File

@@ -89,5 +89,3 @@ interface IOTS_DataDisplay
} }
/**#@-*/ /**#@-*/
?>

View File

@@ -96,5 +96,3 @@ interface IOTS_Display
} }
/**#@-*/ /**#@-*/
?>

View File

@@ -67,5 +67,3 @@ interface IOTS_GuildAction
} }
/**#@-*/ /**#@-*/
?>

View File

@@ -21,7 +21,6 @@
* @property string $password Password. * @property string $password Password.
* @property string $eMail Email address. * @property string $eMail Email address.
* @property int $premiumEnd Timestamp of PACC end. * @property int $premiumEnd Timestamp of PACC end.
* @property bool $blocked Blocked flag state.
* @property bool $deleted Deleted flag state. * @property bool $deleted Deleted flag state.
* @property bool $warned Warned flag state. * @property bool $warned Warned flag state.
* @property bool $banned Ban state. * @property bool $banned Ban state.
@@ -39,7 +38,7 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable
* @var array * @var array
* @version 0.1.5 * @version 0.1.5
*/ */
private $data = array('email' => '', 'blocked' => false, 'rlname' => '','location' => '', 'country' => '','web_flags' => 0, 'lastday' => 0, 'premdays' => 0, 'created' => 0); private $data = array('email' => '', 'rlname' => '','location' => '', 'country' => '','web_flags' => 0, 'lastday' => 0, 'premdays' => 0, 'created' => 0);
public static $cache = array(); public static $cache = array();
@@ -231,26 +230,22 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable
* @param int $id Account number. * @param int $id Account number.
* @throws PDOException On PDO operation error. * @throws PDOException On PDO operation error.
*/ */
public function load($id, $fresh = false, $searchOnlyById = false) public function load($id, $fresh = false)
{ {
if(!$fresh && isset(self::$cache[$id])) { if(!$fresh && isset(self::$cache[$id])) {
$this->data = self::$cache[$id]; $this->data = self::$cache[$id];
return; return;
} }
$numberColumn = 'id';
$nameOrNumber = ''; $nameOrNumber = '';
if (!$searchOnlyById) {
if (USE_ACCOUNT_NAME) { if (USE_ACCOUNT_NAME) {
$nameOrNumber = '`name`,'; $nameOrNumber = '`name`,';
} else if (USE_ACCOUNT_NUMBER) { } else if (USE_ACCOUNT_NUMBER) {
$nameOrNumber = '`number`,'; $nameOrNumber = '`number`,';
$numberColumn = 'number';
}
} }
// SELECT query on database // SELECT query on database
$this->data = $this->db->query('SELECT `id`, ' . $nameOrNumber . '`password`, `email`, `blocked`, `rlname`, `location`, `country`, `web_flags`, ' . ($this->db->hasColumn('accounts', 'premdays') ? '`premdays`, ' : '') . ($this->db->hasColumn('accounts', 'lastday') ? '`lastday`, ' : ($this->db->hasColumn('accounts', 'premend') ? '`premend`,' : ($this->db->hasColumn('accounts', 'premium_ends_at') ? '`premium_ends_at`,' : ''))) . '`created` FROM `accounts` WHERE `' . $numberColumn . '` = ' . (int) $id)->fetch(); $this->data = $this->db->query('SELECT `id`, ' . $nameOrNumber . '`password`, `email`, `rlname`, `location`, `country`, `web_flags`, ' . ($this->db->hasColumn('accounts', 'premdays') ? '`premdays`, ' : '') . ($this->db->hasColumn('accounts', 'lastday') ? '`lastday`, ' : ($this->db->hasColumn('accounts', 'premend') ? '`premend`,' : ($this->db->hasColumn('accounts', 'premium_ends_at') ? '`premium_ends_at`,' : ''))) . '`created` FROM `accounts` WHERE `id` = ' . (int) $id)->fetch();
self::$cache[$id] = $this->data; self::$cache[$id] = $this->data;
} }
@@ -268,8 +263,13 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable
*/ */
public function find($name) public function find($name)
{ {
$nameOrNumberColumn = 'name';
if (USE_ACCOUNT_NUMBER) {
$nameOrNumberColumn = 'number';
}
// finds player's ID // finds player's ID
$id = $this->db->query('SELECT `id` FROM `accounts` WHERE `name` = ' . $this->db->quote($name) )->fetch(); $id = $this->db->query('SELECT `id` FROM `accounts` WHERE `' . $nameOrNumberColumn . '` = ' . $this->db->quote($name) )->fetch();
// if anything was found // if anything was found
if( isset($id['id']) ) if( isset($id['id']) )
@@ -345,7 +345,7 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable
} }
// UPDATE query on database // UPDATE query on database
$this->db->exec('UPDATE `accounts` SET ' . ($this->db->hasColumn('accounts', 'name') ? '`name` = ' . $this->db->quote($this->data['name']) . ',' : '') . '`password` = ' . $this->db->quote($this->data['password']) . ', `email` = ' . $this->db->quote($this->data['email']) . ', `blocked` = ' . (int) $this->data['blocked'] . ', `rlname` = ' . $this->db->quote($this->data['rlname']) . ', `location` = ' . $this->db->quote($this->data['location']) . ', `country` = ' . $this->db->quote($this->data['country']) . ', `web_flags` = ' . (int) $this->data['web_flags'] . ', ' . ($this->db->hasColumn('accounts', 'premdays') ? '`premdays` = ' . (int) $this->data['premdays'] . ',' : '') . '`' . $field . '` = ' . (int) $this->data[$field] . ' WHERE `id` = ' . $this->data['id']); $this->db->exec('UPDATE `accounts` SET ' . ($this->db->hasColumn('accounts', 'name') ? '`name` = ' . $this->db->quote($this->data['name']) . ',' : '') . '`password` = ' . $this->db->quote($this->data['password']) . ', `email` = ' . $this->db->quote($this->data['email']) . ', `rlname` = ' . $this->db->quote($this->data['rlname']) . ', `location` = ' . $this->db->quote($this->data['location']) . ', `country` = ' . $this->db->quote($this->data['country']) . ', `web_flags` = ' . (int) $this->data['web_flags'] . ', ' . ($this->db->hasColumn('accounts', 'premdays') ? '`premdays` = ' . (int) $this->data['premdays'] . ',' : '') . '`' . $field . '` = ' . (int) $this->data[$field] . ' WHERE `id` = ' . $this->data['id']);
} }
/** /**
@@ -650,53 +650,6 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable
$this->data['email'] = (string) $email; $this->data['email'] = (string) $email;
} }
/**
* Checks if account is blocked.
*
* <p>
* Note: Since 0.0.3 version this method throws {@link E_OTS_NotLoaded E_OTS_NotLoaded} exception instead of triggering E_USER_WARNING.
* </p>
*
* @version 0.0.3
* @return bool Blocked state.
* @throws E_OTS_NotLoaded If account is not loaded.
*/
public function isBlocked()
{
if( !isset($this->data['blocked']) )
{
throw new E_OTS_NotLoaded();
}
return $this->data['blocked'];
}
/**
* Unblocks account.
*
* <p>
* This method only updates object state. To save changes in database you need to use {@link OTS_Account::save() save() method} to flush changed to database.
* </p>
*/
public function unblock()
{
$this->data['blocked'] = false;
}
/**
* Blocks account.
*
* <p>
* This method only updates object state. To save changes in databaseed to use {@link OTS_Account::save() save() method} to flush changed to database.
* </p>
*/
public function block()
{
$this->data['blocked'] = true;
}
/** /**
* Reads custom field. * Reads custom field.
* *
@@ -1041,7 +994,7 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable
$access = 0; $access = 0;
// finds ranks of all characters // finds ranks of all characters
foreach($this->getPlayersList() as $player) foreach($this->getPlayersList(false) as $player)
{ {
$rank = $player->getRank(); $rank = $player->getRank();
@@ -1147,9 +1100,6 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable
case 'playersList': case 'playersList':
return $this->getPlayersList(); return $this->getPlayersList();
case 'blocked':
return $this->isBlocked();
case 'deleted': case 'deleted':
return $this->isDeleted(); return $this->isDeleted();
@@ -1195,17 +1145,6 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable
$this->setPremiumEnd($value); $this->setPremiumEnd($value);
break; break;
case 'blocked':
if($value)
{
$this->block();
}
else
{
$this->unblock();
}
break;
case 'deleted': case 'deleted':
if($value) if($value)
{ {
@@ -1259,5 +1198,3 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable
} }
/**#@-*/ /**#@-*/
?>

View File

@@ -34,5 +34,3 @@ class OTS_AccountBans_List extends OTS_Bans_List
$this->setFilter($filter); $this->setFilter($filter);
} }
} }
?>

View File

@@ -735,5 +735,3 @@ class OTS_Admin
} }
/**#@-*/ /**#@-*/
?>

View File

@@ -100,5 +100,3 @@ class OTS_Bans_List extends OTS_Base_List
} }
} }
} }
?>

View File

@@ -265,5 +265,3 @@ abstract class OTS_Base_DB extends PDO implements IOTS_DB
} }
/**#@-*/ /**#@-*/
?>

View File

@@ -146,5 +146,3 @@ class OTS_BinaryTools
} }
/**#@-*/ /**#@-*/
?>

View File

@@ -149,5 +149,3 @@ class OTS_Container extends OTS_Item implements IteratorAggregate
} }
/**#@-*/ /**#@-*/
?>

View File

@@ -357,5 +357,3 @@ class OTS_FileLoader
} }
/**#@-*/ /**#@-*/
?>

View File

@@ -671,5 +671,3 @@ class OTS_Group extends OTS_Row_DAO implements IteratorAggregate, Countable
} }
/**#@-*/ /**#@-*/
?>

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