Compare commits

..

124 Commits

Author SHA1 Message Date
slawkens
a11d038c1d Update to 0.8.6 2021-07-10 23:35:57 +02:00
slawkens
2f627bf4b0 VERSION needs eol=lf 2021-07-10 23:35:02 +02:00
slawkens
67c603ef94 Fix some unexpected behaviour in release.sh on "cd" command 2021-07-10 23:24:48 +02:00
slawkens
dec63f353f Update to 0.8.6-dev 2021-07-05 03:13:30 +02:00
slawkens
7ab6b026fb Move admin pages part 2 2021-07-05 03:11:42 +02:00
slawkens
a2a773d714 This is the actual security fix 2021-07-05 02:59:41 +02:00
slawkens
aa26a71949 Revert "Security fix"
This reverts commit ef2a408298.
2021-07-05 02:51:45 +02:00
slawkens
e3c695175b Update admin files path 2021-07-04 07:10:46 +02:00
slawkens
ccdcdd01d8 Move admin files 2021-07-04 06:50:34 +02:00
slawkens
ef2a408298 Security fix
Don't allow slash in URL
2021-07-03 08:38:32 +02:00
slawkens
6a4dbcef62 Fix release.sh (some warning) 2021-06-08 23:18:24 +02:00
slawkens
c8a87a2a8a Update CHANGELOG.md 2021-06-08 22:26:54 +02:00
slawkens
d0bfe93d38 Update VERSION 2021-06-08 22:26:14 +02:00
slawkens
75df8c5a6a Update VERSION 2021-06-08 22:20:57 +02:00
slawkens
b55813e362 Update to v0.8.5 2021-06-08 22:19:52 +02:00
slawkens
575f0c62b4 Update CHANGELOG.md 2021-06-08 22:18:42 +02:00
slawkens
3e9544f1dc Fix forum boards white color style
So it works on all templates
2021-06-08 22:16:42 +02:00
slawkens
152e5ac70e Fix forum table style (boards & thread view) 2021-06-08 22:16:03 +02:00
slawkens
3544643a07 Fix guild back buttons (change logo & motd) 2021-06-08 22:15:47 +02:00
slawkens
f7ae76d10f Remove unneeded escape 2021-06-08 22:15:31 +02:00
slawkens
add9370696 Update CHANGELOG.md 2021-06-08 22:15:17 +02:00
anyeor
cadc17cc52 Update 404 response (#163)
Updating for new SPL standard.
2021-06-05 05:17:51 +02:00
slawkens
878dfc5a01 bcsub is not needed here
bcmath module is not required anymore
2021-05-01 01:21:22 +02:00
slawkens
2400f7c20a Fix #158 Thanks @Misztrz 2021-05-01 01:05:19 +02:00
czbadaro
9d7854dda6 Gratis premium account (#156)
* skip premdays and lastdays calculation when premdays = 65535 (gratis premium in TFS)

* TFS consider 65535 as gratis premium account and PHP_INT_MAX does not assume this value

* adds condition of premdays=65535 and standardize the label "gratis premium account" with tibia client

* adjust the label "days" when there is only one day of premium account

* adjusted premium account status

* Some small adjustment

* Sorry, typo.

Co-authored-by: slawkens <slawkens@gmail.com>
2021-04-22 22:49:42 +02:00
slawkens
7303aabc2b Some small fix regarding parsing creature name from request 2021-04-22 19:13:37 +02:00
slawkens
ab478f488a Fix some unexpected behaviour in characters.php
Just in case someone uses $storage variable somewhere in their code
Thanks TheEther
2021-04-14 02:20:26 +02:00
slawkens
c7a2b090d7 Fix guild list description new lines <br> being ignored
Thanks TheEther for reporting
2021-04-08 22:08:37 +02:00
slawkens
f2c3b6362d Fix travis 2021-02-23 23:13:22 +01:00
slawkens
c664be7b74 Update version to 0.8.5-dev 2021-02-23 15:10:44 +01:00
slawkens
aa17ddbf24 Fix compatibility with PHP 7.0 and lower 2021-02-23 15:10:03 +01:00
slawkens
62faacbed6 Update CHANGELOG.md 2021-02-18 18:41:58 +01:00
slawkens
d03d6e2ec1 Release of v0.8.4 2021-02-18 18:19:04 +01:00
slawkens
93a1760263 Patch "Delete char with house" from develop
Co-Authored-By: Lee <42119604+Leesneaks@users.noreply.github.com>
2021-02-16 02:18:13 +01:00
Lee
0de8894e4d #142 Guildnick fix
Fixes the Guildnick not showing in the guild pages.
2021-02-16 02:10:30 +01:00
slawkens
e95ea22dbd Revert "Fix phpmailer array style (PHP 8.0)"
This reverts commit 0ba886bc6b.
2021-02-16 01:56:21 +01:00
slawkens
5dbfde62a6 Update .travis.yml 2021-02-16 01:56:11 +01:00
slawkens
0ba886bc6b Fix phpmailer array style (PHP 8.0) 2021-02-16 01:42:42 +01:00
slawkens
2684205b5a More fixes for PHP 8.0 2021-02-16 01:39:58 +01:00
slawkens
856507fb66 Update .travis.yml 2021-02-16 01:33:53 +01:00
slawkens
d019fbc050 Attempt to fix travis build 2021-02-16 01:31:48 +01:00
slawkens
129d5653e6 Apply changes from develop branch 2021-02-16 01:18:01 +01:00
slawkens
9560ad0c20 Add missing migration from 0.9 2021-02-16 01:06:03 +01:00
slawkens
a4fa7567aa Increase size of myaac_visitors.page column to 2048
Thanks to OtLand user kaleuui (https://otland.net/threads/myaac-v0-8-3.268654/page-11#post-2643853)
2021-02-16 01:05:29 +01:00
slawkens
9ff032740c Minimum PHP 5.6 is now required 2021-02-16 00:30:56 +01:00
slawkens
dbc76abcdd Fix compatibility with PHP 8.0 (latest XAMPP)
Solution by doctrine developers
2021-02-16 00:29:09 +01:00
slawkens
746a5dc816 Fix setPremDays for latest TFS
Fixes editing account in admin panel
2021-02-15 21:05:19 +01:00
slawkens
194d110079 Fixed account getPremDays() function for latest TFS
This fixes account management + signature
2021-02-15 20:57:54 +01:00
slawkens
eed490507c Fix parsing empty strings in config.lua (with comments) 2021-02-13 22:56:53 +01:00
slawkens
2800ab1e88 Fix headling.php cannot find font 2021-02-13 22:35:57 +01:00
slawkens
faf40f8bed Fix typo 2021-02-13 22:08:38 +01:00
slawkens
3f12ee40ac Update .gitignore 2021-02-13 21:55:35 +01:00
slawkens
b4532bd473 Add ./login.php to .gitignore 2021-02-13 21:55:08 +01:00
slawkens
b389874a7e Ignore arrays in config.lua (fixes experienceStages loading)
In future we want to parse arrays too, this is just a temporary solution
Thread: https://otland.net/threads/myacc-problem.274795/
2021-02-13 21:54:12 +01:00
slawkens
ea2dc69f7c Add more clients to clients.conf.php 2021-01-18 01:49:08 +01:00
slawkens
b0593b0ae1 Fixed the check if vocations.xml were correctly loaded 2021-01-17 17:44:53 +01:00
slawkens
664348e475 Merge branch 'master' of https://github.com/slawkens/myaac 2021-01-17 17:16:02 +01:00
slawkens
e3e00f0109 Just typo.. 2021-01-17 17:15:54 +01:00
slawkens
d3850280f4 Add some badges to README.md 2021-01-17 10:18:43 +01:00
slawkens
d8b3b41358 Remove facebook.js, replace with direct live link
This fixes some console errors
2021-01-07 23:34:17 +01:00
slawkens
e7706cad74 Use local storage for saving menu items
Fixes a bug when visiting with browser: www.wykop.pl, and then navigating back to myaac (browser freeze)
2021-01-07 22:43:39 +01:00
slawkens
727d6788fe Password can now contain any characters
Also added limit of 29 characters (client limitation)
2020-12-30 00:28:42 +01:00
slawkens
e3ecf8ec96 Fix notice about premend 2020-12-30 00:28:05 +01:00
slawkens
1999b19a1c Add support for accounts.premium_ends_at (Latest tfs 1.x) 2020-12-30 00:11:46 +01:00
slawkens
c55e2910ac On prod it won't display any PHP errors
As suggested by PHP Manual
2020-12-29 22:11:58 +01:00
slawkens
ad3694ef96 Add SSL on external image requests of items and outfits
Co-Authored-By: Fernando Matos <fernando@pixele.com.br>
2020-12-26 23:45:36 +01:00
slawkens
7fd784b2f6 You cannot delete character more than twice (Thanks Okke) 2020-11-24 16:13:23 +01:00
slawkens
d8f0ac5880 Update .gitignore 2020-11-02 23:29:54 +01:00
slawkens
b4ee4de110 Bump version to 0.8.4-dev 2020-11-02 23:19:38 +01:00
slawkens
b9713fea76 Fix branch 2020-10-27 08:10:23 +01:00
slawkens
c6dd937922 Release 0.8.3 2020-10-27 07:53:11 +01:00
slawkens
81d4158c03 Update CHANGELOG.md 2020-10-27 07:51:30 +01:00
slawkens
bf0e6ff862 Add accept=".zip" to plugin upload file 2020-10-24 05:32:28 +02:00
slawkens
8518afe70d Fix two boxes being show on email_change_cancel 2020-10-12 22:30:04 +02:00
slawkens
091ab688e7 Fix when adding poll = template tibiacom broken
With Exception and red message
2020-10-12 21:59:47 +02:00
slawkens
2e5b066d88 Remove duplicated code 2020-10-09 20:07:56 +02:00
slawkens
cd3a15feab Add pdo_mysql as required extension
+ Some code refactoring
2020-10-09 20:07:20 +02:00
slawkens
836499a48c Fix some PhpStorm editor error message 2020-10-09 20:06:08 +02:00
slawkens
4983816ff6 Change wrong table header: Description -> Version 2020-10-09 20:03:39 +02:00
slawkens
0326657d60 Fix creating very uncommon (bugged) account names 2020-07-07 01:23:36 +02:00
slawkens
fcff820858 Fix #131 2020-07-07 00:53:56 +02:00
whiteblXK
dc536f0fc0 Added limit to search characters (#134)
* Update characters.php

* Update config.php

* Variable name change, better use LIMIT in query instead in loop

* Just to be sure. Security first :)

* use config function

Co-authored-by: slawkens <slawkens@gmail.com>
2020-07-07 00:31:50 +02:00
slawkens
f958b8dd4f Change hasTable -> hasColumn 2020-07-07 00:16:09 +02:00
slawkens
352d3b1bde Merge pull request #133 from whiteblXK/patch-1
Fixed bug with showing hidden characters
2020-07-06 23:59:50 +02:00
whiteblXK
f3061a0e74 Fixed bug with showing hidden character 2020-07-06 23:07:18 +02:00
slawkens
d4222e98e6 Fix #132 2020-07-03 23:24:46 +02:00
slawkens
8dd07d4873 Fix account create when account_mail_verify is enabled 2020-07-03 22:44:21 +02:00
slawkens
5f891fb9d6 Add some notice about Email validation 2020-07-03 22:15:27 +02:00
slawkens
b3b6d0ff5d Fix for CloudFlare IP detection 2020-07-03 20:38:48 +02:00
slawkens
0ac01b3f0d Fix undefined constant 2020-06-26 23:57:22 +02:00
slawkens
c6e55edb09 Fix network_twitter link in tibiacom template 2020-06-20 08:50:11 +02:00
slawkens
dfc70c098f Fix XSS in character search 2020-06-06 18:32:22 +02:00
slawkens
c1d1e9596a Update CHANGELOG.md 2020-06-06 18:01:40 +02:00
slawkens
53078e046e Fix admin menu news editing warning when leaving page without touching the inputs 2020-06-06 17:57:23 +02:00
slawkens
2af968031c Update version to 0.8.3-dev 2020-06-06 09:10:37 +02:00
slawkens
bdd3c394a3 Move register DATABASE_VERSION into schema.sql
Caused migrations being fired when user manually imported database
2020-06-06 07:33:33 +02:00
slawkens
f719b3c112 Update CHANGELOG.md 2020-06-03 23:56:13 +02:00
slawkens
8e0001a635 Fix release branch 2020-06-03 23:47:46 +02:00
slawkens
5b3581b88e Update CHANGELOG.md 2020-06-03 21:39:47 +02:00
slawkens
ca1436ea3f Fix #123 Guild Invite not working on otservbr-global 2020-06-03 21:35:45 +02:00
slawkens
5cd6b79ee0 Revert some change I did
Causing "'" and "-" being accepted as first character in player name
2020-06-03 21:21:28 +02:00
slawkens
0ec5942ee4 Update CHANGELOG.md 2020-06-03 21:04:49 +02:00
slawkens
90af164a8a Release v0.8.2 2020-06-03 21:02:33 +02:00
slawkens
fd83ee37ae Update CHANGELOG.md for 0.8.2 release 2020-06-03 21:01:36 +02:00
slawkens
8e935e62be Avoid ERR_TOO_MANY_REDIRECTS on template change
(cherry picked from commit 523afccb51)
2020-06-03 20:42:52 +02:00
slawkens
a0d38b1f36 Fix #128 (Remove MyISAM engine) from migration scripts
(cherry picked from commit 2c09b0ae86)
2020-06-03 20:42:41 +02:00
slawkens
6b49ecc99a Fix message() function when executed in CLI
(cherry picked from commit 8de8ad13bf)
2020-06-03 20:42:36 +02:00
slawkens
ae24a464dc Add new constant: IS_CLI
Also fixed some warnings when running in CLI mode

(cherry picked from commit 70bd442bb0)
2020-06-03 20:42:29 +02:00
slawkens
f519784cae Fix #126 (Max count and chance not shown)
(cherry picked from commit 5250b3189b)
2020-06-03 20:42:10 +02:00
slawkens
601cbd5ab7 dummy me.. thanks @gerotib
(cherry picked from commit 2534651e20)
2020-06-03 20:42:05 +02:00
Lee
fd4a507645 Update version.php
- removed extra line that is added when using a newer version than official release.

(cherry picked from commit e2ab301340)
2020-06-03 20:41:53 +02:00
slawkens
bf8d07226e Fix #125 (wrong mana of character samples)
Should be 90.

(cherry picked from commit 700f835243)
2020-06-03 20:41:36 +02:00
slawkens
fcddfb6adf Remove duplicated code
(cherry picked from commit 9ce7162a04)
2020-06-03 20:41:23 +02:00
slawkens
5fcd97129e Rewrite towns support for TFS 1.3
Won't show warning anymore

(cherry picked from commit cd58008a0f)
2020-06-03 20:41:14 +02:00
slawkens
af3a1c2f55 Add error_reporting in admin panel
Same as in main page

(cherry picked from commit 1f6bd975d0)
2020-06-03 20:41:08 +02:00
slawkens
13584a4d96 Move migration into separate file + add into admin panel
This fixes some rare bugs when database is no up-to-date and someone enters admin panel

(cherry picked from commit dbe83f8a74)
2020-06-03 20:40:52 +02:00
slawkens
6de4953d50 Change input type of account_login to text
This fixes autofill by Chrome and other tools

(cherry picked from commit fb326d0354)
2020-06-03 20:40:21 +02:00
slawkens
b15c213890 Add executing missing migration on install
This fixes missing rules on clean install

(cherry picked from commit 8e04328482)
2020-06-03 20:40:13 +02:00
slawkens
2f52e5d9f3 Fixes in create new character nick
+ fixed config.character_name_min/max_length being ignored in change_name.php

(cherry picked from commit d148b71f0f)
2020-06-03 20:39:52 +02:00
Lee
1d6afea9c4 CreateChar Fix
-checks if name has double space on create character (#121)

(cherry picked from commit 4e68838172)
2020-06-03 20:35:13 +02:00
slawkens
8d79efd6ad Add system/data to .gitignore
(cherry picked from commit 1799ef42a7)
2020-06-03 20:34:47 +02:00
slawkens
99bcd54afe Fix cancel change email request
Thanks to OtLand user anyeor

(cherry picked from commit df59b104db)
2020-06-03 20:34:36 +02:00
slawkens
6ce6eee529 Fix exception when characters.frags enabled on TFS 1.x
(cherry picked from commit ee6e68d0bf)
2020-06-03 20:34:19 +02:00
slawkens
054b40e358 Add example quest
(cherry picked from commit 7c208b38ed)
2020-06-03 20:33:53 +02:00
839 changed files with 48048 additions and 16651 deletions

View File

@@ -11,9 +11,4 @@ insert_final_newline = true
[*.md]
trim_trailing_whitespace = false
[{composer.json,package.json}]
indent_style = space
[package.json]
indent_size = 2
indent_style = tab

1
.gitattributes vendored
View File

@@ -8,3 +8,4 @@ _config.yml export-ignore
release.sh export-ignore
*.sh text eol=lf
VERSION text eol=lf

View File

@@ -1,13 +0,0 @@
name: PHP Linting
on:
pull_request:
branches: [master, develop]
push:
branches: [master]
jobs:
phplint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- uses: michaelw90/PHP-Lint@master

16
.gitignore vendored
View File

@@ -1,19 +1,15 @@
Thumbs.db
.DS_Store
.idea
tmp
# composer
composer.lock
vendor
# npm
node_modules
# created by release.sh
releases
tmp
config.local.php
PERSONAL_NOTES
# all custom templates
templates/*
@@ -39,10 +35,6 @@ system/logs/*
system/data/*
!system/data/index.html
# php sessions
system/php_sessions/*
!system/php_sessions/index.html
# plugins
plugins/*
!plugins/.htaccess
@@ -50,9 +42,7 @@ plugins/*
!plugins/account-create-hint.json
!plugins/account-create-hint
landing
# system
system/functions_custom.php
/login.php
# others/rest
system/pages/downloads.php

View File

@@ -1,6 +1,8 @@
language: php
php:
- 5.6
- 7.0
- 7.1
- 7.2
- 7.3
@@ -15,4 +17,4 @@ 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" .
- php vendor/bin/parallel-lint --no-progress --no-colors --exclude vendor --exclude "system/libs/pot/OTS_DB_PDOQuery_PHP71.php" .

View File

@@ -1,9 +1,742 @@
# Changelog
## [0.9.0 - x.x.2020]
## [0.8.6 - 10.07.2021]
This update contains very important security fix.
### Added
Please update your MyAAC instances to this version.
## [0.8.5 - 08.06.2021]
### Changed
* bcmath module is not required anymore
* Gratis premium account fixes (#156, by @czbadaro)
* Update 404 response (#163, by @anyeor)
### Fixed
* compatibility with PHP 7.0 and lower
* deleting ranks in guilds (#158, by @Misztrz)
* guild back buttons (change logo & motd)
* forum table style (boards & thread view)
* guild list description new lines `<br>` being ignored (Thanks @anyeor for reporting)
## [0.8.4 - 18.02.2021]
### Added
* support for accounts.premium_ends_at (Latest TFS 1.x)
* more clients to clients.conf.php
### Changed
* minimum PHP 5.6 is now required
* password can now contain any characters
* add SSL on external image requests of items and outfits (@fernandomatos)
* Use local storage for saving menu items (tibiacom template) - fixes bug with some websites like wykop.pl (browser freeze)
* increase size of myaac_visitors.page column to 2048 (Thanks to OtLand user kaleuui)
### Fixed
* compatibility with PHP 8.0 (latest XAMPP)
* displaying PHP errors on env = "prod"
* the Guildnick not showing in the guild pages (@leesneaks)
* you cannot delete character more than twice (Thanks Okke)
* ignore arrays in config.lua (fixes experienceStages loading)
* parsing empty strings in config.lua (with comments)
* headling.php cannot find font
## [0.8.3 - 27.10.2020]
### Added
* pdo_mysql as required extension
* some notice about Email validation in create account
### Changed
* Move register DATABASE_VERSION into schema.sql
* Caused migrations being fired when user manually imported database
### Fixed
* creating very uncommon (bugged) account names
* XSS in character search
* Admin menu news editing warning when leaving page without touching the inputs
* Guild Invite not working on otservbr-global
* two boxes being show on email_change_cancel
* when adding poll = template tibiacom broken
* houses: Unknown column 'guild' in 'where clause (https://github.com/slawkens/myaac/issues/131)
* account create when account_mail_verify is enabled
* CloudFlare IP detection
* network_twitter link in tibiacom template
## [0.8.2 - 03.06.2020]
### Added
* Log query time in database_log (can be used for benchmarking)
* new PHP constant: IS_CLI
* $_SERVER['REQUEST_URI'] to database.log
* outfit to highscores box in tibiacom template
* system/data to .gitignore
* error_reporting in admin panel (when in dev mode), so it shows php notices and warnings
* example quests in config.php
### Changed
* account_login input type from password to text
### Fixed
* Guild Invite not working on otservbr-global (#123)
* news not updating after adding in admin panel
* wrong mana of character samples (#125)
* missing rules page on clean install
* double space character name creation (@Lee, #121)
* creatures page: Max count and chance not shown on hovered items
* exception being thrown when characters.frags enabled on TFS 1.x
* TFS 0.4 guilds creation (Where guilds.checkdata and motd doesn't have default value)
* ERR_TOO_MANY_REDIRECTS browser error on template change
* updating template menus on template change
* Account change info when config.account_country is disabled
* cancel change email request
* config.character_name_min/max_length being ignored in change_name.php
* some rare bugs when database is no up-to-date and someone enters admin panel
* extra line that is added when using a newer version than official release (@Lee)
* admin links in featured article
* some PHP Notice when HTTP_HOST is not set (Can happen on some old versions of HTTP protocol)
* Show character indicator in check_name.js
* Houses list View button was wrong (was from bootstrap)
* OTS_House __construct - not loading by houseid parameter
* message() function when executed in CLI
### Removed
* unused myaac_commands table from schema
* MyISAM engine from migration scripts (#128)
## [0.8.1 - 10.03.2020]
### Added
* Support for Nostalrius OTS
### Changed
* Move TODO to wiki
* .tooltip css class to .item_image (bootstrap conflict)
### Fixed
* Reloading of creatures/monsters throwing an exception
* Loading custom pages with old Gesior variables [#108](https://github.com/slawkens/myaac/issues/107)
* Some weird behaviour with installation of plugins
* CHANGELOG.md loading in Admin Panel
* spells displaying when level = 0
* Some PHP warnings and notices
## [0.8.0 - 19.02.2020]
### Added:
* new Awesome Bootstrap Admin Panel by Lee (@Leesneaks)
* using Bootstrap 3
* all existing pages were adjusted
* new editor: Accounts
* improved editor: Players
* new Reports View page
* Modules directory, which can be added using Plugins (@Leesneaks, @whiteblXK)
* move News Management here (@whiteblXK)
* interactive player outfit chooser (@tobi132)
* added Highscores by balance
* possibility to define colors and "Open in New Tab" on Template Menus (needs to be supported by Template)
* support for database persistent and socket connections (performance boost)
* Team page - display outfits of the players (configurable)
* added clear_cache.php, send_email.php bin commands (@slawkens, @tobi132)
* added locale pt_br (@ivenspontes)
* added load time into items & weapons loading admin page
* new, beautiful exception handler
* added travisci to prevent mistype (@gpedro, #89)
* added showing database name into installation script (@tobi132)
* compatibility with old z_ gesior table (@tobi132, #46)
* added nginx-sample.conf, .editorconfig, VERSION
* database towns table support for TFS 1.3 (@tobi132)
* added enable_tinymce option to Pages editor
### Fixed:
* account login redirect with special chars (like '&' and '?')
* black skull info at serverInfo (@tornadia)
* set correct limit at lastkills page from config (anyeor from OtLand)
* myaac_monsters table column loot problem (#79)
* players column deleted install description (@gpedro, #91)
* experience table being to wide and buggy on some templates (@tobi132, #90)
* fix errors with .htaccess files
* added index.html to prevent indexing the folder by mod_index
### Changed:
* Environment is now configurable by env setting (Significantly better load times with 'prod')
* replace spells, monsters tables with JavaScript Sortable Tables - DataTables (@Leesneaks)
* change default MySQL Storage Engine to InnoDB and Default Character Set to utf8
* updated OTS_House class to support latest TFS 1.x (new columns)
* updated monster images to the original ones from tibia.com
* increased the minimum length (3 -> 4) and decreased the maximum length (25 -> 21) of the New Character Name (by @vankk)
* use $db->exec instead of $db->query optimisation
* move items from database to Cache_PHP (Much more faster load time)
* allow simultaneous loading of config.ini and config.php in templates
* updated copyright year and SSL link (@EPuncker, #88)
* move commands, rules and downloads pages into database (@tobi132)
* better view of guilds (new buttons, table look and feel) (@tobi132)
* remove stupid alerts on account create
* remove .dist extension from .htaccess
### New Configurables (config.php)
* env (Environment)
* account_create_auto_login (Auto Login after Create Account - Registration)
* account_create_character_create (Create Character directly on Create Account page) (@tobi132)
* footer_show_load_time (display load time of the page in the footer)
* database_socket (Connection via Unix Socket)
* database_persistent (Database Persistent Connection)
* database_log (Logging of Database Queries)
* admin_panel_modules (Modules displayed in Admin Panel Dashboard)
* status_timeout, status_interval
* smtp_debug (More info about SMTP errors in error.log)
* team_display_outfit (Display outfit of the team members on teams page)
* highscores_balance (Display highscores by balance)
* character_name_min/max_length (Minimum and maximum length of character name)
* characters.deleted (display deleted characters on characters page)
### Forum:
* show image in full screen on click
* show user avatar (outfit) in posts
* replaced forum actions links (move, remove, edit, quote) with images
* redirect directly to the thread on user login (on new reply)
### Installer:
* AJAX loader for the important stuff
* create admin account: ask for e-mail + character name
* load items & weapons
* check user IP on install to prevent install by random user
* remember status of the installation
* remember language on first step (welcome)
* ask user for timezone
* auto detected browser language in select language
### Plugins
* sandbox for plugins, don't install when requirements are not satisfied
* allow comments inside plugin json file (php style)
* new require options for plugins: (look into example.json)
* require database version, table or column of the MyAAC schema
* require php-extension
* require semantic-version (like in composer.json)
* new hooks: LOGIN, LOGIN_ATTEMPT, LOGOUT, HOOK_ACCOUNT_CREATE_*
### Cache
* php 7.x APCu cache support (faster cache engine)
* new cache engine: plain PHP (is good with pure php 7.0+ and opcache)
* cache lastkills.php, $db->hasTable, $db->hasColumn, hooks and template menus
* stop using global $cache variable, use Singleton pattern instead
### Twig
* move pages to Twig templates: team, lastkills, serverinfo, houses, guilds.list, guild.view, admin.logs, admin.reports (@whiteblXK, @tobi132)
* replace "$twig->render()" with "$this->display"
* move Twig functions to separate file
* move tibiacom boxes to Twig templates
* allow Pages to be loaded as Twig template (this allows using Twig variables in Pages) (@tobi132)
* allow string to be passed to hook twig function
### Functions
* config($key), configLua($key)
* clearCache()
* OTS_Account:
* getCountry()
* setLastLogin($lastlogin) (@Leesneaks)
* setWebFlags(webflags) (@Leesneaks)
* OTS_Player:
* getAccountId()
* countBlessings() (@Leesneaks)
* checkBlessings($count) (@Leesneaks)
* is_sub_dir (in system/libs/plugins.php)
* Twig:
* getPlayerLink($name, $generate = true)
* removed SQLquote and SQLquery from OTS_Base_DB
* Add optional $params param into log_append (will log arrays) (@tobi132)
### Internal
* moved clients list to the new file (clients.conf.php)
* changed tableExist and fieldExist to $db->hasTable(table) + $db->hasColumn(table, column)
* changed deprecated $ots->createObject() functions with their OTS_ equivalents
* add global helper config($key) function + twig binding
* use config() instead of global $config
* remove unnecessary parentheses in include/require PHP functions
* use __DIR__ instead of dirname(__FILE__) - since PHP 5.3.0
* change intval() function to (int) casting (up to 6x faster)
* add release.sh script (for GitHub releases)
* use curl as alternative option for reporting install
### Libraries
* updated Twig to version v1.35.0
* updated TinyMCE to version v4.7.4
### Deprecations
* change deprecated HTML <center> tag to <div style="text-align:center">
* replace deprecated HTML <font> tag with <span>
## [0.7.11 - 04.05.2019]
### Added:
* support for some old servers, where arrays are used in config.lua
* an additional text to the install page informing that user can reinstall MyAAC by deleting config.local.php
### Fixed:
* XSS in forum show_thread
* guilds - "Add new rank" function
* multiple mail recipients when using admin mailer function
* Admin Panel - MyAAC logs not shown if servers logs directory doesn't exist (#47)
* missing prefix for cache get() and delete() functions
* add fatal error message when myaac tables in database do not exist
* the mystical defect where "Create Account" button was not highlighted (on the account/manage page)
* bug where server_config table does not exist (OTHire as an example)
* database_name in Usage_Statistics
* forgot to open <head> in install template
### Changed:
* do not display software version
## [0.7.10 - 03.03.2018]
### Added:
* new configurable: smtp_secure
* robots.txt
### Fixed:
* editing an existing page that had php enabled
* chrome bug on save (when editing page) ERR_BLOCKED_BY_XSS_AUDITOR
* showing IP and Port in admin panel (#44, by miqueiaspenha)
* deleting plugin showing "You don't have rights to delete"
* some bug with PHPMailer not finding its language file
* default accounts.vote value
* saving some really high long ip addresses
### Changed:
* update config.highscores_ids_hidden on install when there are samples already in database
* auto add z_polls table on install
### Internal:
* changed mb_strtolower functions to strtolower()
* added new function: $hooks->exist($type)
## [0.7.9 - 13.01.2018]
* removed 6mb of trash (some useless things)
* (fix) TFS 1.x not showing promoted vocations in highscores
* otserv 0.6.x: fixed some warning (on the characters page) and fatal mysql error (on the mango signature)
* fixed default stamina on otserv 0.6.x engine (and some others perhaps)
* install: change permission check to is_writable
* changed highscores_groups_hidden to 3 (for TFS 1.x)
* updated background-artwork (tibiacom template) to the latest version, removed other ones
## [0.7.8 - 12.01.2018]
* fixed installation error " call to undefined method OTS_DB_MySQL::hasColumn()"
* updated tinymce to the latest (4.7.4) version
* enabled emoticons plugin in tinymce :)
* some security fixes
## [0.7.7 - 08.01.2018]
* important fix for servers with promotion column (caused player.vocation to be resetted when saving player, for example: on change name, accept invite to guild, leave guild)
* immediately reload config.lua when there's change in config.server_path detected
* added new forum option: "Enable HTML" (only for moderators)
* fixed othire default column value (#26)
* fixed saving custom vocations in admin panel (#36)
* fixed warning in highscores when vocation doesn't exist
* fixed characters page - config.characters.frags "Notice: Use of undefined constant"
* fixed getBoolean function when boolean is passed
* fixed empty success message on leave guild
* fixed displaying premium account days
* function OTS_Account:getPremDays will now return -1 if there's freePremium configurable enabled on the server
* fixed tr bgcolor in characters view (Frags) (#38)
* fixed some warning in guild show
* fixed PHP warning about country not existing on online and characters pages
* fixed forum bbcode parsing
* don't add extra <br/> to the TinyMCE news forum posts
* (internal) using $player->getVocationName() where possible instead of older method
## [0.7.6 - 05.01.2017]
* fixed othire account creating/installation
* fixed table name players -> players_online
* fixed unexpected error logging about email fail
* added max_execution_time to the install finish step
* some small fix regarding highscores vocation box
## [0.7.5 - 04.01.2017]
* fixed bug on othire with config.account_premium_days
* fixed bug on TFS 1.x when online_afk is enabled
* warning about leaving news page with changes
* added player status to tibiacom top 5 highscores box
* save detected country on create account in session
* fixed getPremDays and isPremium functions (newest 11.x engines are bugged when it comes to PACC, its not fault of MyAAC)
* fix when there are no changelogs or highscores yet
* small fix regarding getTopPlayers function which was ignoring $limit variable
* fixed news adding when type != ARTICLE
* fixed template path finding
* fixed displaying article_text when it was empty saved
## [0.7.4 - 24.12.2017]
* fixed mysql fatal error on tibiacom template - top 5 box
* fixed displaying of level percent bar on tibian signature
* inform user about Twig cache failure on installation, instead of http 500 error
* when dir system/cache is not writable by the webserver, then show some nice notice to the user about it instead of http 500 error
* remember client version select and usage stats checkbox in session on install
* automatically update highscores_ids_hidden for users who installed myaac before (migration)
## [0.7.3 - 18.12.2017]
* auto generate myaac cache & session prefix on install to be unique across installations
* fixed hiding shop system menu on tibiacom template when disabled in config
* prevent adding duplicated newses with installation
* some changes to sample characters: chanced town_id to 1, posx: 1000, posy: 1000, posz: 1000 and default group_id to 1 so you can change in-game outfits and they will be used
* added version 772 constant to install client choose (OTHire)
* better solution for hidding samples (configurable) - highscores_ids_hidden
* fixed account.login redirect not working on tibiacom template
* installation: warn about wrong admin account name/id and password
* fixed last menu closing in tibiacom template
* updated polish locale (translation) on install
* (internal) removed some duplicated code on install finish
* (internal) renamed installation step files to be in correct order
* added TODO file
## [0.7.1 - 13.12.2017]
* added changelog menu item to kathrine template
* fixed some php short tag in changelogs page
* fixed guild change description back button
* removed duplicated "Support List" menu item from tibiacom template
* changed some notice when version check is failed
* (internal) moved changelog to twig
## [0.7.0 - 20.11.2017]
* moved template menus to database, they're now dynamically loaded
* added anonymous usage statistics reporting (only if user agrees, first usage report will be send after 7 days)
* you can edit them in Admin Panel under 'Menus' option
* you can also add custom links, like http://google.pl
* added networks (facebook and twitter) and highscores (top 5) boxes to tibiacom template, configurable in templates/tibiacom/config.php
* added news ticker for kathrine template
* added featured article to tibiacom template (you can add them with add news button)
* added tinymce editor to 'Pages' in admin panel
* added links to edit/delete/hide custom page directly from page
* update forum post after editing news (when forum post has been created)
* enabled code plugin for tinymce which enabled raw html code editing
* removed videos pages, as it can be easily added using custom Menus and Pages with insert Media
* removed bug_report configurable, its now enabled by default
* log some error info when mail cannot be send on account create
* twig getLink function will now return with full url (BASE_URL included)
* verify install post values directly on config page and display error
* updated tinymce to version 4.7.2 (from 4.7.0)
* updated phpmailer to version 5.2.26 (from 5.2.23)
* (#30) (fix) recovering account on servers that doesn't support salts
* (fix) account email confirm function
* (fix) showing changelog with urls in Admin Panel
* (fix) uninstalling plugin
* (fix) polls box in tibiacom template
* (fix) remove hooks from db on plugin deinstall
* (fix) some weird include possibilities with forum and account actions (verify action name)
* (fix) loading hooks from plugin installed from command line
* (fix) some changelog PHP Notice warning
* (internal) moved uninstall logic to Plugins class
* (internal) moved tibiacom boxes to separate directory
* (internal) moved news tickers to twig template
* (internal) moved Forum class to separate file
* (internal) moved deprecated functions to compat.php
* (internal) added some compat functions that are used by shop system
* (internal) renamed constant TICKET -> TICKER
* (internal) shortened message functions
## [0.6.6 - 22.10.2017]
* fixed some php fatal error on spells page
* changed spells.vocations field in db size to 300
* please reload your spells after this update!
## [0.6.5 - 21.10.2017]
* fixed displaying custom pages
* fixed adding new group forum board
## [0.6.4 - 20.10.2017]
* reverted OTS_Account::getLastLogin() cause its used by tibia11-login plugin
## [0.6.3 - 20.10.2017]
* fixed creating account
* fixed viewing thread without being logged
* fixed showing premium account status
## [0.6.2 - 20.10.2017]
* added forums for guilds and groups
* added nice looking menu for my account page in default template
* new command line tool: install_plugin.php - can be used to install plugins from command line. Usage: "php install_plugin.php path_to_file"
* added new tooltip to view characters equipment item name and monster loot
* added items.xml loader class and weapons.xml loader class
* minimum PHP version to install AAC is now 5.3.0 cause of Anonymous functions used by Twig
* Added 'Are you sure?' popup when uninstalling plugin
* added some warnings when plugin json file is incomplete
* fixed showing in characters ban expires when is unlimited
* fixed displaying monster loot when item.name in loot is used instead of item.id
* load also runes into spells table
* display plugin uninstall option only if its possible
* after changing template you will be redirected to latest viewed page
* display gallery add image form only on main gallery page
* (internal) moved most of guilds html-in-php code to twig
* (internal) moved spells page to twig template
* (internal) removed useless spells.spell column that was duplicate of spells.words
* (internal) save monster loot in database in json format instead loading it every time from xml file
* (internal) store monster voices and immunities in json format
* (internal) moved buttons to separate template
* (internal) moved online search form to twig
* (internal) added new function getItemNameById($id)
* (internal) Moved plugin install logic to a new class: Plugins
* (internal) changed spells.vocations database field to store json data instead of comma separated
* (internal) removed $hook_types array, using defined() and constant() functions now
* (internal) removed useless monsters.gfx_name field from database
* (internal) renamed database field monsters.hide_creature to hidden
* (internal) renamed existing Items class to Items_Images
* (internal) optimized Spells class
* (internal) new function: OTS_Guild::hasMember(OTS_Player $player)
* (internal) new function: Forum::hasAccess($board_id)
## [0.6.1 - 17.10.2017]
* fixed signatures loading
* new configurable: session_prefix, to allow more websites on one machine (must be unique for every website on your dedicated server!)
* better error handling for monsters and spells loader (save errors to system/logs/error.log)
* check if file exist before loading (monsters and spells)
* (internal) Account::getAccess() = Account::getGroupId()
* (internal) moved account actions (pages) to account/ directory
* (internal) moved forum actions (pages) to forum/ directory
* (internal) moved forum.edit_post to twig templates
## [0.6.0 - 16.10.2017]
* added faq management - add/edit/move/hide/delete from website
* new account.login view for tibiacom template
* monsters and spells are now being loaded at the installation of the AAC
* fix for php versions under 5.5 where empty() function supported only variables
* added missing change email and change info buttons to account.management default template
* added new indicator icons for create account, create character and change character name
* fixed config loader when some inline comments are present
* fixed editing page in admin panel that contains some html code
* fixed forum new post on mac os and some specific mysql versions
* attempt to fix incorrect views counter behavior (its resetting to 0 in some cases)
* enabled cache http headers for signatures
* check if monster file exist before loading it
* fixed if plugin zip file name contains dot (.)
* renamed screenshots to gallery and movies to videos
* moved install pages to twig
* fixed Account::getGuildAccess function
* removed never used library from sources - dwoo
* moved check_* functions to class Validator
* from now all validators ajax requests will fire onblur instead of onkeyup
* ajax requests returns now json instead of xml
* added 404 response when file is not found
## [0.5.1 - 11.10.2017]
* fixed forum add/edit board
* new configurable: highscores_length, how much highscores to display
* fixed highscores links (ALL, previous and next page)
* update templates cache when installing/uninstalling plugin
* moved character deaths and frags table generation to twig
* fixed some bug when you uninstall plugin and then try to install again on the same page
* check if plugin exist before uninstalling
* fixed some warning in OTS_Base_DB
## [0.5.0 - 10.10.2017]
* moved .htaccess rules to plain php (index.php)
* updated tinymce to the latest (4.7.0) version, you can now embed code, for example youtube videos
* added option to uninstall plugin
* added option to require specified myaac, php or database version for plugins, without that plugin won't be installed
* change accountmanagement links to use friendly_urls
* fixed creating new forum thread
* sample characters are now assigned to admin account and have group_id 4 to not be shown on highscores
* added links loaded from database to admin panel - for future plugins
* print some info to error.log when can't find config.lua
* some fixes in account changecomment action
* show info when account name/number or password is empty on login
* fixed showing account login errors
* added few characters hooks
* fixed some kathrine template js bug when shop is disabled
* you can now use slash '/' in custom pages loaded from database
* added new twig function getLink that convert link taking into account config.friendly_urls
* internalLayoutLink -> getLink
## [0.4.3 - 05.10.2017]
* better config loader taken from latest gesior, you can now include files in your config by doing dofile('config.local.lua')
* fixed country detection in create account
* fixed showing of character deaths and frags
* fixed https://otland.net/threads/myaac-v0-0-1.251454/page-13#post-2466303
* fixed https://otland.net/threads/myaac-v0-0-1.251454/page-13#post-2466313
* fixed rook sample, which will now have level 1, 150 health, 0 mana, and 400 cap.
* fixed samples being deleted by tfs 1.0+ cause of 'deletion' field set to 1
* pages loaded from database have higher priority than normal .php pages, so they will be loaded first if they exist
* moved many pages to twig templates
* change download client links from clients.halfaway.net to tibia-clients.com
* added bugtracker to kathrine template
* added CREDITS file
## [0.4.2 - 14.09.2017]
* updated version number
## [0.4.1 - 13.09.2017]
* fixed log in to admin panel
* fixed File is not .zip plugin upload error
## [0.4.0 - 13.09.2017
* added option to add/edit/delete/hide/move forum boards
* moved some of HTML-in-PHP code to Twig templates
* added bug_report configurable which can enable/disable bug tracker
* log errors instead of showing them to users with system directories
* fix when $_SERVER['HTTP_ACCEPT_ENCODING'] is not set
* when it fails to load config.lua it will output error also to error.log
* automatically detect json file in .zip instead of basing on filename (admin panel - plugins)
* hopefully fixed the error with "The file you are trying to upload is not a .zip file. Please try again."
* fixed wrong name of table in bugtracker
* fixed some bugs in bugtracker
* added report bug link in templates
* fixed some rare error when user is logged in for longer than 15 minutes and tries to login again
* fixed some grammar errors
* some small improvements
* fixed some separators in kathrine template
## [0.3.0 - 28.08.2017]
* added administration panel for screenshots management with auto thumbnail generator and image auto-resizing
* added Twig template engine and moved some html-in-php code to it
* automatically detect player country based on user location (IP) on create account
* player sex (gender) is now configurable at $config['genders']
* fixed recovering account and changing password when salt is enabled
* fixed installing samples when for example Rook Sample already exist and other samples not
* fixed some mysql error when character you trying to create already exist
* fixed some warning when you select nonexistent country
* password change minimal/maximal length notice is now more precise
* added 'enabled' field in myaac_hooks table, which can enable or disable specified hook
* removed DEFAULT '' for TEXT field. It didn't worked under some systems like MAC OS X.
* minimum PHP version to install the MyAAC is now 5.2.0 cause of pathinfo (extension) function
* removed unused admin stylish template
* removed some unused cities field from myaac_spells table
* moved news adding at installation from schema.sql to finish.php
* some optimizations
## [0.2.4 - 09.06.2017]
* fixed invite to guild
* added id field on monsters, so you can delete them in phpmyadmin
* fixed adding some creatures with ' and "
* fixed when there are spaces at beginning of the file (creatures)
* fixed when file is unable to parse (creatures)
* fixed typo loss_items => loss_containers
* more elegant way of showing message on reload creatures and spells
## [0.2.3 - 31.05.2017]
* fixed guild management on OTHire 0.0.3
* set default skills to 10 when creating new character
* fixed displaying of "Create forum thread" in newses
* fixed deleting guild on servers that use players.rank_id field
* fixed phpmailer class loading (https://otland.net/threads/myaac-v0-0-1.251454/page-8#post-2445222)
* fixed displaying vocation amount on online page
* better support for custom vocations, you just need to set in config vocations_amount to yours.
* fixed huge space in player name (https://otland.net/threads/myaac-v0-0-1.251454/page-7#post-2444328)
* fixed Undefined variable (https://otland.net/threads/myaac-v0-0-1.251454/page-7#post-2444034)
* fixed Undefined offset (https://otland.net/threads/myaac-v0-0-1.251454/page-7#post-2444035)
## [0.2.2 - 22.05.2017]
* added missing cache/signature directory
* fixed https://otland.net/threads/myaac-v0-0-1.251454/page-7#post-2443868
## [0.2.1 - 21.05.2017]
* added Swedish translation by Sizaro
* fixed some bugs with installlation & characters & houses
## [0.2.0 - 21.05.2017]
* added option to change character sex for premium points
* moved site_closed to database, now you can close your site through admin panel
* added option to admin panel: clear cache
* added experiencetable_rows configurable
* optimized OTS_Account->getGroupId(), now its using like 20 queries less
* optimized OTS_Player->load($id) function, should be much faster now
* fixed displaying on highscores special outfits
* fixed skull images displaying
* fixed displaying unlimited premium account
* fixed bug where players.lookaddons doesn't exist (OTHire etc.) (https://otland.net/threads/myaac-v0-0-1.251454/page-6#post-2442407)
* fixed signature tibian for OTHire and other servers that doesnt use accounts.premdays field
* fixed when player name in signature containst space
* don't show "Create forum thread" when editing
* fixed red color table after create account
* updated download links, as clients.halfaway.net isn't working anymore
* fixed some bugs while installing when field `email_next` or `hidden` already exist
* fixed movies unexpected comment
* added template_place_holder('center_top') to kathrine template
## [0.1.5 - 13.05.2017]
* fixed bug with "Integrity constraint violation: 1048 Column 'ip' cannot be null"
## [0.1.4 - 13.05.2017]
* added outfit shower, in characters, online, and highscores
* updated database to version 2
* fixed item images (now using item-images.ots.me host by default)
* fixed news ticket and posting long newses (https://otland.net/threads/myaac-v0-0-1.251454/page-5#post-2442026)
* news body limit increased to 65535 (mysql text field)
* removed some unused code from my old server
* added spells & monsters to kathrine template
## [0.1.3 - 11.05.2017]
* this is just release to update version number
## [0.1.2 - 11.05.2017]
* forgot to update CHANGELOG and MYAAC_VERSION
## [0.1.1 - 11.05.2017]
* fixed updating myaac_config with database_version to 1
* fixed database updater
## [0.1.0 - 11.05.2017]
* added new feature: change character name for premium points (disabled by default, you can enable it in config under account_change_character_name in config.php)
* added automatic database updater (data migrations)
* renamed events to hooks
* moved hooks to database
* now you can use hooks in plugins
* set account.type field to 5 on install, if TFS 1.0+
* added example plugin
* new, latest google analytics code
* fixed bug with loading account.name that has numbers in it
* fixed many bugs in player editor in admin panel
* added error handling to plugin manager and some more verification in
* file has been correctly unpacked/uploaded
* fixed Statistics page in admin panel when using account.number
* fixed bug when creating/recovering account on servers with
* account.salt field (TFS 0.3 for example)
* fixed forum showing thread with html tags (added from news manager)
* new, latest code for youtube videos in movies page
* fixed showing vocation images when using $config['online_vocations_images']
* many fixes in polls (also importing proper schema)
* fixed hovering on buttons in kathrine template (on accountmanagement page)
* fixed signatures (many fixes)
* added missing gesior signature system
## [0.0.6 - 06.05.2017]
* fixed bug while installing (https://otland.net/threads/myaac-v0-0-1.251454/page-3#post-2440543)
* fixed bug when creating character (not showing errors) (one more time)
* fixed support for TFS 0.2 series
* added FAQ link
## [0.0.5 - 05.05.2017]
* fixed bug when creating character (not showing errors)
* Fixed characters loading with names that has been created with other AAC
* fixed links to shop in default template
* fixed some weird PHP 7.1 warnings/notices
* Fixed config loading with some weird comments
* fixed bug with status info utf8 encoding (https://otland.net/threads/myaac-v0-0-1.251454/page-2#post-2440259)
* fixed when ip in log_action is NULL (https://otland.net/threads/myaac-v0-0-1.251454/page-2#post-2440357)
* fixed bug when guild doesn't exist on characters page (https://otland.net/threads/myaac-v0-0-1.251454/page-2#post-2440320)
* disabled friendly_urls by default
* fixes when $config['database_*'] is set
* added CHANGELOG
## [0.0.3 - 03.05.2017]
* Full support for OTHire 0.0.3
* added support for otservers that doesn't use account.name field, instead just account number will be used
* fixed encryption detection on TFS 0.3
* fixed bug when server_config table doesn't exist
* (install) moved admin account creation to new step
* fixed news comment link
* by default, the installer creates now the Admin player, for admin account
* fixed installation errors
* fixed config.lua loading with some weird comments
## [0.0.2 - 02.05.2017]
* updated forum links to use friendly_urls
* some more info will be shown when cannot connect to database
* show more error infos when creating character
* fixed forum link on newses
* fixed spells loading when there's vocation name instead of id
* fixed bug when you have changed template but it doesn't exist anymore
* fixed vocations with promotion loading
* fixed support for gesior pages and templates
* added function OTS_Acount:getGroupId()
## [0.0.1 - 01.05.2017]
This is first official release of MyAAC.
Features are listed here
For more information, see the release announcement on OTLand: https://otland.net/threads/myaac-v0-0-1.251454/

View File

@@ -1,14 +0,0 @@
# automatically exported using this script:
# git log --all --format='%cN <%cE>' | sort -u > contributors
# in no particular order
# cleaned for readability
Evil Puncker <EPuncker@users.noreply.github.com>
Fernando Matos <fernando@pixele.com.br>
Lee <42119604+Leesneaks@users.noreply.github.com>
caio <caio.zucoli@gmail.com>
slawkens <slawkens@gmail.com>
tobi132 <52947952+tobi132@users.noreply.github.com>
vankk <nwtr.otland@hotmail.com>
whiteblXK <krzys16001@gmail.com>
xitobuh <jonas.hockert92@gmail.com>

View File

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

View File

@@ -1,4 +1,4 @@
# [MyAAC](https://my-aac.org)
# MyAAC
[![Build Status Master](https://img.shields.io/travis/slawkens/myaac/master)](https://travis-ci.org/github/slawkens/myaac)
[![License: GPL-3.0](https://img.shields.io/github/license/slawkens/myaac)](https://opensource.org/licenses/gpl-license)
@@ -11,7 +11,7 @@ MyAAC is a free and open-source Automatic Account Creator (AAC) written in PHP.
Official website: https://my-aac.org
### Requirements
### REQUIREMENTS
- PHP 5.6 or later
- MySQL database
@@ -20,7 +20,7 @@ Official website: https://my-aac.org
- ZIP PHP Extension
- (optional) mod_rewrite to use friendly_urls
### Installation
### INSTALLATION AND CONFIGURATION
Just decompress and untar the source (which you should have done by now,
if you're reading this), into your webserver's document root.
@@ -40,40 +40,15 @@ Official website: https://my-aac.org
Visit http://your_domain/install (http://localhost/install) and follow instructions in the browser.
### Configuration
### KNOWN PROBLEMS
Check *config.php* to get more informations.
Use *config.local.php* for your local configuration changes.
- none -
### Branches
This repository follows the Git Flow Workflow.
Cheatsheet: [Git-Flow-Cheetsheet](https://danielkummer.github.io/git-flow-cheatsheet)
That means, we use:
* master branch, for current stable release
* develop branch, for development version (next release)
* feature branches, for features etc.
### Known Problems
- Some compatibility issues with some exotical distibutions.
### Contributing
Contributions are more than welcome.
Pull requests should be made to the *develop* branch as that is the working branch, master is for release code.
Bug fixes to current release should be done to master branch.
Look: [Contributing](https://github.com/otsoft/myaac/wiki/Contributing) in our wiki.
### Other Notes
### OTHER NOTES
If you have a great idea or want contribute to the project - visit our website at https://www.my-aac.org
### License
### LICENSING
This program and all associated files are released under the GNU Public License.
See [LICENSE](https://github.com/slawkens/myaac/blob/master/LICENSE) for details.
This program and all associated files are released under the GNU Public
License, see LICENSE for details.

1
VERSION Normal file
View File

@@ -0,0 +1 @@
0.8.6

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.3 KiB

View File

@@ -2,9 +2,6 @@
// few things we'll need
require '../common.php';
define('ADMIN_PANEL', true);
define('MYAAC_ADMIN', true);
if(file_exists(BASE . 'config.local.php')) {
require_once BASE . 'config.local.php';
}
@@ -15,6 +12,8 @@ if(file_exists(BASE . 'install') && (!isset($config['installed']) || !$config['i
throw new RuntimeException('Setup detected that <b>install/</b> directory exists. Please visit <a href="' . BASE_URL . 'install">this</a> url to start MyAAC Installation.<br/>Delete <b>install/</b> directory if you already installed MyAAC.<br/>Remember to REFRESH this page when you\'re done!');
}
define('ADMIN_PANEL', true);
$content = '';
// validate page
@@ -53,7 +52,7 @@ if(!$logged || !admin()) {
}
// include our page
$file = SYSTEM . 'pages/admin/' . $page . '.php';
$file = ADMIN . 'pages/' . $page . '.php';
if(!@file_exists($file)) {
$page = '404';
$file = SYSTEM . 'pages/404.php';

484
admin/pages/accounts.php Normal file
View File

@@ -0,0 +1,484 @@
<?php
/**
* Account editor
*
* @package MyAAC
* @author Lee
* @copyright 2019 MyAAC
* @link https://my-aac.org
*/
defined('MYAAC') or die('Direct access not allowed!');
$title = 'Account editor';
$base = BASE_URL . 'admin/?p=accounts';
if ($config['account_country'])
require SYSTEM . 'countries.conf.php';
function echo_success($message)
{
echo '<p class="success">' . $message . '</p>';
}
function echo_error($message)
{
global $error;
echo '<p class="error">' . $message . '</p>';
$error = true;
}
function verify_number($number, $name, $max_length)
{
if (!Validator::number($number))
echo_error($name . ' can contain only numbers.');
$number_length = strlen($number);
if ($number_length <= 0 || $number_length > $max_length)
echo_error($name . ' cannot be longer than ' . $max_length . ' digits.');
}
$hasSecretColumn = $db->hasColumn('accounts', 'secret');
$hasCoinsColumn = $db->hasColumn('accounts', 'coins');
$hasPointsColumn = $db->hasColumn('accounts', 'premium_points');
$hasTypeColumn = $db->hasColumn('accounts', 'type');
$hasGroupColumn = $db->hasColumn('accounts', 'group_id');
if ($config['account_country']) {
$countries = array();
foreach (array('pl', 'se', 'br', 'us', 'gb') as $c)
$countries[$c] = $config['countries'][$c];
$countries['--'] = '----------';
foreach ($config['countries'] as $code => $c)
$countries[$code] = $c;
}
?>
<link rel="stylesheet" type="text/css" href="<?php echo BASE_URL; ?>tools/css/jquery.datetimepicker.css"/ >
<script src="<?php echo BASE_URL; ?>tools/js/jquery.datetimepicker.js"></script>
<?php
$id = 0;
if (isset($_REQUEST['id']))
$id = (int)$_REQUEST['id'];
else if (isset($_REQUEST['search_name'])) {
if (strlen($_REQUEST['search_name']) < 3 && !Validator::number($_REQUEST['search_name'])) {
echo 'Player name is too short.';
} else {
if (Validator::number($_REQUEST['search_name']))
$id = $_REQUEST['search_name'];
else {
$query = $db->query('SELECT `id` FROM `accounts` WHERE `name` = ' . $db->quote($_REQUEST['search_name']));
if ($query->rowCount() == 1) {
$query = $query->fetch();
$id = $query['id'];
} else {
$query = $db->query('SELECT `id`, `name` FROM `accounts` WHERE `name` LIKE ' . $db->quote('%' . $_REQUEST['search_name'] . '%'));
if ($query->rowCount() > 0 && $query->rowCount() <= 10) {
echo 'Do you mean?<ul>';
foreach ($query as $row)
echo '<li><a href="' . $base . '&id=' . $row['id'] . '">' . $row['name'] . '</a></li>';
echo '</ul>';
} else if ($query->rowCount() > 10)
echo 'Specified name resulted with too many accounts.';
}
}
}
}
$groups = new OTS_Groups_List();
if ($id > 0) {
$account = new OTS_Account();
$account->load($id);
if (isset($account, $_POST['save']) && $account->isLoaded()) {// we want to save
$error = false;
$_error = '';
$account_db = new OTS_Account();
if(USE_ACCOUNT_NAME) {
$name = $_POST['name'];
$account_db->find($name);
if ($account_db->isLoaded() && $account->getName() != $name)
echo_error('This name is already used. Please choose another name!');
}
$account_db->load($id);
if (!$account_db->isLoaded())
echo_error('Account with this id doesn\'t exist.');
//type/group
if($hasTypeColumn || $hasGroupColumn) {
$group = $_POST['group'];
}
$password = ((!empty($_POST["pass"]) ? $_POST['pass'] : null));
if (!Validator::password($password)) {
$errors['password'] = Validator::getLastError();
}
//secret
if($hasSecretColumn) {
$secret = $_POST['secret'];
}
//key
$key = $_POST['key'];
$email = $_POST['email'];
if (!Validator::email($email))
$errors['email'] = Validator::getLastError();
//tibia coins
if ($hasCoinsColumn) {
$t_coins = $_POST['t_coins'];
verify_number($t_coins, 'Tibia coins', 12);
}
// prem days
$p_days = (int)$_POST['p_days'];
verify_number($p_days, 'Prem days', 11);
//prem points
$p_points = $_POST['p_points'];
verify_number($p_points, 'Prem Points', 11);
//rl name
$rl_name = $_POST['rl_name'];
//location
$rl_loca = $_POST['rl_loca'];
//country
$rl_country = $_POST['rl_country'];
$web_flags = $_POST['web_flags'];
verify_number($web_flags, 'Web Flags', 1);
//created
$created = $_POST['created'];
verify_number($created, 'Created', 11);
//web last login
$web_lastlogin = $_POST['web_lastlogin'];
verify_number($web_lastlogin, 'Web Last logout', 11);
if (!$error) {
if(USE_ACCOUNT_NAME) {
$account->setName($name);
}
if ($hasTypeColumn) {
$account->setCustomField('type', $group);
} elseif ($hasGroupColumn) {
$account->setCustomField('group_id', $group);
}
if($hasSecretColumn) {
$account->setCustomField('secret', $secret);
}
$account->setCustomField('key', $key);
$account->setEMail($email);
if ($hasCoinsColumn) {
$account->setCustomField('coins', $t_coins);
}
$lastDay = 0;
if($p_days != 0 && $p_days != OTS_Account::GRATIS_PREMIUM_DAYS) {
$lastDay = time();
} else if ($lastDay != 0) {
$lastDay = 0;
}
$account->setPremDays($p_days);
$account->setLastLogin($lastDay);
if ($hasPointsColumn) {
$account->setCustomField('premium_points', $p_points);
}
$account->setRLName($rl_name);
$account->setLocation($rl_loca);
$account->setCountry($rl_country);
$account->setCustomField('created', $created);
$account->setWebFlags($web_flags);
$account->setCustomField('web_lastlogin', $web_lastlogin);
if (isset($password)) {
$config_salt_enabled = $db->hasColumn('accounts', 'salt');
if ($config_salt_enabled) {
$salt = generateRandomString(10, false, true, true);
$password = $salt . $password;
$account_logged->setCustomField('salt', $salt);
}
$password = encrypt($password);
$account->setPassword($password);
if ($config_salt_enabled)
$account->setCustomField('salt', $salt);
}
$account->save();
echo_success('Account saved at: ' . date('G:i'));
}
}
}
$search_account = '';
if (isset($_REQUEST['search_name']))
$search_account = $_REQUEST['search_name'];
else if (isset($_REQUEST['search_account']))
$search_account = $_REQUEST['search_account'];
else if ($id > 0 && isset($account) && $account->isLoaded()) {
if(USE_ACCOUNT_NAME) {
$search_account = $account->getName();
}
else {
$search_account = $account->getId();
}
}
?>
<div class="row">
<?php if (isset($account) && $account->isLoaded()) { ?>
<form action="<?php echo $base . ((isset($id) && $id > 0) ? '&id=' . $id : ''); ?>" method="post"
class="form-horizontal">
<div class="col-md-8">
<div class="box box-primary">
<div class="box-body">
<div class="row">
<?php if(USE_ACCOUNT_NAME): ?>
<div class="col-xs-4">
<label for="name" class="control-label">Account Name:</label>
<input type="text" class="form-control" id="name" name="name"
autocomplete="off" style="cursor: auto;"
value="<?php echo $account->getName(); ?>"/>
</div>
<?php endif; ?>
<div class="col-xs-5">
<label for="c_pass" class="control-label">Password: (check to change)</label>
<div class="input-group">
<span class="input-group-addon">
<input type="checkbox"
name="c_pass"
id="c_pass"
value="false"
class="input_control"/>
</span>
<input type="text" class="form-control" id="pass" name="pass"
autocomplete="off" maxlength="20"
value=""/>
</div>
</div>
<div class="col-xs-3">
<label for="account_id" class="control-label">Account ID:</label>
<input type="text" class="form-control" id="account_id" name="account_id"
autocomplete="off" style="cursor: auto;" size="8" maxlength="11" disabled
value="<?php echo $account->getId(); ?>"/>
</div>
</div>
<div class="row">
<?php
$acc_group = $account->getAccGroupId();
if ($hasTypeColumn) {
$acc_type = array("Normal", "Tutor", "Senior Tutor", "Gamemaster", "God"); ?>
<div class="col-xs-6">
<label for="group" class="control-label">Account Type:</label>
<select name="group" id="group" class="form-control">
<?php foreach ($acc_type as $id => $a_type): ?>
<option value="<?php echo($id + 1); ?>" <?php echo($acc_group == ($id + 1) ? 'selected' : ''); ?>><?php echo $a_type; ?></option>
<?php endforeach; ?>
</select>
</div>
<?php
} elseif ($hasGroupColumn) {
?>
<div class="col-xs-6">
<label for="group" class="control-label">Account Type:</label>
<select name="group" id="group" class="form-control">
<?php
foreach ($groups->getGroups() as $id => $group): ?>
<option value="<?php echo $id; ?>" <?php echo($acc_group == $id ? 'selected' : ''); ?>><?php echo $group->getName(); ?></option>
<?php endforeach; ?>
</select>
</div>
<?php } ?>
<div class="col-xs-6">
<label for="web_flags" class="control-label">Website Access:</label>
<select name="web_flags" id="web_flags" class="form-control">
<?php $web_acc = array("None", "Admin", "Super Admin", "(Admin + Super Admin)");
foreach ($web_acc as $id => $a_type): ?>
<option value="<?php echo($id); ?>" <?php echo($account->getWebFlags() == ($id) ? 'selected' : ''); ?>><?php echo $a_type; ?></option>
<?php endforeach; ?>
</select>
</div>
</div>
<div class="row">
<?php if($hasSecretColumn): ?>
<div class="col-xs-6">
<label for="secret" class="control-label">Secret:</label>
<input type="text" class="form-control" id="secret" name="secret"
autocomplete="off" style="cursor: auto;" size="8" maxlength="11"
value="<?php echo $account->getCustomField('secret'); ?>"/>
</div>
<?php endif; ?>
<div class="col-xs-6">
<label for="key" class="control-label">Key:</label>
<input type="text" class="form-control" id="key" name="key"
autocomplete="off" style="cursor: auto;" size="8" maxlength="11"
value="<?php echo $account->getCustomField('key'); ?>"/>
</div>
</div>
<div class="row">
<div class="col-xs-6">
<label for="email" class="control-label">Email:</label>
<input type="text" class="form-control" id="email" name="email"
autocomplete="off" maxlength="20"
value="<?php echo $account->getEMail(); ?>"/>
</div>
<?php if ($hasCoinsColumn): ?>
<div class="col-xs-6">
<label for="t_coins" class="control-label">Tibia Coins:</label>
<input type="text" class="form-control" id="t_coins" name="t_coins"
autocomplete="off" maxlength="8"
value="<?php echo $account->getCustomField('coins') ?>"/>
</div>
<?php endif; ?>
<div class="col-xs-6">
<label for="p_days" class="control-label">Premium Days:</label>
<input type="text" class="form-control" id="p_days" name="p_days"
autocomplete="off" maxlength="11"
value="<?php echo $account->getPremDays(); ?>"/>
</div>
<?php if ($hasPointsColumn): ?>
<div class="col-xs-6">
<label for="p_points" class="control-label">Premium Points:</label>
<input type="text" class="form-control" id="p_points" name="p_points"
autocomplete="off" maxlength="8"
value="<?php echo $account->getCustomField('premium_points') ?>"/>
</div>
<?php endif; ?>
</div>
<div class="row">
<div class="col-xs-4">
<label for="rl_name" class="control-label">RL Name:</label>
<input type="text" class="form-control" id="rl_name" name="rl_name"
autocomplete="off" maxlength="20"
value="<?php echo $account->getRLName(); ?>"/>
</div>
<div class="col-xs-4">
<label for="rl_loca" class="control-label">Location:</label>
<input type="text" class="form-control" id="rl_loca" name="rl_loca"
autocomplete="off" maxlength="20"
value="<?php echo $account->getLocation(); ?>"/>
</div>
<div class="col-xs-4">
<label for="rl_country" class="control-label">Country:</label>
<select name="rl_country" id="rl_country" class="form-control">
<?php foreach ($countries as $id => $a_type): ?>
<option value="<?php echo($id); ?>" <?php echo($account->getCountry() == ($id) ? 'selected' : ''); ?>><?php echo $a_type; ?></option>
<?php endforeach; ?>
</select>
</div>
</div>
<div class="row">
<div class="col-xs-4">
<label for="created" class="control-label">Created:</label>
<input type="text" class="form-control" id="created" name="created"
autocomplete="off" maxlength="20"
value="<?php echo $account->getCustomField('created'); ?>"/>
</div>
<div class="col-xs-4">
<label for="web_lastlogin" class="control-label">Web Last Login:</label>
<input type="text" class="form-control" id="web_lastlogin" name="web_lastlogin"
autocomplete="off" maxlength="20"
value="<?php echo $account->getCustomField('web_lastlogin'); ?>"/>
</div>
</div>
<input type="hidden" name="save" value="yes"/>
<div class="box-footer">
<a href="<?php echo ADMIN_URL; ?>?p=accounts"><span class="btn btn-danger">Cancel</span></a>
<div class="pull-right">
<input type="submit" class="btn btn-primary" value="Update">
</div>
</div>
</div>
</div>
</form>
</div>
<?php } ?>
<div class="col-md-4">
<div class="box box-primary">
<div class="box-header with-border">
<h3 class="box-title">Search Account:</h3>
<div class="box-tools pull-right">
<button type="button" class="btn btn-box-tool" data-widget="collapse"><i class="fa fa-minus"></i>
</button>
</div>
</div>
<div class="box-body">
<form action="<?php echo $base; ?>" method="post">
<div class="input-group input-group-sm">
<input type="text" class="form-control" name="search_name" value="<?php echo $search_account; ?>"
maxlength="32" size="32">
<span class="input-group-btn">
<button type="submit" type="button" class="btn btn-info btn-flat">Search</button>
</span>
</div>
</form>
</div>
</div>
<?php
if (isset($account) && $account->isLoaded()) {
$account_players = array();
$query = $db->query('SELECT `name`,`level`,`vocation` FROM `players` WHERE `account_id` = ' . $account->getId() . ' ORDER BY `name`')->fetchAll();
if (isset($query)) {
?>
<div class="box">
<div class="box-header">
<h3 class="box-title">Character List:</h3>
</div>
<div class="box-body no-padding">
<table class="table table-striped">
<tbody>
<tr>
<th style="width: 10px">#</th>
<th>Name</th>
<th>Level</th>
<th style="width: 40px">Edit</th>
</tr>
<?php
$i = 1;
foreach ($query as $p) {
$account_players[] = $p;
echo '<tr>
<td>' . $i . '.</td>
<td>' . $p['name'] . '</td>
<td>' . $p['level'] . '</td>
<td><a href="?p=players&search_name=' . $p['name'] . '"><span class="btn btn-success btn-sm edit btn-flat"><i class="fa fa-edit"></i></span></a></span></td>
</tr>';
$i++;
} ?>
</tbody>
</table>
</div>
</div>
<?php
};
};
?>
</div>
<script type="text/javascript">
$('#lastlogout').datetimepicker({format: 'unixtime'});
$('#created').datetimepicker({format: 'unixtime'});
$('#web_lastlogin').datetimepicker({format: 'unixtime'});
$(document).ready(function () {
$('.input_control').change(function () {
$('input[name=pass]')[0].disabled = !this.checked;
$('input[name=pass]')[0].value = '';
}).change();
});
</script>

View File

@@ -4,8 +4,7 @@
*
* @package MyAAC
* @author Slawkens <slawkens@gmail.com>
* @author Lee
* @copyright 2020 MyAAC
* @copyright 2019 MyAAC
* @link https://my-aac.org
*/
defined('MYAAC') or die('Direct access not allowed!');
@@ -16,6 +15,8 @@ if (!file_exists(BASE . 'CHANGELOG.md')) {
return;
}
require LIBS . 'Parsedown.php';
$changelog = file_get_contents(BASE . 'CHANGELOG.md');
$Parsedown = new Parsedown();

View File

@@ -19,10 +19,8 @@ if (isset($_GET['clear_cache'])) {
}
if (isset($_GET['maintenance'])) {
$message = (!empty($_POST['message']) ? $_POST['message'] : null);
$_status = (isset($_POST['status']) && $_POST['status'] == 'true');
$_status = ($_status ? '0' : '1');
$_status = (int)$_POST['status'];
$message = $_POST['message'];
if (empty($message)) {
error('Message cannot be empty.');
} else if (strlen($message) > 255) {
@@ -47,14 +45,42 @@ $tmp = '';
if (fetchDatabaseConfig('site_closed_message', $tmp))
$closed_message = $tmp;
$query = $db->query('SELECT count(*) as `how_much` FROM `accounts`;');
$query = $query->fetch();
$total_accounts = $query['how_much'];
$query = $db->query('SELECT count(*) as `how_much` FROM `players`;');
$query = $query->fetch();
$total_players = $query['how_much'];
$query = $db->query('SELECT count(*) as `how_much` FROM `guilds`;');
$query = $query->fetch();
$total_guilds = $query['how_much'];
$query = $db->query('SELECT count(*) as `how_much` FROM `houses`;');
$query = $query->fetch();
$total_houses = $query['how_much'];
$twig->display('admin.statistics.html.twig', array(
'total_accounts' => $total_accounts,
'total_players' => $total_players,
'total_guilds' => $total_guilds,
'total_houses' => $total_houses
));
$twig->display('admin.dashboard.html.twig', array(
'is_closed' => $is_closed,
'closed_message' => $closed_message,
'status' => $status,
'account_type' => USE_ACCOUNT_NAME ? 'name' : 'number'
));
echo '<div class="row">';
$twig->display('admin.dashboard.html.twig', array());
echo '</div>';
$configAdminPanelModules = config('admin_panel_modules');
if (isset($configAdminPanelModules)) {
echo '<div class="row">';
if(isset($configAdminPanelModules))
$configAdminPanelModules = explode(',', $configAdminPanelModules);
$twig_loader->prependPath(__DIR__ . '/modules/templates');
foreach($configAdminPanelModules as $box) {
$file = __DIR__ . '/modules/' . $box . '.php';
@@ -63,4 +89,3 @@ if (isset($configAdminPanelModules)) {
}
}
echo '</div>';
}

35
admin/pages/items.php Normal file
View File

@@ -0,0 +1,35 @@
<?php
/**
* Load items.xml
*
* @package MyAAC
* @author Slawkens <slawkens@gmail.com>
* @copyright 2019 MyAAC
* @link https://my-aac.org
*/
defined('MYAAC') or die('Direct access not allowed!');
$title = 'Load items.xml';
require LIBS . 'items.php';
require LIBS . 'weapons.php';
$twig->display('admin.items.html.twig');
$reload = isset($_REQUEST['reload']) && (int)$_REQUEST['reload'] === 1;
if ($reload) {
$items_start_time = microtime(true);
if (Items::loadFromXML(true)) {
success('Successfully loaded items (in ' . round(microtime(true) - $items_start_time, 4) . ' seconds).');
}
else {
error(Items::getError());
}
$weapons_start_time = microtime(true);
if (Weapons::loadFromXML(true)) {
success('Successfully loaded weapons (in ' . round(microtime(true) - $weapons_start_time, 4) . ' seconds).');
}
else {
error(Weapons::getError());
}
}

View File

@@ -9,10 +9,18 @@
*/
defined('MYAAC') or die('Direct access not allowed!');
$title = 'Login';
$logout = '';
if ($action == 'logout') {
$logout = "You have been logged out!";
}
if (isset($errors)) {
foreach ($errors as $error) {
error($error);
}
}
$twig->display('admin.login.html.twig', array(
'logout' => ($action == 'logout' ? 'You have been logged out!' : ''),
'logout' => $logout,
'account' => USE_ACCOUNT_NAME ? 'Name' : 'Number',
'account_login_by' => getAccountLoginByLabel(),
'errors' => isset($errors)? $errors : ''
));

View File

@@ -4,7 +4,7 @@
*
* @package MyAAC
* @author Slawkens <slawkens@gmail.com>
* @copyright 2020 MyAAC
* @copyright 2019 MyAAC
* @link https://my-aac.org
*/
defined('MYAAC') or die('Direct access not allowed!');
@@ -13,7 +13,7 @@ $title = 'Logs Viewer';
$files = array();
$aac_path_logs = BASE . 'system/logs/';
foreach (scandir($aac_path_logs, SCANDIR_SORT_ASCENDING) as $f) {
if ($f[0] === '.' || is_dir($aac_path_logs . $f) || $f === 'index.html') {
if ($f[0] === '.' || is_dir($aac_path_logs . $f)) {
continue;
}
@@ -53,6 +53,7 @@ foreach ($files as &$f) {
}
unset($f);
$twig->display('admin.logs.html.twig', array('files' => $files));
define('EXIST_NONE', 0);
define('EXIST_SERVER_LOG', 1);
@@ -71,12 +72,10 @@ if (!empty($file)) {
}
if ($exist !== EXIST_NONE) {
$file_content = nl2br(file_get_contents(($exist === EXIST_SERVER_LOG ? $server_path_logs : $aac_path_logs) . $file));
$twig->display('admin.logs.view.html.twig', array('file' => $file, 'content' => $file_content));
$content = nl2br(file_get_contents(($exist === EXIST_SERVER_LOG ? $server_path_logs : $aac_path_logs) . $file));
$twig->display('admin.logs.view.html.twig', array('file' => $file, 'content' => $content));
}
} else {
echo 'Invalid file name specified.';
}
}
$twig->display('admin.logs.html.twig', array('files' => $files));

69
admin/pages/mailer.php Normal file
View File

@@ -0,0 +1,69 @@
<?php
/**
* Mailer
*
* @package MyAAC
* @author Slawkens <slawkens@gmail.com>
* @copyright 2019 MyAAC
* @link https://my-aac.org
*/
defined('MYAAC') or die('Direct access not allowed!');
$title = 'Mailer';
if (!hasFlag(FLAG_CONTENT_MAILER) && !superAdmin()) {
echo 'Access denied.';
return;
}
if (!$config['mail_enabled']) {
echo 'Mail support disabled.';
return;
}
$mail_content = isset($_POST['mail_content']) ? stripslashes($_POST['mail_content']) : NULL;
$mail_subject = isset($_POST['mail_subject']) ? stripslashes($_POST['mail_subject']) : NULL;
$preview = isset($_REQUEST['preview']);
$preview_done = false;
if ($preview) {
if (!empty($mail_content) && !empty($mail_subject)) {
$preview_done = _mail($account_logged->getCustomField('email'), $mail_subject, $mail_content);
if (!$preview_done)
error('Error while sending preview mail. More info can be found in system/logs/mailer-error.log');
}
}
$twig->display('admin.mailer.html.twig', array(
'mail_subject' => $mail_subject,
'mail_content' => $mail_content,
'preview_done' => $preview_done
));
if (empty($mail_content) || empty($mail_subject) || $preview)
return;
$success = 0;
$failed = 0;
$add = '';
if ($config['account_mail_verify']) {
note('Note: Sending only to users with verified E-Mail.');
$add = ' AND ' . $db->fieldName('email_verified') . ' = 1';
}
$query = $db->query('SELECT ' . $db->fieldName('email') . ' FROM ' . $db->tableName('accounts') . ' WHERE ' . $db->fieldName('email') . ' != ""' . $add);
foreach ($query as $email) {
if (_mail($email['email'], $mail_subject, $mail_content))
$success++;
else {
$failed++;
echo '<br />';
error('An error occorred while sending email to <b>' . $email['email'] . '</b>. For Admin: More info can be found in system/logs/mailer-error.log');
}
}
success('Mailing finished.');
success("$success emails delivered.");
warning("$failed emails failed.");

View File

@@ -46,6 +46,7 @@ if (isset($_REQUEST['template'])) {
if ($cache->enabled()) {
$cache->delete('template_menus');
}
success('Saved at ' . date('H:i'));
}
@@ -56,73 +57,70 @@ if (isset($_REQUEST['template'])) {
echo 'Cannot find template config.php file.';
return;
}
if (!isset($config['menu_categories'])) {
echo "No menu categories set in template config.php.<br/>This template doesn't support dynamic menus.";
return;
}
$title = 'Menus - ' . $template;
?>
<div align="center" class="text-center">
<p class="note">You are editing: <?= $template ?><br/><br/>
Hint: You can drag menu items.<br/>
echo 'Hint: You can drag menu items.<br/>
Hint: Add links to external sites using: <b>http://</b> or <b>https://</b> prefix.<br/>
Not all templates support blank and colorful links.
</p>
</div>
<?php
Not all templates support blank and colorful links.<br/><br/>
<div class="row">';
$menus = array();
$menus_db = $db->query('SELECT `name`, `link`, `blank`, `color`, `category`, `ordering` FROM `' . TABLE_PREFIX . 'menu` WHERE `enabled` = 1 AND `template` = ' . $db->quote($template) . ' ORDER BY `ordering` ASC;')->fetchAll();
foreach ($menus_db as $menu) {
$menus[$menu['category']][] = array('name' => $menu['name'], 'link' => $menu['link'], 'blank' => $menu['blank'], 'color' => $menu['color'], 'ordering' => $menu['ordering']);
}
$last_id = array();
?>
<form method="post" id="menus-form" action="?p=menus">
<input type="hidden" name="template" value="<?php echo $template ?>"/>
<div class="row">
<?php foreach ($config['menu_categories'] as $id => $cat): ?>
<div class="col-md-12 col-lg-6">
<div class="card card-info card-outline">
<div class="card-header">
<h5 class="m-0"><?php echo $cat['name'] ?> <i class="far fa-plus-square add-button" id="add-button-<?php echo $id ?>"></i></h5>
echo '<form method="post" id="menus-form" action="?p=menus">';
echo '<input type="hidden" name="template" value="' . $template . '"/>';
foreach ($config['menu_categories'] as $id => $cat) {
echo ' <div class="col-md-12 col-lg-6">
<div class="box box-danger">
<div class="box-header with-border">
<h3 class="box-title">' . $cat['name'] . ' <img class="add-button" id="add-button-' . $id . '" src="' . BASE_URL . 'images/plus.png" width="16" height="16"/></h3>
</div>
<div class="card-body">
<ul class="sortable" id="sortable-<?php echo $id ?>">
<?php
<div class="box-body">';
echo '<ul class="sortable" id="sortable-' . $id . '">';
if (isset($menus[$id])) {
foreach ($menus[$id] as $i => $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 $menu['name'] ?>"/>
<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"/>
<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'] ?>"/>
<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;
endforeach;
} ?>
</ul>
$i = 0;
foreach ($menus[$id] as $menu) {
echo '<li class="ui-state-default" id="list-' . $id . '-' . $i . '"><label>Name:</label><input type="text" name="menu[' . $id . '][]" value="' . $menu['name'] . '"/>
<label>Link:</label><input type="text" name="menu_link[' . $id . '][]" value="' . $menu['link'] . '"/>
<input type="hidden" name="menu_blank[' . $id . '][]" value="0" />
<label><input class="blank-checkbox" type="checkbox" ' . ($menu['blank'] == 1 ? 'checked' : '') . '/><span title="Open in New Window">Open in New Window</span></label>
<input class="color-picker" type="text" name="menu_color[' . $id . '][]" value="#' . $menu['color'] . '" />
<a class="remove-button" id="remove-button-' . $id . '-' . $i . '"><img src="' . BASE_URL . 'images/del.png"/></a></li>';
$i++;
$last_id[$id] = $i;
}
}
echo '</ul>';
echo ' </div>
</div>
</div>
</div>
<?php endforeach ?>
</div>
<div class="row pb-2">
<div class="col-md-12">
<button type="submit" class="btn btn-info"><i class="fas fa-update"></i> Save</button>
<?php
echo '<button type="button" class="btn btn-danger float-right" value="Cancel" onclick="window.location = \'' . ADMIN_URL . '?p=menus\';"><i class="fas fa-cancel"></i> Cancel</button>';
?>
</div>
</div>
</form>
<?php
';
}
echo ' </div><div class="row"><div class="col-md-6">';
echo '<input type="submit" class="btn btn-info" value="Save">';
echo '<input type="button" class="btn btn-default pull-right" value="Cancel" onclick="window.location = \'' . ADMIN_URL . '?p=menus&template=' . $template . '\';">';
echo '</div></div>';
echo '</form>';
$twig->display('admin.menus.js.html.twig', array(
'menus' => $menus,
'last_id' => $last_id
));
?>
<?php
} else {
$templates = $db->query('SELECT `template` FROM `' . TABLE_PREFIX . 'menu` GROUP BY `template`;')->fetchAll();

View File

@@ -0,0 +1,11 @@
<?php
if ($db->hasColumn('accounts', 'coins')) {
$coins = $db->query('SELECT `coins`, `' . (USE_ACCOUNT_NAME ? 'name' : 'id') . '` as `name` FROM `accounts` ORDER BY `coins` DESC LIMIT 10;');
} else {
$coins = 0;
}
$twig->display('coins.html.twig', array(
'coins' => $coins
));

View File

@@ -0,0 +1,11 @@
<?php
if ($db->hasColumn('players', 'lastlogin')) {
$players = $db->query('SELECT name, level, lastlogin FROM players ORDER BY lastlogin DESC LIMIT 10;');
} else {
$players = 0;
}
$twig->display('lastlogin.html.twig', array(
'players' => $players,
));

View File

@@ -0,0 +1,10 @@
<?php
if ($db->hasColumn('accounts', 'premium_points')) {
$points = $db->query('SELECT `premium_points`, `' . (USE_ACCOUNT_NAME ? 'name' : 'id') . '` as `name` FROM `accounts` ORDER BY `premium_points` DESC LIMIT 10;');
} else {
$points = 0;
}
$twig->display('points.html.twig', array(
'points' => $points,
));

View File

@@ -0,0 +1,29 @@
{% if coins is iterable %}
<div class="col-md-3">
<div class="box">
<div class="box-header">
<h3 class="box-title">Top 10 - Most coins</h3>
</div>
<div class="box-body no-padding">
<table class="table table-condensed">
<tbody>
<tr>
<th>#</th>
<th>Account {{ account_type }}</th>
<th>Tibia coins</th>
</tr>
{% set i = 0 %}
{% for result in coins %}
{% set i = i + 1 %}
<tr>
<td>{{ i }}</td>
<td>{{ result.name }}</td>
<td>{{ result.coins }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
{% endif %}

View File

@@ -0,0 +1,29 @@
{% if players is iterable %}
<div class="col-md-3">
<div class="box">
<div class="box-header">
<h3 class="box-title">Last 10 Logins</h3>
</div>
<div class="box-body no-padding">
<table class="table table-condensed">
<tbody>
<tr>
<th>#</th>
<th>Player</th>
<th>Login Date</th>
</tr>
{% set i = 0 %}
{% for result in players %}
{% set i = i + 1 %}
<tr>
<td>{{ i }}</td>
<td>{{ result.name }}</td>
<td>{{ result.lastlogin|date("M d Y, H:i:s") }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
{% endif %}

View File

@@ -0,0 +1,29 @@
{% if points is iterable %}
<div class="col-md-3">
<div class="box">
<div class="box-header">
<h3 class="box-title">Top 10 - Most premium points</h3>
</div>
<div class="box-body no-padding">
<table class="table table-condensed">
<tbody>
<tr>
<th>#</th>
<th>Account {{ account_type }}</th>
<th>Premium points</th>
</tr>
{% set i = 0 %}
{% for result in points %}
{% set i = i + 1 %}
<tr>
<td>{{ i }}</td>
<td>{{ result.name }}</td>
<td>{{ result.premium_points }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
{% endif %}

View File

@@ -13,7 +13,6 @@ require_once LIBS . 'forum.php';
require_once LIBS . 'news.php';
$title = 'News Panel';
$use_datatable = true;
if (!hasFlag(FLAG_CONTENT_PAGES) && !superAdmin()) {
echo 'Access denied.';

View File

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

897
admin/pages/players.php Normal file
View File

@@ -0,0 +1,897 @@
<?php
/**
* Players editor
*
* @package MyAAC
* @author Slawkens <slawkens@gmail.com>
* @copyright 2019 MyAAC
* @link https://my-aac.org
*/
defined('MYAAC') or die('Direct access not allowed!');
$title = 'Player editor';
$base = BASE_URL . 'admin/?p=players';
function echo_success($message)
{
echo '<p class="success">' . $message . '</p>';
}
function echo_error($message)
{
global $error;
echo '<p class="error">' . $message . '</p>';
$error = true;
}
function verify_number($number, $name, $max_length)
{
if (!Validator::number($number))
echo_error($name . ' can contain only numbers.');
$number_length = strlen($number);
if ($number_length <= 0 || $number_length > $max_length)
echo_error($name . ' cannot be longer than ' . $max_length . ' digits.');
}
$skills = array(
POT::SKILL_FIST => array('Fist fighting', 'fist'),
POT::SKILL_CLUB => array('Club fighting', 'club'),
POT::SKILL_SWORD => array('Sword fighting', 'sword'),
POT::SKILL_AXE => array('Axe fighting', 'axe'),
POT::SKILL_DIST => array('Distance fighting', 'dist'),
POT::SKILL_SHIELD => array('Shielding', 'shield'),
POT::SKILL_FISH => array('Fishing', 'fish')
);
$hasBlessingsColumn = $db->hasColumn('players', 'blessings');
$hasBlessingColumn = $db->hasColumn('players', 'blessings1');
$hasLookAddons = $db->hasColumn('players', 'lookaddons');
?>
<link rel="stylesheet" type="text/css" href="<?php echo BASE_URL; ?>tools/css/jquery.datetimepicker.css"/ >
<script src="<?php echo BASE_URL; ?>tools/js/jquery.datetimepicker.js"></script>
<?php
$id = 0;
if (isset($_REQUEST['id']))
$id = (int)$_REQUEST['id'];
else if (isset($_REQUEST['search_name'])) {
if (strlen($_REQUEST['search_name']) < 3 && !Validator::number($_REQUEST['search_name'])) {
echo 'Player name is too short.';
} else {
if (Validator::number($_REQUEST['search_name']))
$id = $_REQUEST['search_name'];
else {
$query = $db->query('SELECT `id` FROM `players` WHERE `name` = ' . $db->quote($_REQUEST['search_name']));
if ($query->rowCount() == 1) {
$query = $query->fetch();
$id = $query['id'];
} else {
$query = $db->query('SELECT `id`, `name` FROM `players` WHERE `name` LIKE ' . $db->quote('%' . $_REQUEST['search_name'] . '%'));
if ($query->rowCount() > 0 && $query->rowCount() <= 10) {
echo 'Do you mean?<ul>';
foreach ($query as $row)
echo '<li><a href="' . $base . '&id=' . $row['id'] . '">' . $row['name'] . '</a></li>';
echo '</ul>';
} else if ($query->rowCount() > 10)
echo 'Specified name resulted with too many players.';
}
}
}
}
$groups = new OTS_Groups_List();
if ($id > 0) {
$player = new OTS_Player();
$player->load($id);
if (isset($player) && $player->isLoaded() && isset($_POST['save'])) {// we want to save
$error = false;
if ($player->isOnline())
echo_error('This player is actually online. You can\'t edit online players.');
$name = $_POST['name'];
$_error = '';
if (!Validator::characterName($name))
echo_error(Validator::getLastError());
//if(!Validator::newCharacterName($name)
// echo_error(Validator::getLastError());
$player_db = new OTS_Player();
$player_db->find($name);
if ($player_db->isLoaded() && $player->getName() != $name)
echo_error('This name is already used. Please choose another name!');
$account_id = $_POST['account_id'];
verify_number($account_id, 'Account id', 11);
$account_db = new OTS_Account();
$account_db->load($account_id);
if (!$account_db->isLoaded())
echo_error('Account with this id doesn\'t exist.');
$group = $_POST['group'];
if ($groups->getGroup($group) == false)
echo_error('Group with this id doesn\'t exist');
$level = $_POST['level'];
verify_number($level, 'Level', 11);
$experience = $_POST['experience'];
verify_number($experience, 'Experience', 20);
$vocation = $_POST['vocation'];
verify_number($vocation, 'Vocation id', 11);
if (!isset($config['vocations'][$vocation])) {
echo_error("Vocation with this id doesn't exist.");
}
// health
$health = $_POST['health'];
verify_number($health, 'Health', 11);
$health_max = $_POST['health_max'];
verify_number($health_max, 'Health max', 11);
// mana
$magic_level = $_POST['magic_level'];
verify_number($magic_level, 'Magic_level', 11);
$mana = $_POST['mana'];
verify_number($mana, 'Mana', 11);
$mana_max = $_POST['mana_max'];
verify_number($mana_max, 'Mana max', 11);
$mana_spent = $_POST['mana_spent'];
verify_number($mana_spent, 'Mana spent', 11);
// look
$look_body = $_POST['look_body'];
verify_number($look_body, 'Look body', 11);
$look_feet = $_POST['look_feet'];
verify_number($look_feet, 'Look feet', 11);
$look_head = $_POST['look_head'];
verify_number($look_head, 'Look head', 11);
$look_legs = $_POST['look_legs'];
verify_number($look_legs, 'Look legs', 11);
$look_type = $_POST['look_type'];
verify_number($look_type, 'Look type', 11);
if ($hasLookAddons) {
$look_addons = $_POST['look_addons'];
verify_number($look_addons, 'Look addons', 11);
}
// pos
$pos_x = $_POST['pos_x'];
verify_number($pos_x, 'Position x', 11);
$pos_y = $_POST['pos_y'];
verify_number($pos_y, 'Position y', 11);
$pos_z = $_POST['pos_z'];
verify_number($pos_z, 'Position z', 11);
$soul = $_POST['soul'];
verify_number($soul, 'Soul', 10);
$town = $_POST['town'];
verify_number($town, 'Town', 11);
$capacity = $_POST['capacity'];
verify_number($capacity, 'Capacity', 11);
$sex = $_POST['sex'];
verify_number($sex, 'Sex', 1);
$lastlogin = $_POST['lastlogin'];
verify_number($lastlogin, 'Last login', 20);
$lastlogout = $_POST['lastlogout'];
verify_number($lastlogout, 'Last logout', 20);
$skull = $_POST['skull'];
verify_number($skull, 'Skull', 1);
$skull_time = $_POST['skull_time'];
verify_number($skull_time, 'Skull time', 11);
if ($db->hasColumn('players', 'loss_experience')) {
$loss_experience = $_POST['loss_experience'];
verify_number($loss_experience, 'Loss experience', 11);
$loss_mana = $_POST['loss_mana'];
verify_number($loss_mana, 'Loss mana', 11);
$loss_skills = $_POST['loss_skills'];
verify_number($loss_skills, 'Loss skills', 11);
$loss_containers = $_POST['loss_containers'];
verify_number($loss_containers, 'Loss loss_containers', 11);
$loss_items = $_POST['loss_items'];
verify_number($loss_items, 'Loss items', 11);
}
if ($db->hasColumn('players', 'offlinetraining_time')) {
$offlinetraining = $_POST['offlinetraining'];
verify_number($offlinetraining, 'Offline Training time', 11);
}
if ($hasBlessingsColumn) {
$blessings = $_POST['blessings'];
verify_number($blessings, 'Blessings', 2);
}
$balance = $_POST['balance'];
verify_number($balance, 'Balance', 20);
if ($db->hasColumn('players', 'stamina')) {
$stamina = $_POST['stamina'];
verify_number($stamina, 'Stamina', 20);
}
$deleted = (isset($_POST['deleted']) && $_POST['deleted'] == 'true');
$hidden = (isset($_POST['hidden']) && $_POST['hidden'] == 'true');
$created = $_POST['created'];
verify_number($created, 'Created', 11);
$comment = isset($_POST['comment']) ? htmlspecialchars(stripslashes(substr($_POST['comment'], 0, 2000))) : NULL;
foreach ($_POST['skills'] as $skill => $value)
verify_number($value, $skills[$skill][0], 10);
foreach ($_POST['skills_tries'] as $skill => $value)
verify_number($value, $skills[$skill][0] . ' tries', 10);
if ($hasBlessingColumn) {
$bless_count = $_POST['blesscount'];
for ($i = 1; $i <= $bless_count; $i++) {
$a = 'blessing' . $i;
${'blessing' . $i} = (isset($_POST[$a]) && $_POST[$a] == 'true');
}
}
if (!$error) {
$player->setName($name);
$player->setAccount($account_db);
$player->setGroup($groups->getGroup($group));
$player->setLevel($level);
$player->setExperience($experience);
$player->setVocation($vocation);
$player->setHealth($health);
$player->setHealthMax($health_max);
$player->setMagLevel($magic_level);
$player->setMana($mana);
$player->setManaMax($mana_max);
$player->setManaSpent($mana_spent);
$player->setLookBody($look_body);
$player->setLookFeet($look_feet);
$player->setLookHead($look_head);
$player->setLookLegs($look_legs);
$player->setLookType($look_type);
if ($hasLookAddons)
$player->setLookAddons($look_addons);
if ($db->hasColumn('players', 'offlinetraining_time'))
$player->setCustomField('offlinetraining_time', $offlinetraining);
$player->setPosX($pos_x);
$player->setPosY($pos_y);
$player->setPosZ($pos_z);
$player->setSoul($soul);
$player->setTownId($town);
$player->setCap($capacity);
$player->setSex($sex);
$player->setLastLogin($lastlogin);
$player->setLastLogout($lastlogout);
//$player->setLastIP(ip2long($lastip));
$player->setSkull($skull);
$player->setSkullTime($skull_time);
if ($db->hasColumn('players', 'loss_experience')) {
$player->setLossExperience($loss_experience);
$player->setLossMana($loss_mana);
$player->setLossSkills($loss_skills);
$player->setLossContainers($loss_containers);
$player->setLossItems($loss_items);
}
if ($db->hasColumn('players', 'blessings'))
$player->setBlessings($blessings);
if ($hasBlessingColumn) {
for ($i = 1; $i <= $bless_count; $i++) {
$a = 'blessing' . $i;
$player->setCustomField('blessings' . $i, ${'blessing' . $i} ? '1' : '0');
}
}
$player->setBalance($balance);
if ($db->hasColumn('players', 'stamina'))
$player->setStamina($stamina);
if ($db->hasColumn('players', 'deletion'))
$player->setCustomField('deletion', $deleted ? '1' : '0');
else
$player->setCustomField('deleted', $deleted ? '1' : '0');
$player->setCustomField('hidden', $hidden ? '1' : '0');
$player->setCustomField('created', $created);
if (isset($comment))
$player->setCustomField('comment', $comment);
foreach ($_POST['skills'] as $skill => $value) {
$player->setSkill($skill, $value);
}
foreach ($_POST['skills_tries'] as $skill => $value) {
$player->setSkillTries($skill, $value);
}
$player->save();
echo_success('Player saved at: ' . date('G:i'));
}
}
}
$search_name = '';
if (isset($_REQUEST['search_name']))
$search_name = $_REQUEST['search_name'];
else if ($id > 0 && isset($player) && $player->isLoaded())
$search_name = $player->getName();
?>
<div class="row">
<?php
if (isset($player) && $player->isLoaded()) {
$account = $player->getAccount();
?>
<form action="<?php echo $base . ((isset($id) && $id > 0) ? '&id=' . $id : ''); ?>" method="post"
class="form-horizontal">
<div class="col-md-8">
<div class="box box-primary">
<div class="box-body">
<div class="nav-tabs-custom">
<ul class="nav nav-tabs">
<li class="active"><a href="#tab_1" data-toggle="tab" aria-expanded="true">Player</a>
</li>
<li class=""><a href="#tab_2" data-toggle="tab" aria-expanded="false">Stats</a></li>
<li class=""><a href="#tab_3" data-toggle="tab" aria-expanded="false">Skills</a></li>
<li class=""><a href="#tab_4" data-toggle="tab" aria-expanded="false">Pos/Look</a></li>
<li class=""><a href="#tab_5" data-toggle="tab" aria-expanded="false">Misc</a></li>
<li class="pull-right"><a
href="<?php echo ADMIN_URL; ?>?p=accounts&search_name=<?php echo $account->getId(); ?>"
class="text-muted"><i class="fa fa-gear" title="Edit Account"></i></a></li>
</ul>
<div class="tab-content">
<div class="tab-pane active" id="tab_1">
<div class="row">
<div class="col-xs-6">
<label for="name" class="control-label">Name</label>
<input type="text" class="form-control" id="name" name="name"
autocomplete="off" style="cursor: auto;"
value="<?php echo $player->getName(); ?>"/>
</div>
<div class="col-xs-6">
<label for="account_id" class="control-label">Account id:</label>
<input type="text" class="form-control" id="account_id" name="account_id"
autocomplete="off" style="cursor: auto;" size="8" maxlength="11"
value="<?php echo $account->getId(); ?>"/>
</div>
</div>
<div class="row">
<div class="col-xs-6 ">
<label for="group" class="control-label">Group:</label>
<select name="group" id="group" class="form-control">
<?php foreach ($groups->getGroups() as $id => $group): ?>
<option value="<?php echo $id; ?>" <?php echo($player->getGroup()->getId() == $id ? 'selected' : ''); ?>><?php echo $group->getName(); ?></option>
<?php endforeach; ?>
</select>
</div>
<div class="col-xs-6">
<label for="vocation" class="control-label">Vocation</label>
<select name="vocation" id="vocation" class="form-control">
<?php
foreach ($config['vocations'] as $id => $name) {
echo '<option value=' . $id . ($id == $player->getVocation() ? ' selected' : '') . '>' . $name . '</option>';
}
?>
</select>
</div>
</div>
<div class="row">
<div class="col-xs-6">
<label for="sex" class="control-label">Sex:</label>
<select name="sex" id="sex" class="form-control">>
<?php foreach ($config['genders'] as $id => $sex): ?>
<option value="<?php echo $id; ?>" <?php echo($player->getSex() == $id ? 'selected' : ''); ?>><?php echo strtolower($sex); ?></option>
<?php endforeach; ?>
</select>
</div>
<div class="col-xs-6">
<label for="town" class="control-label">Town:</label>
<select name="town" id="town" class="form-control">
<?php foreach ($config['towns'] as $id => $town): ?>
<option value="<?php echo $id; ?>" <?php echo($player->getTownId() == $id ? 'selected' : ''); ?>><?php echo $town; ?></option>
<?php endforeach; ?>
</select>
</div>
</div>
<div class="row">
<div class="col-xs-6">
<label for="skull" class="control-label">Skull:</label>
<select name="skull" id="skull" class="form-control">
<?php
$skull_type = array("None", "Yellow", "Green", "White", "Red", "Black", "Orange");
foreach ($skull_type as $id => $s_name) {
echo '<option value=' . $id . ($id == $player->getSkull() ? ' selected' : '') . '>' . $s_name . '</option>';
}
?>
</select>
</div>
<div class="col-xs-6">
<label for="skull_time" class="control-label">Skull time:</label>
<input type="text" class="form-control" id="skull_time" name="skull_time"
autocomplete="off" maxlength="11"
value="<?php echo $player->getSkullTime(); ?>"/>
</div>
</div>
<div class="row">
<?php if ($hasBlessingColumn):
$blesscount = $player->countBlessings();
$bless = $player->checkBlessings($blesscount);
?>
<input type="hidden" name="blesscount" value="<?php echo $blesscount; ?>"/>
<div class="col-xs-6">
<label for="blessings" class="control-label">Blessings:</label>
<div class="checkbox">
<?php
for ($i = 1; $i <= $blesscount; $i++) {
echo '<label><input style="margin-left: -16px;" type="checkbox" name="blessing' . $i . '" id="blessing' . $i . '"
value="true" ' . (($bless[$i - 1] == 1) ? ' checked' : '') . '/>' . $i . '</label>';
}
?>
</div>
</div>
<?php endif; ?>
<?php if ($hasBlessingsColumn): ?>
<div class="col-xs-6">
<label for="blessings" class="control-label">Blessings:</label>
<input type="text" class="form-control" id="blessings" name="blessings"
autocomplete="off" maxlength="11"
value="<?php echo $player->getBlessings(); ?>"/>
</div>
<?php endif; ?>
<div class="col-xs-6">
<label for="balance" class="control-label">Bank Balance:</label>
<input type="text" class="form-control" id="balance" name="balance"
autocomplete="off" maxlength="20"
value="<?php echo $player->getBalance(); ?>"/>
</div>
</div>
<div class="row">
<div class="col-xs-6">
<label for="deleted" class="control-label">Deleted:</label>
<input type="checkbox" name="deleted" id="deleted"
value="true" <?php echo($player->getCustomField($db->hasColumn('players', 'deletion') ? 'deletion' : 'deleted') == '1' ? ' checked' : ''); ?>/>
</div>
<div class="col-xs-6">
<label for="hidden" class="control-label">Hidden:</label>
<input type="checkbox" name="hidden" id="hidden"
value="true" <?php echo($player->isHidden() ? ' checked' : ''); ?>/>
</div>
</div>
</div>
<div class="tab-pane" id="tab_2">
<div class="row">
<div class="col-xs-6 ">
<label for="level" class="control-label">Level:</label>
<input type="text" class="form-control" id="level" name="level"
autocomplete="off"
style="cursor: auto;" value="<?php echo $player->getLevel(); ?>"/>
</div>
<div class="col-xs-6">
<label for="magic_level" class="control-label">Magic level:</label>
<input type="text" class="form-control" id="magic_level" name="magic_level"
autocomplete="off" size="8" maxlength="11" style="cursor: auto;"
value="<?php echo $player->getMagLevel(); ?>"/>
</div>
</div>
<div class="row">
<div class="col-xs-6 ">
<label for="experience" class="control-label">Experience:</label>
<input type="text" class="form-control" id="experience" name="experience"
autocomplete="off"
style="cursor: auto;"
value="<?php echo $player->getExperience(); ?>"/>
</div>
<div class="col-xs-6">
<label for="mana_spent" class="control-label">Mana spent:</label>
<input type="text" class="form-control" id="mana_spent" name="mana_spent"
autocomplete="off"
size="3" maxlength="11" style="cursor: auto;"
value="<?php echo $player->getManaSpent(); ?>"/>
</div>
</div>
<div class="row">
<div class="col-xs-6 ">
<label for="health" class="control-label">Health:</label>
<input type="text" class="form-control" id="health" name="health"
autocomplete="off"
size="5" maxlength="11" style="cursor: auto;"
value="<?php echo $player->getHealth(); ?>"/>
</div>
<div class="col-xs-6">
<label for="health_max" class="control-label">Health max:</label>
<input type="text" class="form-control" id="health_max" name="health_max"
autocomplete="off"
size="5" maxlength="11" style="cursor: auto;"
value="<?php echo $player->getHealthMax(); ?>"/>
</div>
</div>
<div class="row">
<div class="col-xs-6 ">
<label for="mana" class="control-label">Mana:</label>
<input type="text" class="form-control" id="mana" name="mana"
autocomplete="off" size="3"
maxlength="11" style="cursor: auto;"
value="<?php echo $player->getMana(); ?>"/>
</div>
<div class="col-xs-6">
<label for="mana_max" class="control-label">Mana max:</label>
<input type="text" class="form-control" id="mana_max" name="mana_max"
autocomplete="off"
size="3" maxlength="11" style="cursor: auto;"
value="<?php echo $player->getManaMax(); ?>"/>
</div>
</div>
<div class="row">
<div class="col-xs-6">
<label for="capacity" class="control-label">Capacity:</label>
<input type="text" class="form-control" id="capacity" name="capacity"
autocomplete="off"
size="3" maxlength="11" style="cursor: auto;"
value="<?php echo $player->getCap(); ?>"/>
</div>
<div class="col-xs-6 ">
<label for="soul" class="control-label">Soul:</label>
<input type="text" class="form-control" id="soul" name="soul"
autocomplete="off" size="3"
maxlength="10" style="cursor: auto;"
value="<?php echo $player->getSoul(); ?>"/>
</div>
<?php if ($db->hasColumn('players', 'stamina')): ?>
<div class="col-xs-6">
<label for="stamina" class="control-label">Stamina:</label>
<input type="text" class="form-control" id="stamina" name="stamina"
autocomplete="off"
maxlength="20" style="cursor: auto;"
value="<?php echo $player->getStamina(); ?>"/>
</div>
<?php endif; ?>
<?php if ($db->hasColumn('players', 'offlinetraining_time')): ?>
<div class="col-xs-6">
<label for="offlinetraining" class="control-label">Offline Training
Time:</label>
<input type="text" class="form-control" id="offlinetraining"
name="offlinetraining" autocomplete="off"
maxlength="11"
value="<?php echo $player->getCustomField('offlinetraining_time'); ?>"/>
</div>
<?php endif; ?>
</div>
</div>
<div class="tab-pane" id="tab_3">
<?php
$i = 0;
foreach ($skills as $id => $info) {
if ($i == 0 || $i++ == 2) {
$i = 0;
}
echo '
<div class="row">
<div class="col-xs-6 ">
<label for="skills[' . $id . ']" class="control-label">' . $info[0] . '</label>
<input type="text" class="form-control" id="skills[' . $id . ']" name="skills[' . $id . ']" maxlength="10" autocomplete="off" style="cursor: auto;" value="' . $player->getSkill($id) . '"/>
</div>
<div class="col-xs-6">
<label for="skills_tries[' . $id . ']" class="control-label">' . $info[0] . ' tries</label>
<input type="text" class="form-control" id="skills_tries[' . $id . ']" name="skills_tries[' . $id . ']" maxlength="10" autocomplete="off" style="cursor: auto;" value="' . $player->getSkillTries($id) . '"/>
</div>
</div>';
if ($i == 0)
echo '';
}
?>
</div>
<div class="tab-pane" id="tab_4">
<?php $outfit = $config['outfit_images_url'] . '?id=' . $player->getLookType() . ($hasLookAddons ? '&addons=' . $player->getLookAddons() : '') . '&head=' . $player->getLookHead() . '&body=' . $player->getLookBody() . '&legs=' . $player->getLookLegs() . '&feet=' . $player->getLookFeet(); ?>
<div id="imgchar"
style="width:64px;height:64px;position:absolute; top:30px; right:30px"><img id="player_outfit"
style="margin-left:0;margin-top:0px;width:64px;height:64px;"
src="<?php echo $outfit; ?>"
alt="player outfit"/></div>
<?php ?>
<td>Position:</td>
<div class="row">
<div class="col-xs-4">
<label for="pos_x" class="control-label">X:</label>
<input type="text" class="form-control" id="pos_x" name="pos_x"
autocomplete="off"
maxlength="11" style="cursor: auto;"
value="<?php echo $player->getPosX(); ?>"/>
</div>
<div class="col-xs-4">
<label for="pos_y" class="control-label">Y:</label>
<input type="text" class="form-control" id="pos_y" name="pos_y"
autocomplete="off"
maxlength="11" value="<?php echo $player->getPosY(); ?>"/>
</div>
<div class="col-xs-4">
<label for="pos_z" class="control-label">Z:</label>
<input type="text" class="form-control" id="pos_z" name="pos_z"
autocomplete="off"
maxlength="11" value="<?php echo $player->getPosZ(); ?>"/>
</div>
</div>
<td>Look:</td>
<div class="row">
<div class="col-xs-3">
<label for="look_head" class="control-label">Head: <span
id="look_head_val"></span></label>
<input type="range" min="0" max="132"
value="<?php echo $player->getLookHead(); ?>"
class="slider form-control" id="look_head" name="look_head">
</div>
<div class="col-xs-3">
<label for="look_body" class="control-label">Body: <span
id="look_body_val"></span></label>
<input type="range" min="0" max="132"
value="<?php echo $player->getLookBody(); ?>"
class="slider form-control" id="look_body" name="look_body">
</div>
<div class="col-xs-3">
<label for="look_legs" class="control-label">Legs: <span
id="look_legs_val"></span></label>
<input type="range" min="0" max="132"
value="<?php echo $player->getLookLegs(); ?>"
class="slider form-control" id="look_legs" name="look_legs">
</div>
<div class="col-xs-3">
<label for="look_feet" class="control-label">Feet: <span
id="look_feet_val"></span></label>
<input type="range" min="0" max="132"
value="<?php echo $player->getLookBody(); ?>"
class="slider form-control" id="look_feet" name="look_feet">
</div>
</div>
<div class="row">
<div class="col-xs-6">
<label for="look_type" class="control-label">Type:</label>
<input type="text" class="form-control" id="look_type" name="look_type"
autocomplete="off"
maxlength="11" style="cursor: auto;"
value="<?php echo $player->getLookType(); ?>"/>
</div>
<?php if ($hasLookAddons): ?>
<div class="col-xs-6">
<label for="look_addons" class="control-label">Addons:</label>
<input type="text" class="form-control" id="look_addons"
name="look_addons" autocomplete="off"
maxlength="11" value="<?php echo $player->getLookAddons(); ?>"/>
</div>
<?php endif; ?>
</div>
</div>
<div class="tab-pane" id="tab_5">
<div class="row">
<div class="col-xs-6">
<label for="created" class="control-label">Created:</label>
<input type="text" class="form-control" id="created" name="created"
autocomplete="off"
maxlength="10"
value="<?php echo $player->getCustomField('created'); ?>"/>
</div>
<div class="col-xs-6">
<label for="lastlogin" class="control-label">Last login:</label>
<input type="text" class="form-control" id="lastlogin" name="lastlogin"
autocomplete="off"
maxlength="20" value="<?php echo $player->getLastLogin(); ?>"/>
</div>
<div class="col-xs-6">
<label for="lastlogout" class="control-label">Last logout:</label>
<input type="text" class="form-control" id="lastlogout" name="lastlogout"
autocomplete="off"
maxlength="20" value="<?php echo $player->getLastLogout(); ?>"/>
</div>
<div class="col-xs-6">
<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/>
</div>
</div>
<?php if ($db->hasColumn('players', 'loss_experience')): ?>
<div class="row">
<div class="col-xs-6">
<label for="loss_experience" class="control-label">Experience
Loss:</label>
<input type="text" class="form-control" id="loss_experience"
name="loss_experience" autocomplete="off"
maxlength="11"
value="<?php echo $player->getLossExperience(); ?>"/>
</div>
<div class="col-xs-6">
<label for="loss_mana" class="control-label">Mana Loss:</label>
<input type="text" class="form-control" id="loss_mana"
name="loss_mana" autocomplete="off"
maxlength="11" value="<?php echo $player->getLossMana(); ?>"/>
</div>
<div class="col-xs-6">
<label for="loss_skills" class="control-label">Skills Loss:</label>
<input type="text" class="form-control" id="loss_skills"
name="loss_skills" autocomplete="off"
maxlength="11" value="<?php echo $player->getLossSkills(); ?>"/>
</div>
<div class="col-xs-6">
<label for="loss_containers" class="control-label">Containers
Loss:</label>
<input type="text" class="form-control" id="loss_containers"
name="loss_containers" autocomplete="off"
maxlength="11"
value="<?php echo $player->getLossContainers(); ?>"/>
</div>
<div class="col-xs-6">
<label for="loss_items" class="control-label">Items Loss:</label>
<input type="text" class="form-control" id="loss_items"
name="loss_items" autocomplete="off"
maxlength="11" value="<?php echo $player->getLossItems(); ?>"/>
</div>
</div>
<?php endif; ?>
<div class="row">
<div class="col-xs-12">
<label for="comment" class="control-label">Comment:</label>
<textarea class="form-control" name="comment" rows="10" cols="50"
wrap="virtual"><?php echo $player->getCustomField("comment"); ?></textarea>
<small>[max.
length: 2000 chars, 50 lines (ENTERs)]
</small>
</div>
</div>
</div>
</div>
</div>
</div>
<input type="hidden" name="save" value="yes"/>
<div class="box-footer">
<a href="<?php echo ADMIN_URL; ?>?p=players"><span class="btn btn-danger">Cancel</span></a>
<div class="pull-right">
<input type="submit" class="btn btn-primary" value="Update">
</div>
</div>
</div>
</div>
</form>
<?php } ?>
<div class="col-md-4">
<div class="box box-primary">
<div class="box-header with-border">
<h3 class="box-title">Search Player:</h3>
<div class="box-tools pull-right">
<button type="button" class="btn btn-box-tool" data-widget="collapse"><i class="fa fa-minus"></i>
</button>
</div>
</div>
<div class="box-body">
<form action="<?php echo $base; ?>" method="post">
<div class="input-group input-group-sm">
<input type="text" class="form-control" name="search_name" value="<?php echo $search_name; ?>"
maxlength="32" size="32">
<span class="input-group-btn">
<button type="submit" type="button" class="btn btn-info btn-flat">Search</button>
</span>
</div>
</form>
</div>
</div>
<?php
if (isset($account) && $account->isLoaded()) {
$account_players = array();
$query = $db->query('SELECT `name`,`level`,`vocation` FROM `players` WHERE `account_id` = ' . $account->getId() . ' ORDER BY `name`')->fetchAll();
if (isset($query)) {
?>
<div class="box">
<div class="box-header">
<h3 class="box-title">Character List:</h3>
</div>
<div class="box-body no-padding">
<table class="table table-striped">
<tbody>
<tr>
<th style="width: 10px">#</th>
<th>Name</th>
<th>Level</th>
<th style="width: 40px">Edit</th>
</tr>
<?php
$i = 1;
foreach ($query as $p) {
$account_players[] = $p;
echo '<tr>
<td>' . $i . '.</td>
<td>' . $p['name'] . '</td>
<td>' . $p['level'] . '</td>
<td><a href="?p=players&search_name=' . $p['name'] . '"><span class="btn btn-success btn-sm edit btn-flat"><i class="fa fa-edit"></i></span></a></span></td>
</tr>';
$i++;
} ?>
</tbody>
</table>
</div>
</div>
<?php
};
};
?>
</div>
<script type="text/javascript">
$('#lastlogin').datetimepicker({
format: 'unixtime'
});
$('#lastlogout').datetimepicker({
format: 'unixtime'
});
$('#created').datetimepicker({
format: 'unixtime'
});
var slider_head = document.getElementById("look_head");
var output_head = document.getElementById("look_head_val");
var slider_body = document.getElementById("look_body");
var output_body = document.getElementById("look_body_val");
var slider_legs = document.getElementById("look_legs");
var output_legs = document.getElementById("look_legs_val");
var slider_feet = document.getElementById("look_feet");
var output_feet = document.getElementById("look_feet_val");
output_head.innerHTML = slider_head.value;
output_body.innerHTML = slider_body.value;
output_legs.innerHTML = slider_legs.value;
output_feet.innerHTML = slider_feet.value;
slider_head.oninput = function () {
output_head.innerHTML = this.value;
}
slider_body.oninput = function () {
output_body.innerHTML = this.value;
}
slider_legs.oninput = function () {
output_legs.innerHTML = this.value;
}
slider_feet.oninput = function () {
output_feet.innerHTML = this.value;
}
$('#look_head').change(function() {updateOutfit()});
$('#look_body').change(function() {updateOutfit()});
$('#look_legs').change(function() {updateOutfit()});
$('#look_feet').change(function() {updateOutfit()});
$('#look_type').change(function() {updateOutfit()});
<?php if($hasLookAddons): ?>
$('#look_addons').change(function() {updateOutfit()});
<?php endif; ?>
function updateOutfit()
{
var look_head = $('#look_head').val();
var look_body = $('#look_body').val();
var look_legs = $('#look_legs').val();
var look_feet = $('#look_feet').val();
var look_type = $('#look_type').val();
var look_addons = '';
<?php if($hasLookAddons): ?>
look_addons = '&addons=' + $('#look_addons').val();
<?php endif; ?>
new_outfit = '<?= $config['outfit_images_url']; ?>?id=' + look_type + look_addons + '&head=' + look_head + '&body=' + look_body + '&legs=' + look_legs + '&feet=' + look_feet;
$("#player_outfit").attr("src", new_outfit);
console.log(new_outfit);
}
</script>

View File

@@ -4,7 +4,7 @@
*
* @package MyAAC
* @author Lee
* @copyright 2020 MyAAC
* @copyright 2019 MyAAC
* @link https://my-aac.org
*/
defined('MYAAC') or die('Direct access not allowed!');
@@ -42,13 +42,16 @@ foreach ($files as &$f) {
unset($f);
$twig->display('admin.reports.html.twig', array('files' => $files));
$file = isset($_GET['file']) ? $_GET['file'] : NULL;
if (!empty($file)) {
if (!preg_match('/[^A-z0-9\' _\/\-\.]/', $file)) {
if (file_exists($server_path_reports . $file)) {
$file_content = nl2br(file_get_contents($server_path_reports . $file));
$content = nl2br(file_get_contents($server_path_reports . $file));
$twig->display('admin.logs.view.html.twig', array('file' => $file, 'content' => $file_content));
$twig->display('admin.logs.view.html.twig', array('file' => $file, 'content' => $content));
} else {
echo 'Specified file does not exist.';
}
@@ -56,5 +59,3 @@ if (!empty($file)) {
echo 'Invalid file name specified.';
}
}
$twig->display('admin.reports.html.twig', array('files' => $files));

View File

@@ -24,10 +24,10 @@ if (!$myaac_version) {
$version_compare = version_compare($myaac_version, MYAAC_VERSION);
if ($version_compare == 0) {
success('MyAAC latest version is ' . $myaac_version . '. You\'re using the latest version.
<br/>View CHANGELOG ' . generateLink(ADMIN_URL . '?p=clmd', 'here'));
<br/>View CHANGELOG ' . generateLink(ADMIN_URL . '?p=changelog', 'here'));
} else if ($version_compare < 0) {
success('Woah, seems you\'re using newer version as latest released one! MyAAC latest released version is ' . $myaac_version . ', and you\'re using version ' . MYAAC_VERSION . '.
<br/>View CHANGELOG ' . generateLink(ADMIN_URL . '?p=clmd', 'here'));
<br/>View CHANGELOG ' . generateLink(ADMIN_URL . '?p=changelog', 'here'));
} else {
warning('You\'re using outdated version.<br/>
Your version: <b>' . MYAAC_VERSION . '</b><br/>

View File

@@ -1,48 +0,0 @@
<?php
return [
['name' => 'Dashboard', 'icon' => 'tachometer-alt', 'link' => 'dashboard'],
['name' => 'News', 'icon' => 'newspaper', 'link' =>
[
['name' => 'View', 'link' => 'news'],
['name' => 'Add news', 'link' => 'news&action=new&type=1'],
['name' => 'Add ticker', 'link' => 'news&action=new&type=2'],
['name' => 'Add article', 'link' => 'news&action=new&type=3'],
],
],
['name' => 'Changelogs', 'icon' => 'newspaper', 'link' =>
[
['name' => 'View', 'link' => 'changelog'],
['name' => 'Add', 'link' => 'changelog&action=new'],
],
],
['name' => 'Mailer', 'icon' => 'envelope', 'link' => 'mailer', 'disabled' => !config('mail_enabled')],
['name' => 'Pages', 'icon' => 'book', 'link' =>
[
['name' => 'View', 'link' => 'pages'],
['name' => 'Add', 'link' => 'pages&action=new'],
],
],
['name' => 'Menus', 'icon' => 'list', 'link' => 'menus'],
['name' => 'Plugins', 'icon' => 'plug', 'link' => 'plugins'],
['name' => 'Server Data', 'icon' => 'gavel', 'link' => 'data'],
['name' => 'Editor', 'icon' => 'edit', 'link' =>
[
['name' => 'Accounts', 'link' => 'accounts'],
['name' => 'Players', 'link' => 'players'],
],
],
['name' => 'Tools', 'icon' => 'tools', 'link' =>
[
['name' => 'Notepad', 'link' => 'notepad'],
['name' => 'phpinfo', 'link' => 'phpinfo'],
],
],
['name' => 'Logs', 'icon' => 'bug', 'link' =>
[
['name' => 'Logs', 'link' => 'logs'],
['name' => 'Reports', 'link' => 'reports'],
['name' => 'Visitors', 'icon' => 'user', 'link' => 'visitors'],
],
],
];

View File

@@ -1,10 +1,44 @@
.menu-text-li {color: #4b646f; background: #1a2226;}
.menu-text {
display: block;
padding: .5rem 1rem;
white-space: nowrap;
.slidecontainer {
width: 100%;
}
.sidebar-mini.sidebar-collapse .menu-text {
display: none;
.slider {
-webkit-appearance: none;
width: 100%;
outline: none;
opacity: 0.7;
-webkit-transition: .2s;
transition: opacity .2s;
}
.slider:hover {
opacity: 1;
}
.slider::-webkit-slider-thumb {
-webkit-appearance: none;
appearance: none;
width: 15px;
height: 25px;
background: #3c8dbc;
cursor: pointer;
}
.slider::-moz-range-thumb {
width: 25px;
height: 25px;
background: #3c8dbc;
cursor: pointer;
}
td.details-control {
text-align: center;
color: forestgreen;
cursor: pointer;
}
tr.shown td.details-control {
text-align: center;
color: red;
}

View File

@@ -1,196 +1,229 @@
<?php defined('MYAAC') or die('Direct access not allowed!'); ?>
<!doctype html>
<html lang="en">
<!DOCTYPE html>
<html>
<head>
<?php echo template_header(true); ?>
<title><?php echo (isset($title) ? $title . ' - ' : '') . $config['lua']['serverName'];?></title>
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<link rel="stylesheet" href="<?php echo BASE_URL; ?>tools/css/adminlte.min.css">
<?php echo template_header(true);
$title_full = (isset($title) ? $title . $config['title_separator'] : '') . $config['lua']['serverName'];
?>
<title><?php echo $title_full ?></title>
<link rel="shortcut icon" href="<?php echo BASE_URL; ?>images/favicon.ico" type="image/x-icon" />
<link rel="icon" href="<?php echo BASE_URL; ?>images/favicon.ico" type="image/x-icon" />
<meta content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" name="viewport">
<link rel="stylesheet" href="<?php echo BASE_URL; ?>tools/css/bootstrap.min.css">
<link rel="stylesheet" href="<?php echo BASE_URL; ?>tools/css/AdminLTE.min.css">
<link rel="stylesheet" href="<?php echo BASE_URL; ?>tools/css/skins/skin-blue.min.css">
<link rel="stylesheet" href="<?php echo BASE_URL; ?>tools/css/font-awesome.min.css">
<?php if (isset($use_datatable)) { ?>
<link rel="stylesheet" href="<?php echo BASE_URL; ?>tools/css/datatables.bs.min.css">
<?php } ?>
<link rel="stylesheet" href="<?php echo BASE_URL; ?>tools/css/ionicons.min.css">
<link rel="stylesheet" href="<?php echo BASE_URL; ?>tools/css/jquery.dataTables.min.css">
<link rel="stylesheet" type="text/css" href="<?php echo $template_path; ?>style.css"/>
<!--[if lt IE 9]>
<script src="<?php echo BASE_URL; ?>tools/js/html5shiv.min.js"></script>
<script src="<?php echo BASE_URL; ?>tools/js/respond.min.js"></script>
<script src="https://oss.maxcdn.com/html5shiv/3.7.3/html5shiv.min.js"></script>
<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
<![endif]-->
<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">
</head>
<body class="sidebar-mini ">
<?php if ($logged && admin()) { ?>
<body class="hold-transition skin-blue sidebar-mini">
<div class="wrapper">
<nav class="main-header navbar navbar-expand navbar-white navbar-light">
<ul class="navbar-nav">
<li class="nav-item">
<a class="nav-link" data-widget="pushmenu" href="#"><i class="fas fa-bars"></i></a>
</li>
<li class="nav-item d-none d-sm-inline-block">
<a href="<?php echo ADMIN_URL; ?>" class="nav-link">Home</a>
</li>
</ul>
<ul class="navbar-nav ml-auto">
<li class="nav-item">
<a class="nav-link" data-widget="control-sidebar" data-slide="true" href="#"><i class="fas fa-th-large"></i></a>
</li>
</ul>
</nav>
<aside class="main-sidebar sidebar-dark-info elevation-4">
<a href="<?php echo ADMIN_URL; ?>" class="brand-link navbar-info">
<img src="<?php echo ADMIN_URL; ?>images/logo.png" class="brand-image img-circle elevation-3" style="opacity: .8">
<span class="brand-text"><b>My</b>AAC</span>
</a>
<div class="sidebar">
<nav class="mt-1">
<ul class="nav nav-pills nav-sidebar flex-column nav-legacy nav-child-indent" data-widget="treeview" data-accordion="false">
<li class="menu-text-li">
<span class="menu-text">
<a class="text-info" href="<?php echo BASE_URL; ?>" target="_blank">
<?php echo $config['lua']['serverName'] ?>
</a>
</span>
</li>
<?php
// name = Display name of link
// icon = fontawesome icon name without "fas fa-"
// link = Page link or use as array for sub items
$menus = require __DIR__ . '/menus.php';
if ($logged && admin()) {
?>
<header class="main-header">
<a href="." class="logo">
<span class="logo-mini"><b>M</b>A</span>
<span class="logo-lg"><b>My</b>AAC</span>
</a>
foreach ($menus as $category => $menu) {
if (isset($menu['disabled']) && $menu['disabled']) {
continue;
<nav class="navbar navbar-static-top" role="navigation">
<a href="#" class="sidebar-toggle" data-toggle="push-menu" role="button">
<span class="sr-only">Toggle navigation</span>
</a>
<div class="navbar-custom-menu">
<ul class="nav navbar-nav">
<li>
<a href="#" data-toggle="control-sidebar"><i class="fa fa-gears"></i></a>
</li>
</ul>
</div>
</nav>
</header>
<aside class="main-sidebar">
<section class="sidebar">
<ul class="sidebar-menu" data-widget="tree">
<li class="header">MyAAC</li>
<?php
$icons_a = array(
'dashboard','newspaper-o', 'envelope',
'book', 'list',
'plug', 'user',
'edit', 'gavel',
'wrench', 'edit', 'book', 'book',
);
$menus = array(
'Dashboard' => 'dashboard',
'News' => 'news',
'Mailer' => 'mailer',
'Pages' => 'pages',
'Menus' => 'menus',
'Plugins' => 'plugins',
'Visitors' => 'visitors',
'Editor' => array(
'Accounts' => 'accounts',
'Players' => 'players',
),
'Items' => 'items',
'Tools' => array(
'Notepad' => 'notepad',
'phpinfo' => 'phpinfo',
),
'Logs' => array(
'Logs' => 'logs',
'Reports' => 'reports',
),
);
$i = 0;
foreach ($menus as $_name => $_page) {
$has_child = is_array($_page);
if (!$has_child) {
echo '<li ';
if ($page == $_page) echo ' class="active"';
echo ">";
echo '<a href="?p=' . $_page . '"><i class="fa fa-' . (isset($icons_a[$i]) ? $icons_a[$i] : 'link') . '"></i> <span>' . $_name . '</span></a></li>';
}
$has_child = is_array($menu['link']);
if (!$has_child) { ?>
<li class="nav-item">
<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>
<p><?php echo $menu['name'] ?></p>
</a>
</li>
<?php
} else if ($has_child) {
$used_menu = null;
if ($has_child) {
$used_menu = "";
$nav_construct = '';
foreach ($menu['link'] as $category => $sub_menu) {
$nav_construct .= '<li class="nav-item"><a href="?p=' . $sub_menu['link'] . '" class="nav-link';
if ($page == $sub_menu['link']) {
$nav_construct .= ' active';
foreach ($_page as $__name => $__page) {
$nav_construct = $nav_construct . '<li';
if ($page == $__page) {
$nav_construct = $nav_construct . ' class="active"';
$used_menu = true;
}
$nav_construct .= '"><i class="far fa-' . (isset($sub_menu['icon']) ? $sub_menu['icon'] : 'circle') . ' nav-icon"></i><p>' . $sub_menu['name'] . '</p></a></li>';
$nav_construct = $nav_construct . '><a href="?p=' . $__page . '"><i class="fa fa-circle-o"></i> ' . $__name . '</a></li>';
}
?>
<li class="nav-item has-treeview<?php echo($used_menu ? ' menu-open' : '') ?>">
<a href="#" class="nav-link<?php echo($used_menu ? ' active' : '') ?>">
<i class="nav-icon fas fa-<?php echo(isset($menu['icon']) ? $menu['icon'] : 'link') ?>"></i>
<p><?php echo $menu['name'] ?></p><i class="right fas fa-angle-left"></i>
</a>
<ul class="nav nav-treeview">
<?php echo $nav_construct; ?>
</ul>
</li>
<?php
echo '<li class="treeview' . (($used_menu) ? ' menu-open' : '') . '">
<a href="#"><i class="fa fa-' . (isset($icons_a[$i]) ? $icons_a[$i] : 'link') . '"></i> <span>' . $_name . '</span>
<span class="pull-right-container"><i class="fa fa-angle-left pull-right"></i></span></a>
<ul class="treeview-menu" style="' . (($used_menu) ? ' display: block' : ' display: none') . '">';
echo $nav_construct;
echo '</ul>
</li>';
}
$i++;
}
$query = $db->query('SELECT `name`, `page`, `flags` FROM `' . TABLE_PREFIX . 'admin_menu` ORDER BY `ordering`');
$menu_db = $query->fetchAll();
foreach ($menu_db as $item) {
if ($item['flags'] == 0 || hasFlag($item['flags'])) { ?>
<li class="nav-item">
<a class="nav-link<?php echo($page == $item['page'] ? ' active' : '') ?>" href="?p=<?php echo $item['page'] ?>">
<i class="nav-icon fas fa-link"></i>
<p><?php echo $item['name'] ?></p>
</a>
</li>
<?php
if ($item['flags'] == 0 || hasFlag($item['flags'])) {
echo '<li ';
if ($page == $item['page']) echo ' class="active"';
echo ">";
echo '<a href="?p=' . $item['page'] . '"><i class="fa fa-link"></i> <span>' . $item['name'] . '</span></a></li>';
}
}
?>
</ul>
</nav>
</div>
</section>
</aside>
<div class="content-wrapper" style="min-height: 823px;">
<div class="content-header">
<div class="container-fluid">
<div class="row mb-2">
<div class="col-sm-6">
<h3 class="m-0 text-dark"><?php echo(isset($title) ? $title : ''); ?><small> - Admin Panel</small></h3>
<div class="content-wrapper">
<section class="content-header">
<h1><?php echo(isset($title) ? $title : ''); ?>
<small> - Admin Panel</small>
<div class="pull-right">
<span class="label label-<?php echo(($status['online']) ? 'success' : 'danger'); ?>"><?php echo $config['lua']['serverName'] ?></span>
</div>
<div class="col-sm-6">
<div class="float-sm-right d-none d-sm-inline">
<span class="p-2 right badge badge-<?php echo((isset($status['online']) and $status['online']) ? 'success' : 'danger'); ?>"><?php echo $config['lua']['serverName'] ?></span>
</div>
</div>
</div>
</div>
</div>
<div class="content">
<div class="container-fluid">
</h1>
</section>
<section class="content">
<?php echo $content; ?>
</div>
</div>
</div>
</section>
<aside class="control-sidebar control-sidebar-dark">
<div class="p-3">
<h4>Account:</h4>
<p><h5><a href="?action=logout"><i class="fas fa-sign-out-alt text-danger"></i> Log out</h5></a>
<small>This will log you out</small></p>
</div>
<div class="p-3">
<h4>Site:</h4>
<p><h5><a href="<?php echo BASE_URL; ?>" target="_blank"><i class="far fa-eye text-blue"></i> Preview</a></h5>
<small>This will open a new tab</small></p>
</div>
<div class="p-3">
<h4>Version:</h4>
<p><h5><a href="?p=version"><i class="fas fa-code-branch"></i> <?php echo MYAAC_VERSION; ?></a></h5>
<small>Check for updates</small></p>
</div>
<div class="p-3">
<h4>Site:</h4>
<p><h5><a href="https://github.com/slawkens/myaac" target="_blank"><i class="fab fa-github"></i> Github</a></h5>
<small>Goto GitHub Page</small></p>
<p><h5><a href="http://my-aac.org/" target="_blank"><i class="fas fa-shoe-prints"></i> MyAAC Official</a></h5>
<small>Goto MyAAC Official Website</small></p>
</div>
</aside>
<footer class="main-footer">
<div class="float-sm-right d-none d-sm-inline">
<span class="p-2 right badge badge-<?php echo((isset($status['online']) and $status['online']) ? 'success' : 'danger'); ?>"><?php echo $config['lua']['serverName'] ?></span>
<div class="pull-right hidden-xs">
<div id="status">
<?php if ($status['online']): ?>
<p class="success" style="width: 120px; text-align: center;">Server Online</p>
<?php else: ?>
<p class="error" style="width: 120px; text-align: center;">Server Offline</p>
<?php endif; ?>
</div>
</div>
<?php echo base64_decode('UG93ZXJlZCBieSA8YSBocmVmPSJodHRwOi8vbXktYWFjLm9yZyIgdGFyZ2V0PSJfYmxhbmsiPk15QUFDLjwvYT4='); ?>
</footer>
<div id="sidebar-overlay"></div>
<aside class="control-sidebar control-sidebar-dark">
<ul class="nav nav-tabs nav-justified control-sidebar-tabs">
<li class="active"><a href="#control-sidebar-home-tab" data-toggle="tab"><i class="fa fa-home"></i></a></li>
<li><a href="#control-sidebar-settings-tab" data-toggle="tab"><i class="fa fa-gears"></i></a></li>
</ul>
<div class="tab-content">
<div class="tab-pane active" id="control-sidebar-home-tab">
<h3 class="control-sidebar-heading">Account</h3>
<ul class="control-sidebar-menu">
<li>
<a href="?action=logout">
<i class="menu-icon fa fa-sign-out bg-red"></i>
<div class="menu-info">
<h4 class="control-sidebar-subheading">Log out</h4>
<p>This will log you out
of <?php echo(USE_ACCOUNT_NAME ? $account_logged->getName() : $account_logged->getId()); ?></p>
</div>
</a>
</li>
</ul>
<h3 class="control-sidebar-heading">Site</h3>
<ul class="control-sidebar-menu">
<li>
<a href="<?php echo BASE_URL; ?>" target="_blank">
<i class="menu-icon fa fa-eye bg-blue"></i>
<div class="menu-info">
<h4 class="control-sidebar-subheading">Preview</h4>
<p>This will open a new tab</p>
</div>
</a>
</li>
</ul>
</div>
<div class="tab-pane" id="control-sidebar-settings-tab">
<form method="post">
<h3 class="control-sidebar-heading">Version</h3>
<div class="form-group">
<label class="control-sidebar-subheading">
<?php echo MYAAC_VERSION; ?> (<a href="?p=version">Check for updates</a>)<br/>
</label>
<label class="control-sidebar-subheading">
<p><a href="https://github.com/slawkens/myaac" target="_blank">Github</a></p>
</div>
</form>
</div>
</div>
</aside>
<div class="control-sidebar-bg"></div>
</div>
<?php } else if (!$logged && !admin()) {
<?php }
if (!$logged && !admin()) {
echo $content;
}
?>
<?php
/**
* @var OTS_Account $account_logged
*/
if ($logged && admin()) {
$twig->display('admin-bar.html.twig', [
'username' => USE_ACCOUNT_NAME ? $account_logged->getName() : $account_logged->getId()
]);
}
?>
<script src="<?php echo BASE_URL; ?>tools/js/bootstrap.min.js"></script>
<script src="<?php echo BASE_URL; ?>tools/js/jquery-ui.min.js"></script>
<?php if (isset($use_datatable)) { ?>
<script src="<?php echo BASE_URL; ?>tools/js/datatables.min.js"></script>
<script src="<?php echo BASE_URL; ?>tools/js/datatables.bs.min.js"></script>
<?php } ?>
<script src="<?php echo BASE_URL; ?>tools/js/jquery.dataTables.min.js"></script>
<script src="<?php echo BASE_URL; ?>tools/js/adminlte.min.js"></script>
</body>
</html>

View File

@@ -1,6 +1,4 @@
<?php
define('MYAAC_ADMIN', true);
require '../../common.php';
require SYSTEM . 'functions.php';
require SYSTEM . 'init.php';

View File

@@ -1,46 +0,0 @@
<?php
/**
* Project: MyAAC
* Automatic Account Creator for Open Tibia Servers
*
* This is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* @package MyAAC
* @author Slawkens <slawkens@gmail.com>
* @copyright 2020 MyAAC
* @link https://my-aac.org
*/
define('MYAAC_ADMIN', true);
require '../../common.php';
require SYSTEM . 'functions.php';
require SYSTEM . 'init.php';
require SYSTEM . 'login.php';
if (!admin())
die('Access denied.');
ini_set('max_execution_time', 300);
ob_implicit_flush();
ob_end_flush();
header('X-Accel-Buffering: no');
require LIBS . 'DataLoader.php';
require LOCALE . 'en/main.php';
require LOCALE . 'en/install.php';
DataLoader::setLocale($locale);
DataLoader::load();

View File

@@ -1,6 +1,4 @@
<?php
define('MYAAC_ADMIN', true);
require '../../common.php';
require SYSTEM . 'init.php';
require SYSTEM . 'functions.php';

View File

@@ -23,74 +23,68 @@
* @copyright 2019 MyAAC
* @link https://my-aac.org
*/
if (version_compare(phpversion(), '7.1', '<')) die('PHP version 7.1 or higher is required.');
if (version_compare(phpversion(), '5.6', '<')) die('PHP version 5.6 or higher is required.');
session_start();
const MYAAC = true;
const MYAAC_VERSION = '0.9.0-dev';
const DATABASE_VERSION = 33;
const TABLE_PREFIX = 'myaac_';
define('MYAAC', true);
define('MYAAC_VERSION', '0.8.6');
define('DATABASE_VERSION', 32);
define('TABLE_PREFIX', 'myaac_');
define('START_TIME', microtime(true));
define('MYAAC_OS', stripos(PHP_OS, 'WIN') === 0 ? 'WINDOWS' : (strtoupper(PHP_OS) === 'DARWIN' ? 'MAC' : 'LINUX'));
define('IS_CLI', in_array(php_sapi_name(), ['cli', 'phpdb']));
// account flags
const FLAG_ADMIN = 1;
const FLAG_SUPER_ADMIN = 2;
const FLAG_CONTENT_PAGES = 4;
const FLAG_CONTENT_MAILER = 8;
const FLAG_CONTENT_NEWS = 16;
const FLAG_CONTENT_FORUM = 32;
const FLAG_CONTENT_COMMANDS = 64;
const FLAG_CONTENT_SPELLS = 128;
const FLAG_CONTENT_MONSTERS = 256;
const FLAG_CONTENT_GALLERY = 512;
const FLAG_CONTENT_VIDEOS = 1024;
const FLAG_CONTENT_FAQ = 2048;
const FLAG_CONTENT_MENUS = 4096;
const FLAG_CONTENT_PLAYERS = 8192;
define('FLAG_ADMIN', 1);
define('FLAG_SUPER_ADMIN', 2);
define('FLAG_CONTENT_PAGES', 4);
define('FLAG_CONTENT_MAILER', 8);
define('FLAG_CONTENT_NEWS', 16);
define('FLAG_CONTENT_FORUM', 32);
define('FLAG_CONTENT_COMMANDS', 64);
define('FLAG_CONTENT_SPELLS', 128);
define('FLAG_CONTENT_MONSTERS', 256);
define('FLAG_CONTENT_GALLERY', 512);
define('FLAG_CONTENT_VIDEOS', 1024);
define('FLAG_CONTENT_FAQ', 2048);
define('FLAG_CONTENT_MENUS', 4096);
define('FLAG_CONTENT_PLAYERS', 8192);
// news
const NEWS = 1;
const TICKER = 2;
const ARTICLE = 3;
define('NEWS', 1);
define('TICKER', 2);
define('ARTICLE', 3);
// directories
const BASE = __DIR__ . '/';
const ADMIN = BASE . 'admin/';
const SYSTEM = BASE . 'system/';
const CACHE = SYSTEM . 'cache/';
const LOCALE = SYSTEM . 'locale/';
const LIBS = SYSTEM . 'libs/';
const LOGS = SYSTEM . 'logs/';
const PAGES = SYSTEM . 'pages/';
const PLUGINS = BASE . 'plugins/';
const TEMPLATES = BASE . 'templates/';
const TOOLS = BASE . 'tools/';
const VENDOR = BASE . 'vendor/';
define('BASE', __DIR__ . '/');
define('ADMIN', BASE . 'admin/');
define('SYSTEM', BASE . 'system/');
define('CACHE', SYSTEM . 'cache/');
define('LOCALE', SYSTEM . 'locale/');
define('LIBS', SYSTEM . 'libs/');
define('LOGS', SYSTEM . 'logs/');
define('PAGES', SYSTEM . 'pages/');
define('PLUGINS', BASE . 'plugins/');
define('TEMPLATES', BASE . 'templates/');
define('TOOLS', BASE . 'tools/');
// menu categories
const MENU_CATEGORY_NEWS = 1;
const MENU_CATEGORY_ACCOUNT = 2;
const MENU_CATEGORY_COMMUNITY = 3;
const MENU_CATEGORY_FORUM = 4;
const MENU_CATEGORY_LIBRARY = 5;
const MENU_CATEGORY_SHOP = 6;
define('MENU_CATEGORY_NEWS', 1);
define('MENU_CATEGORY_ACCOUNT', 2);
define('MENU_CATEGORY_COMMUNITY', 3);
define('MENU_CATEGORY_FORUM', 4);
define('MENU_CATEGORY_LIBRARY', 5);
define('MENU_CATEGORY_SHOP', 6);
// otserv versions
const OTSERV = 1;
const OTSERV_06 = 2;
const OTSERV_FIRST = OTSERV;
const OTSERV_LAST = OTSERV_06;
const TFS_02 = 3;
const TFS_03 = 4;
const TFS_FIRST = TFS_02;
const TFS_LAST = TFS_03;
// other definitions
const ACCOUNT_NUMBER_LENGTH = 10;
session_save_path(SYSTEM . 'php_sessions');
session_start();
define('OTSERV', 1);
define('OTSERV_06', 2);
define('OTSERV_FIRST', OTSERV);
define('OTSERV_LAST', OTSERV_06);
define('TFS_02', 3);
define('TFS_03', 4);
define('TFS_FIRST', TFS_02);
define('TFS_LAST', TFS_03);
// basedir
$basedir = '';
@@ -121,10 +115,4 @@ if(!IS_CLI) {
require SYSTEM . 'exception.php';
}
$autoloadFile = VENDOR . 'autoload.php';
if (!is_file($autoloadFile)) {
throw new RuntimeException('The vendor folder is missing. Please download Composer: <a href="https://getcomposer.org/download">https://getcomposer.org/download</a>, install it and execute in the main MyAAC directory this command: <b>composer install</b>. Or download MyAAC from <a href="https://github.com/slawkens/myaac/releases">GitHub releases</a>, which includes Vendor folder.');
}
require $autoloadFile;
require SYSTEM . 'autoload.php';

View File

@@ -1,14 +0,0 @@
{
"require": {
"php": "^7.2.5 || ^8.0",
"ext-pdo": "*",
"ext-pdo_mysql": "*",
"ext-json": "*",
"ext-xml": "*",
"ext-dom": "*",
"phpmailer/phpmailer": "^6.1",
"composer/semver": "^3.2",
"twig/twig": "^1.0",
"erusev/parsedown": "^1.7"
}
}

View File

@@ -52,6 +52,7 @@ $config = array(
// 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
'title_separator' => ' - ',
// footer
'footer' => ''/*'<br/>Your Server &copy; 2016. All rights reserved.'*/,
@@ -86,26 +87,14 @@ $config = array(
// 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
'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
@@ -135,17 +124,11 @@ $config = array(
'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 (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,
'recaptcha_theme' => 'light', // light, dark
//
'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)
@@ -168,8 +151,6 @@ $config = array(
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,
@@ -181,12 +162,9 @@ $config = array(
// 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
// if you use TFS 1.3 with support for 'towns' table in database, then you can ignore this - it will be configured automatically (generated from your .OTBM map)
'towns' => array(
0 => 'No town',
1 => 'Sample town'
@@ -197,7 +175,6 @@ $config = array(
'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
@@ -218,19 +195,19 @@ $config = array(
'team_display_outfit' => true,
// bans page
'bans_per_page' => 20,
'bans_limit' => 50,
'bans_display_all' => true, // should all bans be displayed? (sorted page by page)
// 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_frags' => false, // show 'Frags' tab (best fraggers on the server)? Only 0.3
'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)
'highscores_length' => 100, // how many records per page on highscores
// characters page
'characters' => array( // what things to display on character view page (true/false in each option)
@@ -281,10 +258,9 @@ $config = array(
'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)
'status_timeout' => 2, // 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
@@ -292,7 +268,7 @@ $config = array(
'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
'admin_panel_modules' => 'lastlogin,points,coins',
// other
'anonymous_usage_statistics' => true,

Binary file not shown.

Before

Width:  |  Height:  |  Size: 318 B

After

Width:  |  Height:  |  Size: 433 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 363 B

After

Width:  |  Height:  |  Size: 450 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 592 B

After

Width:  |  Height:  |  Size: 706 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 845 B

After

Width:  |  Height:  |  Size: 1004 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 110 B

After

Width:  |  Height:  |  Size: 117 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 631 B

After

Width:  |  Height:  |  Size: 783 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1005 B

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 735 B

After

Width:  |  Height:  |  Size: 789 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.2 KiB

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.6 KiB

After

Width:  |  Height:  |  Size: 9.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 463 B

After

Width:  |  Height:  |  Size: 615 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 633 B

After

Width:  |  Height:  |  Size: 816 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 474 B

After

Width:  |  Height:  |  Size: 476 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 709 B

After

Width:  |  Height:  |  Size: 809 B

View File

@@ -103,12 +103,10 @@ else {
'/^account\/character\/comment\/[A-Za-z0-9-_%+\']+\/?$/' => array('subtopic' => 'accountmanagement', 'action' => 'change_comment', 'name' => '$3'),
'/^account\/character\/comment\/?$/' => array('subtopic' => 'accountmanagement', 'action' => 'change_comment'),
'/^account\/confirm_email\/[A-Za-z0-9-_]+\/?$/' => array('subtopic' => 'accountmanagement', 'action' => 'confirm_email', 'v' => '$2'),
'/^bans\/[0-9]+\/?$/' => array('subtopic' => 'bans', 'page' => '$1'),
'/^characters\/[A-Za-z0-9-_%+\']+$/' => array('subtopic' => 'characters', 'name' => '$1'),
'/^changelog\/[0-9]+\/?$/' => array('subtopic' => 'changelog', 'page' => '$1'),
'/^commands\/add\/?$/' => array('subtopic' => 'commands', 'action' => 'add'),
'/^commands\/edit\/?$/' => array('subtopic' => 'commands', 'action' => 'edit'),
'/^creatures\/[A-Za-z0-9-_%+\']+$/' => array('subtopic' => 'creatures', 'creature' => '$1'),
'/^faq\/add\/?$/' => array('subtopic' => 'faq', 'action' => 'add'),
'/^faq\/edit\/?$/' => array('subtopic' => 'faq', 'action' => 'edit'),
'/^forum\/add_board\/?$/' => array('subtopic' => 'forum', 'action' => 'add_board'),#
@@ -178,11 +176,6 @@ $template_place_holders = array();
require_once SYSTEM . 'init.php';
// verify myaac tables exists in database
if(!$db->hasTable('myaac_account_actions')) {
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.');
}
// event system
require_once SYSTEM . 'hooks.php';
$hooks = new Hooks();
@@ -194,6 +187,11 @@ require_once SYSTEM . 'status.php';
$twig->addGlobal('config', $config);
$twig->addGlobal('status', $status);
// verify myaac tables exists in database
if(!$db->hasTable('myaac_account_actions')) {
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.');
}
require SYSTEM . 'migrate.php';
$hooks->trigger(HOOK_STARTUP);
@@ -314,10 +312,8 @@ if($load_it)
if(SITE_CLOSED && admin())
$content .= '<p class="note">Site is under maintenance (closed mode). Only privileged users can see it.</p>';
if($config['backward_support']) {
require SYSTEM . 'compat/pages.php';
require SYSTEM . 'compat/classes.php';
}
if($config['backward_support'])
require SYSTEM . 'compat_pages.php';
$ignore = false;
@@ -337,17 +333,13 @@ if($load_it)
)) . $content;
}
} else {
$file = $template_path . '/pages/' . $page . '.php';
if(!@file_exists($file))
{
$file = SYSTEM . 'pages/' . $page . '.php';
if(!@file_exists($file))
if(!@file_exists($file) || preg_match('/[^A-z0-9_\-]/', $page))
{
$page = '404';
$file = SYSTEM . 'pages/404.php';
}
}
}
ob_start();
if($hooks->trigger(HOOK_BEFORE_PAGE)) {
@@ -371,15 +363,7 @@ if($config['backward_support']) {
$topic = $title;
}
/**
* @var OTS_Account $account_logged
*/
if ($logged && admin()) {
$content .= $twig->render('admin-bar.html.twig', [
'username' => USE_ACCOUNT_NAME ? $account_logged->getName() : $account_logged->getId()
]);
}
$title_full = (isset($title) ? $title . ' - ' : '') . $config['lua']['serverName'];
$title_full = (isset($title) ? $title . $config['title_separator'] : '') . $config['lua']['serverName'];
require $template_path . '/' . $template_index;
echo base64_decode('PCEtLSBQb3dlcmVkIGJ5IE15QUFDIDo6IGh0dHBzOi8vd3d3Lm15LWFhYy5vcmcvIC0tPg==') . PHP_EOL;

View File

@@ -6,18 +6,12 @@ $ots = POT::getInstance();
require SYSTEM . 'database.php';
if(!isset($db)) {
$database_error = '<p class="lead">' . $locale['step_database_error_mysql_connect'] . '</p>';
$database_error .= '<p>' . $locale['step_database_error_mysql_connect_2'] . '</p>';
$database_error .= '<ul class="list-group">' .
'<li class="list-group-item list-group-item-warning">' . $locale['step_database_error_mysql_connect_3'] . '</li>' .
'<li class="list-group-item list-group-item-warning">' . $locale['step_database_error_mysql_connect_4'] . '</li>' .
'</ul>';
$database_error .= '<div class="alert alert-danger mt-4">
<span>' . $error . '</span>
</div>';
$database_error = $locale['step_database_error_mysql_connect'] . '<br/>' .
$locale['step_database_error_mysql_connect_2'] .
'<ul>' .
'<li>' . $locale['step_database_error_mysql_connect_3'] . '</li>' .
'<li>' . $locale['step_database_error_mysql_connect_4'] . '</li>' .
'</ul>' . '<br/>' . $error;
}
else {
if($db->hasTable('accounts'))

View File

@@ -62,9 +62,9 @@ function next_buttons($previous = true, $next = true)
$ret .= '<input class="button" type="submit" onclick="document.getElementById(\'step\').value=\'' . $steps[$i + 1] . '\';" value="' . $locale['next'] . '" />';
*/
if($previous)
$ret .= '<input type="button" class="button btn btn-primary m-2" onclick="document.getElementById(\'step\').value=\'' . $steps[$i - 1] . '\'; this.form.submit();" value="&laquo; ' . $locale['previous'] . '" />';
$ret .= '<input type="button" class="button" onclick="document.getElementById(\'step\').value=\'' . $steps[$i - 1] . '\'; this.form.submit();" value="&laquo; ' . $locale['previous'] . '" />';
if($next)
$ret .= '<input type="button" class="button btn btn-primary m-2" onclick="document.getElementById(\'step\').value=\'' . $steps[$i + 1] . '\'; this.form.submit(); " value="' . $locale['next'] . ' &raquo;" />';
$ret .= '<input type="button" class="button" onclick="document.getElementById(\'step\').value=\'' . $steps[$i + 1] . '\'; this.form.submit(); " value="' . $locale['next'] . ' &raquo;" />';
$ret .= '</div>';
return $ret;

View File

@@ -1,4 +1,4 @@
SET @myaac_database_version = 33;
SET @myaac_database_version = 32;
CREATE TABLE `myaac_account_actions`
(
@@ -228,6 +228,17 @@ CREATE TABLE `myaac_monsters` (
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8;
CREATE TABLE `myaac_videos`
(
`id` INT(11) NOT NULL AUTO_INCREMENT,
`title` VARCHAR(100) NOT NULL DEFAULT '',
`youtube_id` VARCHAR(20) NOT NULL,
`author` VARCHAR(50) NOT NULL DEFAULT '',
`ordering` INT(11) NOT NULL DEFAULT 0,
`hidden` TINYINT(1) NOT NULL DEFAULT 0,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8;
CREATE TABLE `myaac_news`
(
`id` INT(11) NOT NULL AUTO_INCREMENT,
@@ -327,7 +338,7 @@ CREATE TABLE `myaac_spells`
CREATE TABLE `myaac_visitors`
(
`ip` VARCHAR(45) NOT NULL,
`ip` VARCHAR(16) NOT NULL,
`lastvisit` INT(11) NOT NULL DEFAULT 0,
`page` VARCHAR(2048) NOT NULL,
UNIQUE (`ip`)

View File

@@ -2,10 +2,10 @@ We have detected that you don't have access to write to the system/cache directo
<style type="text/css">
.console {
font-family: Courier,serif;
font-family:Courier;
color: #CCCCCC;
background: #000000;
border: 3px double #CCCCCC;
padding: 0;
padding: 0px;
}
</style>

View File

@@ -95,6 +95,10 @@ if($step == 'database') {
$errors[] = $locale['step_config_mail_admin_error'];
break;
}
else if($key == 'mail_address' && !Validator::email($value)) {
$errors[] = $locale['step_config_mail_address_error'];
break;
}
else if($key == 'timezone' && !in_array($value, DateTimeZone::listIdentifiers())) {
$errors[] = $locale['step_config_timezone_error'];
break;

View File

@@ -1,7 +1,7 @@
<?php
defined('MYAAC') or die('Direct access not allowed!');
if(isset($config['installed']) && $config['installed'] && !isset($_SESSION['saved'])) {
echo '<div class="alert alert-warning"><span>' . $locale['already_installed'] . '</span></div>';
echo '<p class="warning">' . $locale['already_installed'] . '</p>';
}
else {
unset($_SESSION['saved']);

View File

@@ -2,21 +2,8 @@
defined('MYAAC') or die('Direct access not allowed!');
// configuration
$dirs_required = [
'system/logs',
'system/cache',
];
$dirs_optional = [
'images/guilds' => $locale['step_requirements_warning_images_guilds'],
'images/gallery' => $locale['step_requirements_warning_images_gallery'],
];
$extensions_required = [
'pdo', 'pdo_mysql', 'json', 'xml'
];
$extensions_optional = [
'gd' => $locale['step_requirements_warning_player_signatures'],
'zip' => $locale['step_requirements_warning_install_plugins'],
'pdo', 'pdo_mysql', 'xml', 'zip'
];
/*
*
@@ -27,11 +14,11 @@ $extensions_optional = [
function version_check($name, $ok, $info = '', $warning = false)
{
global $failed;
echo '<div class="alert alert-' . ($ok ? 'success' : ($warning ? 'warning' : 'danger')) . '">' . $name;
echo '<p class="' . ($ok ? 'success' : ($warning ? 'warning' : 'error')) . '">' . $name;
if(!empty($info))
echo ': <b>' . $info . '</b>';
echo '</div>';
echo '</p>';
if(!$ok && !$warning)
$failed = true;
}
@@ -40,18 +27,12 @@ $failed = false;
// start validating
version_check($locale['step_requirements_php_version'], (PHP_VERSION_ID >= 50500), PHP_VERSION);
foreach ($dirs_required as $value)
foreach(array('images/guilds', 'images/houses', 'images/gallery') as $value)
{
$is_writable = is_writable(BASE . $value) && (MYAAC_OS != 'WINDOWS' || win_is_writable(BASE . $value));
$is_writable = is_writable(BASE . $value);
version_check($locale['step_requirements_write_perms'] . ': ' . $value, $is_writable);
}
foreach ($dirs_optional as $dir => $errorMsg) {
$is_writable = is_writable(BASE . $dir) && (MYAAC_OS != 'WINDOWS' || win_is_writable(BASE . $dir));
version_check($locale['step_requirements_write_perms'] . ': ' . $dir, $is_writable, $is_writable ? '' : $errorMsg, true);
}
$ini_register_globals = ini_get_bool('register_globals');
version_check('register_long_arrays', !$ini_register_globals, $ini_register_globals ? $locale['on'] : $locale['off']);
@@ -63,19 +44,12 @@ foreach ($extensions_required as $ext) {
version_check(str_replace('$EXTENSION$', strtoupper($ext), $locale['step_requirements_extension']) , $loaded, $loaded ? $locale['loaded'] : $locale['not_loaded']);
}
foreach ($extensions_optional as $ext => $errorMsg) {
$loaded = extension_loaded($ext);
version_check(str_replace('$EXTENSION$', strtoupper($ext), $locale['step_requirements_extension']) , $loaded, $loaded ? $locale['loaded'] : $locale['not_loaded'] . '. ' . $errorMsg, true);
}
echo '<div class="text-center m-3">';
if($failed) {
echo '<div class="alert alert-warning"><span>' . $locale['step_requirements_failed'] . '</span></div>';
if($failed)
{
echo '<br/><b>' . $locale['step_requirements_failed'];
echo next_form(true, false);
}else {
echo next_form(true, true);
}
echo '</div>';
else
echo next_form(true, true);
?>

View File

@@ -21,6 +21,8 @@ if(!$error) {
// user can disable when he wants
$content .= '$config[\'env\'] = \'prod\'; // dev or prod';
$content .= PHP_EOL;
$content .= '$config[\'mail_enabled\'] = true;';
$content .= PHP_EOL;
foreach($_SESSION as $key => $value)
{
if(strpos($key, 'var_') !== false)
@@ -65,6 +67,10 @@ if(!$error) {
error($locale['step_config_mail_admin_error']);
$error = true;
}
if(!Validator::email($_SESSION['var_mail_address'])) {
error($locale['step_config_mail_address_error']);
$error = true;
}
$content .= '$config[\'session_prefix\'] = \'myaac_' . generateRandomString(8, true, false, true, false) . '_\';';
$content .= PHP_EOL;
@@ -76,7 +82,6 @@ if(!$error) {
}
if($saved) {
success($locale['step_database_config_saved']);
if(!$error) {
$_SESSION['saved'] = true;
}
@@ -95,10 +100,8 @@ if(!$error) {
}
?>
<div class="text-center m-3">
<form action="<?php echo BASE_URL; ?>install/" method="post">
<input type="hidden" name="step" id="step" value="admin" />
<?php echo next_buttons(true, $error ? false : true);
?>
</form>
</div>

View File

@@ -1,13 +1,299 @@
@import url('https://fonts.googleapis.com/css2?family=Roboto:wght@100;300;400&display=swap');
* {
margin: 0; padding: 0;
}
body {
font-family: 'Roboto', sans-serif;
text-align: center;
font: 12px Verdana;
color: #000000;
background-color: #000000;
}
img {
border: 0;
}
h1{
font-weight: 100 !important;
.break {
font-size: 0;
width: 0; height: 0;
clear: both;
}
.alignleft {
float: left;
margin: 4px 10px 5px 0;
}
.alignright {
float: right;
margin: 4px 0 5px 10px;
}
.aligncenter {
text-align: center;
}
h3 {
font-weight: 300 !important;
/** BEGIN wrapper **/
#wrapper {
background: #ffffff url(images/background.jpg) repeat-x 0 0;
width: 980px;
}
#header {
margin-bottom: 10px;
border-bottom: 1px solid #eee;
padding-bottom: 15px;
}
#footer {
padding-top: 15px;
border-top: 1px solid #eee;
margin-top: 10px;
text-align: right;
color: #555;
}
#header h1 {
font-weight: bold;
margin: 0;
padding: 0;
}
#header span {
font-size: 25px;
color: #000;
font-weight: bold;
padding-left: 40px;
line-height: 80px;
}
#version {
float: right;
color: #000;
font-size: 17px;
padding-top: 25px;
padding-right: 5px;
}
/** BEGIN body **/
#body {
background: url(images/wrapper.gif) repeat-y 0 0;
}
/** END body **/
/** BEGIN content **/
#content {
width: 642px;
float: left;
padding: 20px 18px 20px 20px;
color: #434242;
}
/** begin headers **/
h1, h2, h3, h4, h5, h6 {
font-family: Tahoma;
margin-bottom: 10px;
}
h2, h3, h4, h5, h6 {
margin-top: 30px;
}
h1 { font-size: 2em; }
h2 { font-size: 1.6em; }
h3 { font-size: 1.3em; }
h4, h5, h6 { font-size: 1em; }
/** end headers **/
/** begin messages **/
.error, .success, .note, .warning {
font-weight: bold;
font-size: 0.9em;
padding: 4px 10px 4px 24px;
background-repeat: no-repeat;
background-position: 5px 6px;
border-style: solid;
border-width: 1px;
line-height: 1.6em;
margin-bottom: 10px;
}
.error {
background-color: #FDD9D9;
background-image: url(images/error.gif);
border-color: #FBA3A3;
color: #D80303;
}
.success {
background-color: #E4FCD9;
background-image: url(images/success.gif);
border-color: #BFFDA3;
color: #35A502;
}
.note {
background-color: #DDEAFA;
background-image: url(images/note.gif);
border-color: #A3D8FD;
color: #026DA5;
}
.warning {
background-color: #FBF0B3;
background-image: url(images/warning.gif);
border-color: #FBBB95;
color: #FD6002;
}
/** end messages **/
/** begin form **/
form {
border: 1px solid #DDDDDD;
padding: 16px;
}
form .input {
padding-top: 12px;
clear: both;
}
form .first {
padding-top: 0;
}
form .input p {
margin-bottom: 7px !important;
}
form input {
margin-right: 5px;
}
form label {
margin-right: 10px;
color: #8B8B8B;
}
form input.text, form textarea {
border: 1px solid #BEBDBD;
font-size: 1em;
font-family: Verdana;
background-color: #F3F3F3;
color: #808080;
padding: 2px;
max-width: 100%;
}
.positive, .negative {
font-size: 0.9em;
font-weight: bold;
padding: 1px 0 0 20px;
background-repeat: no-repeat;
background-position: 0 0;
display: inline;
margin-top: 2px;
}
.positive {
background-image: url(images/positive.gif);
color: #35A502;
}
.negative {
background-image: url(images/negative.gif);
color: #D80303;
}
form textarea {
line-height: 1.6em;
}
form button, form input.button {
font-size: 0.9em;
font-family: Verdana;
font-weight: bold;
color: #ffffff;
background: #B6B4B4 url(images/button.gif) repeat-x 0 0;
border: 1px solid #B6B4B4;
padding: 5px 10px;
}
/** end form **/
/** begin table **/
table {
}
table th {
font-size: 0.9em;
color: #ffffff;
background-color: #679BC5;
padding: 2px 4px;
line-height: 1.6em;
}
table td {
line-height: 1.6em;
padding: 2px 4px;
}
table tr.odd td { background-color: #EEEEEE; }
table tr.even td { background-color: #E5E5E5; }
/** end table **/
/** begin paragraphs, lists, etc. **/
#content p {
line-height: 1.6em;
margin-bottom: 10px;
}
#content ul, #content ol {
list-style-position: inside;
}
#content li {
line-height: 1.6em;
padding: 2px 0 2px 0;
}
a {
color: #679BC5;
}
a:hover {
color: #ff0000;
text-decoration: none;
}
blockquote {
padding: 10px;
background-color: #eeeeee;
line-height: 1.6em;
border-width: 2px 0 1px;
border-style: solid;
border-color: #e0e0e0;
}
/** end paragraphs, lists, etc. **/
/** END content **/
/** BEGIN sidebar **/
#sidebar {
width: 300px;
float: right;
padding: 10px 0;
}
#sidebar h2 {
background: green url(images/sidehead.gif) no-repeat 0 0;
margin: 0 10px;
font-size: 1em;
color: #ffffff;
padding: 7px 10px;
}
#sidebar ul {
list-style-type: none;
background: #E0E0E0 url(images/sidebody.gif) no-repeat 0 bottom;
padding: 10px;
margin: 0 10px 10px;
}
#sidebar ul li {
padding: 4px 0 4px 14px;
background: none;
line-height: 1.6em;
font-size: 0.9em;
font-weight: bold;
}
#sidebar ul li a {
color: #000000;
text-decoration: none;
}
#sidebar ul li a:hover {
text-decoration: none;
color: #ff0000;
}
#sidebar ul li a:active {
text-decoration: none;
color: #ff0000;
}
#sidebar ul li current {
text-decoration: none;
color: #ff0000;
}
.current {
text-decoration: none;
color: #ff0000;
}

View File

@@ -1,74 +1,48 @@
<!DOCTYPE html>
<html dir="<?php echo $locale['direction']; ?>" lang="<?php echo $locale['lang']; ?>" xml:lang="<?php echo $locale['lang']; ?>">
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" dir="<?php echo $locale['direction']; ?>" lang="<?php echo $locale['lang']; ?>" xml:lang="<?php echo $locale['lang']; ?>">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=<?php echo $locale['encoding']; ?>" />
<meta name="viewport" content="width=device-width, initial-scale=1">
<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 rel="stylesheet" type="text/css" href="template/style.css" />
<script type="text/javascript" src="<?php echo BASE_URL; ?>tools/js/jquery.min.js"></script>
</head>
<body>
<div id="body" class="container">
<header id="header" class="pt-5 pb-4 pb-sm-5">
<div id="wrapper">
<!--div class="buffer"-->
<div id="header">
<h1>MyAAC <?php echo $locale['installation']; ?></h1>
</header>
</div>
<div class="row">
<div id="body">
<div id="sidebar" class="col-md-3">
<h3><?php echo $locale['steps']; ?></h3>
<ul class="list-group mt-4">
<div id="sidebar">
<h2><?php echo $locale['steps']; ?></h2>
<ul>
<?php
$i = 0;
foreach($steps as $key => $value){
if ($step == $value) {
$progress = ($i == 6) ? 100 : $i * 16;
}
echo '<li' . ($step == $value ? ' class="list-group-item active"' : ' class="list-group-item"') . '>' . ++$i . '. ' . $locale['step_' . $value] . '</li>';
}
foreach($steps as $key => $value)
echo '<li' . ($step == $value ? ' class="current"' : '') . '>' . ++$i . '. ' . $locale['step_' . $value] . '</li>';
?>
</ul>
</div>
<div id="content" class="col-md-9">
<div id="content">
<?php
if(isset($locale['step_' . $step . '_title']))
echo '<h3 class="mb-4 mt-4 mt-md-0">' . $locale['step_' . $step . '_title'] . '</h3>';
echo '<h1>' . $locale['step_' . $step . '_title'] . '</h1>';
else
echo '<h3 class="mb-4 mt-4 mt-md-0">' . $locale['step_' . $step] . '</h3>';
echo '<h1>' . $locale['step_' . $step] . '</h1>';
echo $content;
?>
<?php
if(!isset($config['installed'])):
?>
<div class="row">
<div class="col-md-12">
<div class="progress mb-2">
<div class="progress-bar progress-bar-striped progress-bar-animated" style="width: <?php echo $progress; ?>%" role="progressbar" aria-valuenow="<?php echo $progress; ?>" aria-valuemin="0" aria-valuemax="100"></div>
</div>
</div>
</div>
<?php endif; ?>
<?php echo $content; ?>
</div>
<div class="break"></div>
</div>
<!--/div-->
</div>
<hr />
</div>
<footer id="footer" class="p-4">
<div id="footer">
<p style="text-align: center;"><?php echo base64_decode('UG93ZXJlZCBieSA8YSBocmVmPSJodHRwOi8vbXktYWFjLm9yZyIgdGFyZ2V0PSJfYmxhbmsiPk15QUFDLjwvYT4='); ?></p>
</footer>
</div>
</body>
</html>

View File

@@ -1,6 +1,4 @@
<?php
define('MYAAC_INSTALL', true);
require_once '../../common.php';
require SYSTEM . 'functions.php';

View File

@@ -1,6 +1,4 @@
<?php
define('MYAAC_INSTALL', true);
require_once '../../common.php';
require SYSTEM . 'functions.php';
@@ -45,9 +43,38 @@ if($success) {
success($locale['step_database_imported_players']);
}
require LIBS . 'DataLoader.php';
DataLoader::setLocale($locale);
DataLoader::load();
require LIBS . 'items.php';
if(Items::loadFromXML())
success($locale['step_database_loaded_items']);
else
error(Items::getError());
require LIBS . 'weapons.php';
if(Weapons::loadFromXML())
success($locale['step_database_loaded_weapons']);
else
error(Weapons::getError());
require LIBS . 'creatures.php';
if(Creatures::loadFromXML()) {
success($locale['step_database_loaded_monsters']);
if(Creatures::getMonstersList()->hasErrors()) {
$locale['step_database_error_monsters'] = str_replace('$LOG$', 'system/logs/error.log', $locale['step_database_error_monsters']);
warning($locale['step_database_error_monsters']);
}
}
else {
error(Creatures::getLastError());
}
require LIBS . 'spells.php';
if(Spells::loadFromXML()) {
success($locale['step_database_loaded_spells']);
}
else {
error(Spells::getLastError());
}
// update config.highscores_ids_hidden
require_once SYSTEM . 'migrations/20.php';

View File

@@ -29,9 +29,8 @@ function performInstall(url) {
}
});
// On completed
ajaxRequest.done(function(/*data*/) {
ajaxRequest.done(function(data) {
$('#spinner').hide();
$('#reload_button').show();
});
// On failed
ajaxRequest.fail(function(error){

285
login.php
View File

@@ -1,285 +0,0 @@
<?php
require_once 'common.php';
require_once 'config.php';
require_once 'config.local.php';
require_once SYSTEM . 'functions.php';
require_once SYSTEM . 'init.php';
require_once SYSTEM . 'status.php';
# error function
function sendError($message, $code = 3){
$ret = [];
$ret['errorCode'] = $code;
$ret['errorMessage'] = $message;
die(json_encode($ret));
}
# event schedule function
function parseEvent($table1, $date, $table2)
{
if ($table1) {
if ($date) {
if ($table2) {
$date = $table1->getAttribute('startdate');
return date_create("{$date}")->format('U');
} else {
$date = $table1->getAttribute('enddate');
return date_create("{$date}")->format('U');
}
} else {
foreach($table1 as $attr) {
if ($attr) {
return $attr->getAttribute($table2);
}
}
}
}
return 'error';
}
$request = json_decode(file_get_contents('php://input'));
$action = $request->type ?? '';
/** @var OTS_Base_DB $db */
/** @var array $config */
switch ($action) {
case 'cacheinfo':
$playersonline = $db->query("select count(*) from `players_online`")->fetchAll();
die(json_encode([
'playersonline' => (intval($playersonline[0][0])),
'twitchstreams' => 0,
'twitchviewer' => 0,
'gamingyoutubestreams' => 0,
'gamingyoutubeviewer' => 0
]));
case 'eventschedule':
$eventlist = [];
$file_path = config('server_path') . 'data/XML/events.xml';
if (!file_exists($file_path)) {
die(json_encode([]));
}
$xml = new DOMDocument;
$xml->load($file_path);
$tmplist = [];
$tableevent = $xml->getElementsByTagName('event');
foreach ($tableevent as $event) {
if ($event) { $tmplist = [
'colorlight' => parseEvent($event->getElementsByTagName('colors'), false, 'colorlight'),
'colordark' => parseEvent($event->getElementsByTagName('colors'), false, 'colordark'),
'description' => parseEvent($event->getElementsByTagName('description'), false, 'description'),
'displaypriority' => intval(parseEvent($event->getElementsByTagName('details'), false, 'displaypriority')),
'enddate' => intval(parseEvent($event, true, false)),
'isseasonal' => getBoolean(intval(parseEvent($event->getElementsByTagName('details'), false, 'isseasonal'))),
'name' => $event->getAttribute('name'),
'startdate' => intval(parseEvent($event, true, true)),
'specialevent' => intval(parseEvent($event->getElementsByTagName('details'), false, 'specialevent'))
];
$eventlist[] = $tmplist; } }
die(json_encode(['eventlist' => $eventlist, 'lastupdatetimestamp' => time()]));
case 'boostedcreature':
$boostDB = $db->query("select * from " . $db->tableName('boosted_creature'))->fetchAll();
foreach ($boostDB as $Tableboost) {
die(json_encode([
'boostedcreature' => true,
'raceid' => intval($Tableboost['raceid'])
]));
}
break;
case 'login':
$port = $config['lua']['gameProtocolPort'];
// default world info
$world = [
'id' => 0,
'name' => $config['lua']['serverName'],
'externaladdress' => $config['lua']['ip'],
'externalport' => $port,
'externaladdressprotected' => $config['lua']['ip'],
'externalportprotected' => $port,
'externaladdressunprotected' => $config['lua']['ip'],
'externalportunprotected' => $port,
'previewstate' => 0,
'location' => 'BRA', // BRA, EUR, USA
'anticheatprotection' => false,
'pvptype' => array_search($config['lua']['worldType'], ['pvp', 'no-pvp', 'pvp-enforced']),
'istournamentworld' => false,
'restrictedstore' => false,
'currenttournamentphase' => 2
];
$characters = [];
$account = new OTS_Account();
$inputEmail = $request->email ?? false;
$inputAccountName = $request->accountname ?? false;
$inputToken = $request->token ?? false;
if ($inputEmail != false) { // login by email
$account->findByEmail($request->email);
}
else if($inputAccountName != false) { // login by account name
$account->find($inputAccountName);
}
$config_salt_enabled = fieldExist('salt', 'accounts');
$current_password = encrypt(($config_salt_enabled ? $account->getCustomField('salt') : '') . $request->password);
if (!$account->isLoaded() || $account->getPassword() != $current_password) {
sendError(($inputEmail != false ? 'Email' : 'Account name') . ' or password is not correct.');
}
//log_append('test.log', var_export($account->getCustomField('secret'), true));
$accountHasSecret = false;
if (fieldExist('secret', 'accounts')) {
$accountSecret = $account->getCustomField('secret');
if ($accountSecret != null && $accountSecret != '') {
$accountHasSecret = true;
if ($inputToken === false) {
sendError('Submit a valid two-factor authentication token.', 6);
} else {
require_once LIBS . 'rfc6238.php';
if (TokenAuth6238::verify($accountSecret, $inputToken) !== true) {
sendError('Two-factor authentication failed, token is wrong.', 6);
}
}
}
}
// common columns
$columns = 'id, name, level, sex, vocation, looktype, lookhead, lookbody, looklegs, lookfeet, lookaddons';
if (fieldExist('isreward', 'accounts')) {
$columns .= ', isreward';
}
if (fieldExist('istutorial', 'accounts')) {
$columns .= ', istutorial';
}
$players = $db->query("select {$columns} from players where account_id = " . $account->getId() . " AND deletion = 0");
if($players && $players->rowCount() > 0) {
$players = $players->fetchAll();
$highestLevelId = 0;
$highestLevel = 0;
foreach ($players as $player) {
if ($player['level'] >= $highestLevel) {
$highestLevel = $player['level'];
$highestLevelId = $player['id'];
}
}
foreach ($players as $player) {
$characters[] = create_char($player, $highestLevelId);
}
}
if (fieldExist('premdays', 'accounts') && fieldExist('lastday', 'accounts')) {
$save = false;
$timeNow = time();
$query = $db->query("select `premdays`, `lastday` from `accounts` where `id` = " . $account->getId());
if ($query->rowCount() > 0) {
$query = $query->fetch();
$premDays = (int)$query['premdays'];
$lastDay = (int)$query['lastday'];
$lastLogin = $lastDay;
} else {
sendError("Error while fetching your account data. Please contact admin.");
}
if ($premDays != 0 && $premDays != PHP_INT_MAX) {
if ($lastDay == 0) {
$lastDay = $timeNow;
$save = true;
} else {
$days = (int)(($timeNow - $lastDay) / 86400);
if ($days > 0) {
if ($days >= $premDays) {
$premDays = 0;
$lastDay = 0;
} else {
$premDays -= $days;
$reminder = ($timeNow - $lastDay) % 86400;
$lastDay = $timeNow - $reminder;
}
$save = true;
}
}
} else if ($lastDay != 0) {
$lastDay = 0;
$save = true;
}
if ($save) {
$db->query("update `accounts` set `premdays` = " . $premDays . ", `lastday` = " . $lastDay . " where `id` = " . $account->getId());
}
}
$worlds = [$world];
$playdata = compact('worlds', 'characters');
$sessionKey = ($inputEmail !== false) ? $inputEmail : $inputAccountName; // email or account name
$sessionKey .= "\n" . $request->password; // password
if (!fieldExist('istutorial', 'players')) {
$sessionKey .= "\n";
}
$sessionKey .= ($accountHasSecret && strlen($accountSecret) > 5) ? $inputToken : '';
// this is workaround to distinguish between TFS 1.x and otservbr
// TFS 1.x requires the number in session key
// otservbr requires just login and password
// so we check for istutorial field which is present in otservbr, and not in TFS
if (!fieldExist('istutorial', 'players')) {
$sessionKey .= "\n".floor(time() / 30);
}
//log_append('slaw.log', $sessionKey);
$session = [
'sessionkey' => $sessionKey,
'lastlogintime' => 0,
'ispremium' => $config['lua']['freePremium'] || $account->isPremium(),
'premiumuntil' => ($account->getPremDays()) > 0 ? (time() + ($account->getPremDays() * 86400)) : 0,
'status' => 'active', // active, frozen or suspended
'returnernotification' => false,
'showrewardnews' => true,
'isreturner' => true,
'fpstracking' => false,
'optiontracking' => false,
'tournamentticketpurchasestate' => 0,
'emailcoderequest' => false
];
die(json_encode(compact('session', 'playdata')));
default:
sendError("Unrecognized event {$action}.");
break;
}
function create_char($player, $highestLevelId) {
global $config;
return [
'worldid' => 0,
'name' => $player['name'],
'ismale' => intval($player['sex']) === 1,
'tutorial' => isset($player['istutorial']) && $player['istutorial'],
'level' => intval($player['level']),
'vocation' => $config['vocations'][$player['vocation']],
'outfitid' => intval($player['looktype']),
'headcolor' => intval($player['lookhead']),
'torsocolor' => intval($player['lookbody']),
'legscolor' => intval($player['looklegs']),
'detailcolor' => intval($player['lookfeet']),
'addonsflags' => intval($player['lookaddons']),
'ishidden' => isset($player['deletion']) && (int)$player['deletion'] === 1,
'istournamentparticipant' => false,
'ismaincharacter' => $highestLevelId == $player['id'],
'dailyrewardstate' => isset($player['isreward']) ? intval($player['isreward']) : 0,
'remainingdailytournamentplaytime' => 0
];
}

View File

@@ -11,7 +11,7 @@ server {
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_read_timeout 240;
fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;
fastcgi_pass unix:/var/run/php/php7.2-fpm.sock;
}
location ~ /\.ht {

View File

@@ -13,7 +13,7 @@ fi
if [ $1 = "prepare" ]; then
# define release version
version=`php system/get_version_for_release.php`
version=`cat VERSION`
echo "Preparing to release version $version of the MyAAC Project!"
@@ -41,7 +41,7 @@ fi
if [ $1 = "pack" ]; then
# define release version
version=`php system/get_version_for_release.php`
version=`cat VERSION`
cd tmp || exit

View File

@@ -76,13 +76,11 @@ $config['clients'] = [
1096,
1097,
1098,
1100,
1102,
1140,
1150,
1180,
1200,
1202,
1215,
@@ -91,12 +89,4 @@ $config['clients'] = [
1240,
1251,
1260,
1270,
1280,
1285,
1286,
1290,
1291,
1300,
];

View File

@@ -1,15 +0,0 @@
<?php
/**
* Compat classes (backward support for Gesior AAC)
*
* @package MyAAC
* @author Slawkens <slawkens@gmail.com>
* @copyright 2022 MyAAC
* @link https://my-aac.org
*/
defined('MYAAC') or die('Direct access not allowed!');
class Player extends OTS_Player {}
class Guild extends OTS_Guild {}
class GuildRank extends OTS_GuildRank {}
class House extends OTS_House {}

View File

@@ -116,4 +116,5 @@ catch(PDOException $error) {
'<li>MySQL is not configured propertly in <i>config.lua</i>.</li>' .
'<li>MySQL server is not running.</li>' .
'</ul>' . $error->getMessage());
}

View File

@@ -39,7 +39,7 @@ function exception_handler($exception) {
// we just replace some values manually
// cause in case Twig throws exception, we can show it too
$content = file_get_contents($template_file);
$content = str_replace(array('{{ BASE_URL }}', '{{ exceptionClass }}', '{{ message }}', '{{ backtrace }}', '{{ powered_by }}'), array(BASE_URL, get_class($exception), $message, $backtrace_formatted, base64_decode('UG93ZXJlZCBieSA8YSBocmVmPSJodHRwOi8vbXktYWFjLm9yZyIgdGFyZ2V0PSJfYmxhbmsiPk15QUFDLjwvYT4=')), $content);
$content = str_replace(array('{{ BASE_URL }}', '{{ message }}', '{{ backtrace }}', '{{ powered_by }}'), array(BASE_URL, $message, $backtrace_formatted, base64_decode('UG93ZXJlZCBieSA8YSBocmVmPSJodHRwOi8vbXktYWFjLm9yZyIgdGFyZ2V0PSJfYmxhbmsiPk15QUFDLjwvYT4=')), $content);
echo $content;
}

View File

@@ -8,7 +8,6 @@
* @link https://my-aac.org
*/
use PHPMailer\PHPMailer\PHPMailer;
use Twig\Loader\ArrayLoader as Twig_ArrayLoader;
defined('MYAAC') or die('Direct access not allowed!');
@@ -24,12 +23,10 @@ function message($message, $type, $return)
return true;
}
if($return) {
// for install and admin pages use bootstrap classes
return '<div class="' . ((defined('MYAAC_INSTALL') || defined('MYAAC_ADMIN')) ? 'alert alert-' : '') . $type . '" style="margin-bottom:10px;">' . $message . '</div>';
}
if($return)
return '<div class="' . $type . '" style="margin-bottom:10px;">' . $message . '</div>';
echo '<div class="' . ((defined('MYAAC_INSTALL') || defined('MYAAC_ADMIN')) ? 'alert alert-' : '') . $type . '" style="margin-bottom:10px;">' . $message . '</div>';
echo '<div class="' . $type . '" style="margin-bottom:10px;">' . $message . '</div>';
return true;
}
function success($message, $return = false) {
@@ -42,9 +39,28 @@ function note($message, $return = false) {
return message($message, 'note', $return);
}
function error($message, $return = false) {
return message($message, ((defined('MYAAC_INSTALL') || defined('MYAAC_ADMIN')) ? 'danger' : 'error'), $return);
return message($message, 'error', $return);
}
function message1($head, $message, $type, $icon , $return)
{//return '<div class="' . $type . '">' . $message . '</div>';
if($return)
return '<div class="alert alert-'.$type.' alert-dismissible"><button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button><h4><i class="icon fa fa-'.$icon.'"></i> '.$head.':</h4>'.$message.'</div>';
echo '<div class="alert alert-'.$type.' alert-dismissible"><button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button><h4><i class="icon fa fa-'.$icon.'"></i> '.$head.':</h4>'.$message.'</div>';
return true;
}
function success1($message, $return = false) {
return message('Info', $message, 'success','success', $return);
}
function warning1($message, $return = false) {
return message('Warning',$message, 'warning','ban', $return);
}
function note1($message, $return = false) {
return message('Info',$message, 'info','info', $return);
}
function error1($message, $return = false) {
return message("Alert", $message, 'danger','check', $return);
}
function longToIp($ip)
{
$exp = explode(".", long2ip($ip));
@@ -96,16 +112,6 @@ function getPlayerLink($name, $generate = true)
return generateLink($url, $name);
}
function getMonsterLink($name, $generate = true)
{
global $config;
$url = BASE_URL . ($config['friendly_urls'] ? '' : '?') . 'creatures/' . urlencode($name);
if(!$generate) return $url;
return generateLink($url, $name);
}
function getHouseLink($name, $generate = true)
{
global $db, $config;
@@ -162,24 +168,7 @@ function getItemImage($id, $count = 1)
$file_name .= '-' . $count;
global $config;
return '<img src="' . $config['item_images_url'] . $file_name . config('item_images_extension') . '"' . $tooltip . ' width="32" height="32" border="0" alt="' .$id . '" />';
}
function getItemRarity($chance) {
if ($chance >= 21) {
return "common";
} elseif (between($chance, 8, 21)) {
return "uncommon";
} elseif (between($chance, 1.1, 8)) {
return "semi rare";
} elseif (between($chance, 0.4, 1.1)) {
return "rare";
} elseif (between($chance, 0.8, 0.4)) {
return "very rare";
} elseif ($chance <= 0.8) {
return "extremely rare";
}
return '';
return '<img src="' . $config['item_images_url'] . $file_name . '.gif"' . $tooltip . ' width="32" height="32" border="0" alt="' .$id . '" />';
}
function getFlagImage($country)
@@ -462,7 +451,7 @@ function tickers()
*/
function template_place_holder($type)
{
global $twig, $template_place_holders;
global $template_place_holders;
$ret = '';
if(array_key_exists($type, $template_place_holders) && is_array($template_place_holders[$type]))
@@ -471,9 +460,6 @@ function template_place_holder($type)
if($type === 'head_start') {
$ret .= template_header();
}
elseif ($type === 'body_start') {
$ret .= $twig->render('browsehappy.html.twig');
}
elseif($type === 'body_end') {
$ret .= template_ga_code();
}
@@ -486,16 +472,33 @@ function template_place_holder($type)
*/
function template_header($is_admin = false)
{
global $title_full, $config, $twig;
global $title_full, $config;
$charset = isset($config['charset']) ? $config['charset'] : 'utf-8';
return $twig->render('templates.header.html.twig',
[
'charset' => $charset,
'title' => $title_full,
'is_admin' => $is_admin
]
);
$ret = '
<meta charset="' . $charset . '">
<meta http-equiv="content-language" content="' . $config['language'] . '" />
<meta http-equiv="content-type" content="text/html; charset=' . $charset . '" />';
if(!$is_admin)
$ret .= '
<base href="' . BASE_URL . '" />
<title>' . $title_full . '</title>';
$ret .= '
<meta name="description" content="' . $config['meta_description'] . '" />
<meta name="keywords" content="' . $config['meta_keywords'] . ', myaac, wodzaac" />
<meta name="generator" content="MyAAC" />
<link rel="stylesheet" type="text/css" href="' . BASE_URL . 'tools/css/messages.css" />
<script type="text/javascript" src="' . BASE_URL . 'tools/js/jquery.min.js"></script>
<noscript>
<div class="warning" style="text-align: center; font-size: 14px;">Your browser does not support JavaScript or its disabled!<br/>
Please turn it on, or be aware that some features on this website will not work correctly.</div>
</noscript>
';
if($config['recaptcha_enabled'])
$ret .= "<script src='https://www.google.com/recaptcha/api.js'></script>";
return $ret;
}
/**
@@ -562,8 +565,10 @@ function template_form()
foreach($templates as $key => $value)
$options .= '<option ' . ($template_name == $value ? 'SELECTED' : '') . '>' . $value . '</option>';
global $twig;
return $twig->render('forms.change_template.html.twig', ['options' => $options]);
return '<form method="get" action="' . BASE_URL . '">
<hidden name="subtopic" value="' . PAGE . '"/>
<select name="template" onchange="this.form.submit()">' . $options . '</select>
</form>';
}
function getStyle($i)
@@ -822,16 +827,13 @@ function getWorldName($id)
*/
function _mail($to, $subject, $body, $altBody = '', $add_html_tags = true)
{
/** @var PHPMailer $mailer */
global $mailer, $config;
if (!config('mail_enabled')) {
log_append('mailer-error.log', '_mail() function has been used, but config.mail_enabled is disabled.');
}
if(!$mailer)
{
require SYSTEM . 'libs/phpmailer/PHPMailerAutoload.php';
$mailer = new PHPMailer();
//$mailer->setLanguage('en', LIBS . 'phpmailer/language/');
$mailer->setLanguage('en', LIBS . 'phpmailer/language/');
}
else {
$mailer->clearAllRecipients();
@@ -1037,7 +1039,7 @@ function getTopPlayers($limit = 5) {
$deleted = 'deletion';
$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`, `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();
if($is_tfs10) {
foreach($players as &$player) {
@@ -1239,254 +1241,6 @@ function getCustomPage($page, &$success)
return $content;
}
function getBanReason($reasonId)
{
switch($reasonId)
{
case 0:
return "Offensive Name";
case 1:
return "Invalid Name Format";
case 2:
return "Unsuitable Name";
case 3:
return "Name Inciting Rule Violation";
case 4:
return "Offensive Statement";
case 5:
return "Spamming";
case 6:
return "Illegal Advertising";
case 7:
return "Off-Topic Public Statement";
case 8:
return "Non-English Public Statement";
case 9:
return "Inciting Rule Violation";
case 10:
return "Bug Abuse";
case 11:
return "Game Weakness Abuse";
case 12:
return "Using Unofficial Software to Play";
case 13:
return "Hacking";
case 14:
return "Multi-Clienting";
case 15:
return "Account Trading or Sharing";
case 16:
return "Threatening Gamemaster";
case 17:
return "Pretending to Have Influence on Rule Enforcement";
case 18:
return "False Report to Gamemaster";
case 19:
return "Destructive Behaviour";
case 20:
return "Excessive Unjustified Player Killing";
case 21:
return "Invalid Payment";
case 22:
return "Spoiling Auction";
}
return "Unknown Reason";
}
function getBanType($typeId)
{
switch($typeId)
{
case 1:
return "IP Banishment";
case 2:
return "Namelock";
case 3:
return "Banishment";
case 4:
return "Notation";
case 5:
return "Deletion";
}
return "Unknown Type";
}
function getChangelogType($v)
{
switch($v) {
case 1:
return 'added';
case 2:
return 'removed';
case 3:
return 'changed';
case 4:
return 'fixed';
}
return 'unknown';
}
function getChangelogWhere($v)
{
switch($v) {
case 1:
return 'server';
case 2:
return 'website';
}
return 'unknown';
}
function getPlayerNameByAccount($id)
{
global $vowels, $ots, $db;
if(is_numeric($id))
{
$player = new OTS_Player();
$player->load($id);
if($player->isLoaded())
return $player->getName();
else
{
$playerQuery = $db->query('SELECT `id` FROM `players` WHERE `account_id` = ' . $id . ' ORDER BY `lastlogin` DESC LIMIT 1;')->fetch();
$tmp = "*Error*";
/*
$acco = new OTS_Account();
$acco->load($id);
if(!$acco->isLoaded())
return "Unknown name";
foreach($acco->getPlayersList() as $p)
{
$player= new OTS_Player();
$player->find($p);*/
$player->load($playerQuery['id']);
//echo 'id gracza = ' . $p . '<br/>';
if($player->isLoaded())
$tmp = $player->getName();
// break;
//}
return $tmp;
}
}
return '';
}
function echo_success($message)
{
echo '<div class="col-12 success mb-2">' . $message . '</div>';
}
function echo_error($message)
{
global $error;
echo '<div class="col-12 error mb-2">' . $message . '</div>';
$error = true;
}
function verify_number($number, $name, $max_length)
{
if (!Validator::number($number))
echo_error($name . ' can contain only numbers.');
$number_length = strlen($number);
if ($number_length <= 0 || $number_length > $max_length)
echo_error($name . ' cannot be longer than ' . $max_length . ' digits.');
}
function Outfits_loadfromXML()
{
global $config;
$file_path = $config['data_path'] . 'XML/outfits.xml';
if (!file_exists($file_path)) { return null; }
$xml = new DOMDocument;
$xml->load($file_path);
$outfits = null;
foreach ($xml->getElementsByTagName('outfit') as $outfit) {
$outfits[] = Outfit_parseNode($outfit);
}
return $outfits;
}
function Outfit_parseNode($node) {
$looktype = (int)$node->getAttribute('looktype');
$type = (int)$node->getAttribute('type');
$lookname = $node->getAttribute('name');
$premium = $node->getAttribute('premium');
$unlocked = $node->getAttribute('unlocked');
$enabled = $node->getAttribute('enabled');
return array('id' => $looktype, 'type' => $type, 'name' => $lookname, 'premium' => $premium, 'unlocked' => $unlocked, 'enabled' => $enabled);
}
function left($str, $length) {
return substr($str, 0, $length);
}
function right($str, $length) {
return substr($str, -$length);
}
function getCreatureImgPath($creature){
$creature_path = config('creatures_images_url');
$creature_gfx_name = trim(strtolower($creature)) . config('creatures_images_extension');
if (!file_exists($creature_path . $creature_gfx_name)) {
$creature_gfx_name = str_replace(" ", "", $creature_gfx_name);
if (file_exists($creature_path . $creature_gfx_name)) {
return $creature_path . $creature_gfx_name;
} else {
return $creature_path . 'nophoto.png';
}
} else {
return $creature_path . $creature_gfx_name;
}
}
function between($x, $lim1, $lim2) {
if ($lim1 < $lim2) {
$lower = $lim1; $upper = $lim2;
}
else {
$lower = $lim2; $upper = $lim1;
}
return (($x >= $lower) && ($x <= $upper));
}
function truncate($string, $length)
{
if (strlen($string) > $length) {
$string = substr($string, 0, $length) . '...';
}
return $string;
}
function getAccountLoginByLabel()
{
$ret = '';
if (config('account_login_by_email')) {
$ret = 'Email Address';
if (config('account_login_by_email_fallback')) {
$ret .= ' or ';
}
}
if (!config('account_login_by_email') || config('account_login_by_email_fallback')) {
$ret .= 'Account ' . (USE_ACCOUNT_NAME ? 'Name' : 'Number');
}
return $ret;
}
// validator functions
require_once LIBS . 'validator.php';
require_once SYSTEM . 'compat/base.php';
// custom functions
require SYSTEM . 'functions_custom.php';
require_once SYSTEM . 'compat.php';

View File

@@ -1,11 +0,0 @@
<?php
/**
* Custom functions
*
* @package MyAAC
* @author Slawkens <slawkens@gmail.com>, Lee
* @copyright 2020 MyAAC
* @link https://my-aac.org
*/
// Insert your custom functions here.

View File

@@ -1,6 +0,0 @@
<?php
require __DIR__ . '/../common.php';
if(IS_CLI) {
echo MYAAC_VERSION;
}

View File

@@ -9,46 +9,40 @@
*/
defined('MYAAC') or die('Direct access not allowed!');
$i = 0;
define('HOOK_STARTUP', ++$i);
define('HOOK_BEFORE_PAGE', ++$i);
define('HOOK_AFTER_PAGE', ++$i);
define('HOOK_FINISH', ++$i);
define('HOOK_TIBIACOM_ARTICLE', ++$i);
define('HOOK_TIBIACOM_BORDER_3', ++$i);
define('HOOK_CHARACTERS_BEFORE_INFORMATIONS', ++$i);
define('HOOK_CHARACTERS_AFTER_INFORMATIONS', ++$i);
define('HOOK_CHARACTERS_BEFORE_SKILLS', ++$i);
define('HOOK_CHARACTERS_AFTER_SKILLS', ++$i);
define('HOOK_CHARACTERS_AFTER_QUESTS', ++$i);
define('HOOK_CHARACTERS_AFTER_EQUIPMENT', ++$i);
define('HOOK_CHARACTERS_BEFORE_DEATHS', ++$i);
define('HOOK_CHARACTERS_BEFORE_SIGNATURE', ++$i);
define('HOOK_CHARACTERS_AFTER_SIGNATURE', ++$i);
define('HOOK_CHARACTERS_AFTER_ACCOUNT', ++$i);
define('HOOK_CHARACTERS_AFTER_CHARACTERS', ++$i);
define('HOOK_LOGIN', ++$i);
define('HOOK_LOGIN_ATTEMPT', ++$i);
define('HOOK_LOGOUT', ++$i);
define('HOOK_ACCOUNT_CREATE_BEFORE_FORM', ++$i);
define('HOOK_ACCOUNT_CREATE_BEFORE_BOXES', ++$i);
define('HOOK_ACCOUNT_CREATE_BETWEEN_BOXES_1', ++$i);
define('HOOK_ACCOUNT_CREATE_BETWEEN_BOXES_2', ++$i);
define('HOOK_ACCOUNT_CREATE_AFTER_BOXES', ++$i);
define('HOOK_ACCOUNT_CREATE_BEFORE_ACCOUNT', ++$i);
define('HOOK_ACCOUNT_CREATE_AFTER_ACCOUNT', ++$i);
define('HOOK_ACCOUNT_CREATE_AFTER_EMAIL', ++$i);
define('HOOK_ACCOUNT_CREATE_AFTER_COUNTRY', ++$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_AFTER_CHARACTER_NAME', ++$i);
define('HOOK_ACCOUNT_CREATE_AFTER_SEX', ++$i);
define('HOOK_ACCOUNT_CREATE_AFTER_VOCATION', ++$i);
define('HOOK_ACCOUNT_CREATE_AFTER_TOWNS', ++$i);
define('HOOK_ACCOUNT_CREATE_BEFORE_SUBMIT_BUTTON', ++$i);
define('HOOK_ACCOUNT_CREATE_AFTER_FORM', ++$i);
define('HOOK_ACCOUNT_CREATE_AFTER_SUBMIT', ++$i);
define('HOOK_STARTUP', 1);
define('HOOK_BEFORE_PAGE', 2);
define('HOOK_AFTER_PAGE', 3);
define('HOOK_FINISH', 4);
define('HOOK_TIBIACOM_ARTICLE', 5);
define('HOOK_TIBIACOM_BORDER_3', 6);
define('HOOK_CHARACTERS_BEFORE_INFORMATIONS', 7);
define('HOOK_CHARACTERS_AFTER_INFORMATIONS', 8);
define('HOOK_CHARACTERS_BEFORE_SIGNATURE', 9);
define('HOOK_CHARACTERS_AFTER_SIGNATURE', 10);
define('HOOK_CHARACTERS_AFTER_ACCOUNT', 11);
define('HOOK_CHARACTERS_AFTER_CHARACTERS', 12);
define('HOOK_LOGIN', 13);
define('HOOK_LOGIN_ATTEMPT', 14);
define('HOOK_LOGOUT', 15);
define('HOOK_ACCOUNT_CREATE_BEFORE_FORM', 16);
define('HOOK_ACCOUNT_CREATE_BEFORE_BOXES', 17);
define('HOOK_ACCOUNT_CREATE_BETWEEN_BOXES_1', 18);
define('HOOK_ACCOUNT_CREATE_BETWEEN_BOXES_2', 19);
define('HOOK_ACCOUNT_CREATE_AFTER_BOXES', 20);
define('HOOK_ACCOUNT_CREATE_BEFORE_ACCOUNT', 21);
define('HOOK_ACCOUNT_CREATE_AFTER_ACCOUNT', 22);
define('HOOK_ACCOUNT_CREATE_AFTER_EMAIL', 23);
define('HOOK_ACCOUNT_CREATE_AFTER_COUNTRY', 24);
define('HOOK_ACCOUNT_CREATE_AFTER_PASSWORDS', 25);
define('HOOK_ACCOUNT_CREATE_AFTER_RECAPTCHA', 26);
define('HOOK_ACCOUNT_CREATE_BEFORE_CHARACTER_NAME', 27);
define('HOOK_ACCOUNT_CREATE_AFTER_CHARACTER_NAME', 28);
define('HOOK_ACCOUNT_CREATE_AFTER_SEX', 29);
define('HOOK_ACCOUNT_CREATE_AFTER_VOCATION', 30);
define('HOOK_ACCOUNT_CREATE_AFTER_TOWNS', 31);
define('HOOK_ACCOUNT_CREATE_BEFORE_SUBMIT_BUTTON', 32);
define('HOOK_ACCOUNT_CREATE_AFTER_FORM', 33);
define('HOOK_ACCOUNT_CREATE_AFTER_SUBMIT', 34);
define('HOOK_FIRST', HOOK_STARTUP);
define('HOOK_LAST', HOOK_ACCOUNT_CREATE_AFTER_SUBMIT);

View File

@@ -127,8 +127,6 @@ $ots = POT::getInstance();
require_once SYSTEM . 'database.php';
define('USE_ACCOUNT_NAME', $db->hasColumn('accounts', 'name'));
define('USE_ACCOUNT_NUMBER', $db->hasColumn('accounts', 'number'));
// load vocation names
$tmp = '';
if($cache->enabled() && $cache->fetch('vocations', $tmp)) {
@@ -159,5 +157,54 @@ else {
}
unset($tmp, $id, $vocation);
require LIBS . 'Towns.php';
Towns::load();
// load towns
/* TODO: doesnt work
ini_set('memory_limit', '-1');
$tmp = '';
if($cache->enabled() && $cache->fetch('towns', $tmp)) {
$config['towns'] = unserialize($tmp);
}
else {
$towns = new OTS_OTBMFile();
$towns->loadFile('D:/Projekty/opentibia/wodzislawski/data/world/wodzislawski.otbm');
$config['towns'] = $towns->getTownsList();
if($cache->enabled()) {
$cache->set('towns', serialize($config['towns']), 120);
}
}
*/
////////////////////////////////////////
// load towns from database (TFS 1.3) //
////////////////////////////////////////
$tmp = '';
$towns = [];
if($cache->enabled() && $cache->fetch('towns', $tmp)) {
$towns = unserialize($tmp);
}
else {
if($db->hasTable('towns')) {
$query = $db->query('SELECT `id`, `name` FROM `towns`;')->fetchAll(PDO::FETCH_ASSOC);
foreach($query as $town) {
$towns[$town['id']] = $town['name'];
}
unset($query);
}
else {
$towns = config('towns');
}
if($cache->enabled()) {
$cache->set('towns', serialize($towns), 600);
}
}
config(['towns', $towns]);
//////////////////////////////////////////////
// END - load towns from database (TFS 1.3) //
//////////////////////////////////////////////

View File

@@ -11,57 +11,6 @@
class CreateCharacter
{
/**
* @param $name
* @param $errors
* @return bool
*/
public function checkName($name, &$errors)
{
$minLength = config('character_name_min_length');
$maxLength = config('character_name_max_length');
if(empty($name)) {
$errors['name'] = 'Please enter a name for your character!';
return false;
}
if(strlen($name) > $maxLength) {
$errors['name'] = 'Name is too long. Max. length <b>' . $maxLength . '</b> letters.';
return false;
}
if(strlen($name) < $minLength) {
$errors['name'] = 'Name is too short. Min. length <b>' . $minLength . '</b> letters.';
return false;
}
$name_length = strlen($name);
if(strspn($name, "qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM- '") != $name_length) {
$errors['name'] = 'This name contains invalid letters, words or format. Please use only a-Z, - , \' and space.';
return false;
}
if(!preg_match("/[A-z ']/", $name)) {
$errors['name'] = 'Your name contains illegal characters.';
return false;
}
if(!admin() && !Validator::newCharacterName($name)) {
$errors['name'] = Validator::getLastError();
return false;
}
$player = new OTS_Player();
$player->find($name);
if($player->isLoaded()) {
$errors['name'] = 'Character with this name already exist.';
return false;
}
return empty($errors);
}
/**
* @param string $name
* @param int $sex
@@ -70,28 +19,37 @@ class CreateCharacter
* @param array $errors
* @return bool
*/
public function check($name, $sex, &$vocation, &$town, &$errors)
{
$this->checkName($name, $errors);
public function check($name, $sex, &$vocation, &$town, &$errors) {
$minLength = config('character_name_min_length');
$maxLength = config('character_name_max_length');
if(empty($sex) && $sex != "0") {
$errors['sex'] = 'Please select the sex for your character!';
if(empty($name))
$errors['name'] = 'Please enter a name for your character!';
else if(strlen($name) > $maxLength)
$errors['name'] = 'Name is too long. Max. length <b>'.$maxLength.'</b> letters.';
else if(strlen($name) < $minLength)
$errors['name'] = 'Name is too short. Min. length <b>'.$minLength.'</b> letters.';
else {
if(!admin() && !Validator::newCharacterName($name)) {
$errors['name'] = Validator::getLastError();
}
}
if(empty($sex) && $sex != "0")
$errors['sex'] = 'Please select the sex for your character!';
if(count(config('character_samples')) > 1)
{
if(!isset($vocation))
$errors['vocation'] = 'Please select a vocation for your character.';
}
else {
else
$vocation = config('character_samples')[0];
}
if(count(config('character_towns')) > 1) {
if(!isset($town)) {
if(!isset($town))
$errors['town'] = 'Please select a town for your character.';
}
}
else {
$town = config('character_towns')[0];
}
@@ -138,7 +96,7 @@ class CreateCharacter
if(empty($errors))
{
$number_of_players_on_account = $account->getPlayersList(false)->count();
$number_of_players_on_account = $account->getPlayersList()->count();
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>!';
}
@@ -193,14 +151,8 @@ class CreateCharacter
$player->setManaSpent($char_to_copy->getManaSpent());
$player->setSoul($char_to_copy->getSoul());
for($skill = POT::SKILL_FIRST; $skill <= POT::SKILL_LAST; $skill++) {
$value = 10;
if (config('use_character_sample_skills')) {
$value = $char_to_copy->getSkill($skill);
}
$player->setSkill($skill, $value);
}
for($skill = POT::SKILL_FIRST; $skill <= POT::SKILL_LAST; $skill++)
$player->setSkill($skill, 10);
$player->setLookBody($char_to_copy->getLookBody());
$player->setLookFeet($char_to_copy->getLookFeet());
@@ -240,22 +192,16 @@ class CreateCharacter
if($db->hasTable('player_skills')) {
for($i=0; $i<7; $i++) {
$value = 10;
if (config('use_character_sample_skills')) {
$value = $char_to_copy->getSkill($i);
}
$skillExists = $db->query('SELECT `skillid` FROM `player_skills` WHERE `player_id` = ' . $player->getId() . ' AND `skillid` = ' . $i);
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().', '.$i.', 10, 0)');
}
}
}
$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) {
$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);");
}
foreach($loaded_items_to_copy as $save_item)
$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']."', '".$save_item['attributes']."');");
global $twig;
$twig->display('success.html.twig', array(

View File

@@ -1,113 +0,0 @@
<?php
/**
* Project: MyAAC
* Automatic Account Creator for Open Tibia Servers
*
* This is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* @package MyAAC
* @author Slawkens <slawkens@gmail.com>
* @copyright 2020 MyAAC
* @link https://my-aac.org
*/
/**
* Class DataLoader
*/
class DataLoader
{
private static $locale;
private static $startTime;
/**
* Load data from server
*/
public static function load()
{
self::$startTime = microtime(true);
require LIBS . 'items.php';
if(Items::loadFromXML()) {
success(self::$locale['step_database_loaded_items'] . self::getLoadedTime());
}
else {
error(Items::getError());
}
self::$startTime = microtime(true);
require LIBS . 'creatures.php';
if(Creatures::loadFromXML()) {
success(self::$locale['step_database_loaded_monsters'] . self::getLoadedTime());
if(Creatures::getMonstersList()->hasErrors()) {
self::$locale['step_database_error_monsters'] = str_replace('$LOG$', 'system/logs/error.log', self::$locale['step_database_error_monsters']);
warning(self::$locale['step_database_error_monsters']);
}
}
else {
error(Creatures::getLastError());
}
self::$startTime = microtime(true);
require_once LIBS . 'npc.php';
if(NPCs::loadFromXML()) {
success(self::$locale['step_database_loaded_npcs'] . self::getLoadedTime());
}
else {
error(self::$locale['step_database_error_npcs']);
}
self::$startTime = microtime(true);
require LIBS . 'spells.php';
if(Spells::loadFromXML()) {
success(self::$locale['step_database_loaded_spells'] . self::getLoadedTime());
}
else {
error(Spells::getLastError());
}
self::$startTime = microtime(true);
if (Towns::save()) {
success(self::$locale['step_database_loaded_towns'] . self::getLoadedTime());
}
else {
warning(self::$locale['step_database_error_towns']);
}
self::$startTime = microtime(true);
require LIBS . 'weapons.php';
if(Weapons::loadFromXML()) {
success(self::$locale['step_database_loaded_weapons'] . self::getLoadedTime());
}
else {
error(Weapons::getError());
}
}
public static function setLocale($locale) {
self::$locale = $locale;
}
private static function getLoadedTime()
{
$endTime = round(microtime(true) - self::$startTime, 3);
return ' (' . str_replace('$TIME$', $endTime, self::$locale['loaded_in_ms']) . ')';
}
}

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;
}
}

1994
system/libs/Parsedown.php Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -1,138 +0,0 @@
<?php
/**
* Project: MyAAC
* Automatic Account Creator for Open Tibia Servers
*
* This is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* @package MyAAC
* @author Slawkens <slawkens@gmail.com>
* @copyright 2020 MyAAC
* @link https://my-aac.org
*/
/**
* Class Towns
*/
class Towns
{
/**
* @var string
*/
private static $filename = CACHE . 'towns.php';
/**
* Determine towns
*
* @return array
*/
public static function determine()
{
global $db;
if($db->hasTable('towns')) {
return self::getFromDatabase();
}
return self::getFromOTBM();
}
/**
* Load cached towns file
*/
public static function load()
{
$towns = config('towns');
if (file_exists(self::$filename)) {
$towns = require self::$filename;
}
config(['towns', $towns]);
}
/**
* Save into cache file
*
* @return bool
*/
public static function save()
{
$towns = self::determine();
if (count($towns) > 0) {
file_put_contents(self::$filename, '<?php return ' . var_export($towns, true) . ';', LOCK_EX);
return true;
}
return false;
}
/**
* Load from OTBM map file
*
* @return array
*/
public static function getFromOTBM()
{
$mapName = configLua('mapName');
if (!isset($mapName)) {
$mapName = configLua('map');
$mapFile = config('server_path') . $mapName;
}
if (strpos($mapName, '.otbm') === false) {
$mapName .= '.otbm';
}
if (!isset($mapFile)) {
$mapFile = config('data_path') . 'world/' . $mapName;
}
if (strpos($mapFile, '.gz') !== false) {
$mapFile = str_replace('.gz', '', $mapFile);
}
$towns = [];
if (file_exists($mapFile)) {
ini_set('memory_limit', '-1');
require LIBS . 'TownsReader.php';
$townsReader = new TownsReader($mapFile);
$townsReader->load();
$towns = $townsReader->get();
}
return $towns;
}
/**
* Load from database
*
* @return array
*/
public static function getFromDatabase()
{
global $db;
$query = $db->query('SELECT `id`, `name` FROM `towns`;')->fetchAll(PDO::FETCH_ASSOC);
$towns = [];
foreach($query as $town) {
$towns[$town['id']] = $town['name'];
}
return $towns;
}
}

View File

@@ -1,82 +0,0 @@
<?php
/*
This file is part of OTSCMS (http://www.otscms.com/) project.
Copyright (C) 2005 - 2007 Wrzasq (wrzasq@gmail.com)
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
/*
This code bases on oryginal OTServ code for .otbm files - file iomapotbm.cpp rev.2141
*/
class TownsReader
{
// node bytes
const ESCAPE_CHAR = 0xFD;
const NODE_START = 0xFE;
// map node types
const OTBM_TOWN = 13;
// file handler
protected $file;
// towns
private $towns = [];
// loads map .otbm file
public function __construct($file)
{
// opens file for reading
$this->file = fopen($file, 'rb');
}
public function load()
{
// checks if file is opened correctly
if ($this->file) {
// skips version
fseek($this->file, 4);
// reads nodes chain
while (!feof($this->file)) {
// reads byte
switch (ord(fgetc($this->file))) {
// maybe a town node
case self::NODE_START:
// reads node type
if (ord(fgetc($this->file)) == self::OTBM_TOWN) {
$id = unpack('L', fread($this->file, 4));
$length = unpack('S', fread($this->file, 2));
// reads town name
$this->towns[$id[1]] = fread($this->file, $length[1]);
}
break;
// escape next character - it might be NODE_START character which is in fact not
case self::ESCAPE_CHAR:
fgetc($this->file);
break;
}
}
}
}
public function get() {
return $this->towns;
}
}

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