Compare commits

...

171 Commits
main ... v0.8.7

Author SHA1 Message Date
slawkens
095ff7963d Update CHANGELOG.md 2022-08-31 19:01:30 +02:00
slawkens
dfb8be07f0 Fix: get_version for release 2022-08-31 18:56:48 +02:00
slawkens
74b4d98bba Update to 0.8.7 2022-08-31 18:45:57 +02:00
slawkens
8a7e4f0132 Update CHANGELOG.md 2022-08-31 18:45:40 +02:00
slawkens
6ebdb0ba89 Update CHANGELOG.md 2022-08-31 18:45:13 +02:00
slawkens
33817e5ab1 Fix undefined notice
Ahh @gpedro ;)
2022-08-31 18:43:42 +02:00
slawkens
cd1b481de5 Delete VERSION 2022-08-16 17:38:50 +02:00
slawkens
ab99db62bd Update version 2022-08-15 20:14:24 +02:00
Gabriel Pedro
dd3d6b3f47
feat: custom words blocked (#190)
* Update config.php

* Update validator.php

* Update config.php
2022-07-30 22:53:19 +02:00
Gabriel Pedro
d99f507244
fix: query blob param escape (#200) 2022-07-30 22:47:44 +02:00
Gabriel Pedro
b6c8a0923f
feat: config use character sample skill (#201) 2022-07-27 10:12:30 +02:00
davi costa
0663b3bbf4
fix guild invite page (#196)
* fix guild invite

* removing var_dump

* sending error
2022-06-05 16:52:22 +02:00
slawkens
d683fce2b9 Fix #171 2022-06-04 21:43:37 +02:00
slawkens
3d56214c07 Fix #195 2022-06-04 20:45:12 +02:00
slawkens
e2575c3612 Don't count deleted players (patched from develop) 2022-05-31 11:54:56 +02:00
slawkens
084256ce01 Comment useless log line 2022-05-16 20:37:36 +02:00
slawkens
240be18367 Update login.php for latest TFS 1.x and otservbr
Works in both.
Thanks for Znote for rfc6238 lib.
2022-05-16 20:31:19 +02:00
slawkens
ac271839a6 Merge branch 'master' of https://github.com/otsoft/myaac 2022-05-16 14:33:53 +02:00
slawkens
734a63f6c3 Fix #191
Allow admin to create GM, God etc. names
2022-05-16 14:33:50 +02:00
thatmichaelguy
e73daedd42
Update change_rank.php (#194) 2022-04-26 21:17:40 +02:00
slawkens
802e6c228c login.php is now part of official repo
Big thanks to folks from OpenTibiaBR Team
Will be updated in next commits to support latest TFS too
2022-04-15 19:34:12 +02:00
slawkens
edf2004539 Fiz wrong path in .gitignore 2022-04-15 19:30:38 +02:00
slawkens
9e949eb32a Fix highscores page bug with high pages 2022-03-16 16:56:03 +01:00
slawkens
e255c35002 Add tables.headline
For future reference
2022-02-26 17:50:50 +01:00
slawkens
dfd3c2c4a5 <div> should not be inside of <table> element 2022-02-26 17:50:31 +01:00
slawkens
876543f064 Fix monsters reloading
Was wrong code applied from develop branch
2022-02-26 17:27:10 +01:00
slawkens
e10f82e0e9 Fix typo 2022-01-07 08:32:37 +01:00
slawkens
f496a48a4d
Add notice about branch for contributions 2022-01-07 08:28:33 +01:00
slawkens
1fbb7c373e Fixes (config.news_author, group_name|capitalize) 2022-01-02 07:31:57 +01:00
slawkens
d58d7f79e7 Save php sessions in myaac dir
Instead of default PHP location
This fixes problem with permissions
2021-12-28 07:28:16 +01:00
slawkens
0643c56bc5
move contributing to wiki 2021-12-27 10:03:10 +01:00
slawkens
c51acf9dbd Add browsehappy code 2021-12-22 07:03:05 +01:00
slawkens
2f2a326eac Revert "Update CHANGELOG.md"
This reverts commit 10dad0fb4e4770ae35178f8cd2749b5349b0bd73.
2021-12-16 20:17:44 +01:00
slawkens
10dad0fb4e Update CHANGELOG.md 2021-12-16 20:17:24 +01:00
slawkens
fe01070bd1
Update README.md 2021-12-07 19:44:55 +01:00
slawkens
b558109844
Update README.md 2021-12-07 19:41:11 +01:00
slawkens
ac37802b7a Typo. 2021-12-04 14:38:17 +01:00
slawkens
f9c8027c3f Fix undefined variable notice 2021-11-04 19:54:27 +01:00
Silic0n Alph4
28dd1969b3
Fix rules page formatting (#177)
The rules page uses a textarea to show lines break.
This commit replaces the textarea and uses the Twig
nl2br function to format the text for web browsers.

Fixes #176
2021-10-30 19:29:36 +02:00
anyeor
50270f6d6f
Update nginx-sample.conf (#175)
Now we prevent access to system directory and update php version.
2021-10-28 21:39:38 +02:00
slawkens
fad80307d8 Revert "Adjustments"
This reverts commit 323d1b0504c5ce9fb83e853b19c1aef700c081ac.
2021-10-23 12:15:58 +02:00
slawkens
323d1b0504 Adjustments 2021-10-23 12:00:52 +02:00
slawkens
d6c1232d2d Update .gitignore 2021-10-23 11:52:20 +02:00
silic0nalph4
678d719036
Fix: admin page changed feet to match body colour (#174)
When saving changes to a character, the admin page
overwrote their foot colour with the body colour.
This fix renders the correct variable into the page
so the foot colour is preserved.
2021-10-20 20:58:28 +02:00
slawkens
723e81e90e Fix: undefined variable notice on database_log enabled 2021-08-30 16:10:54 +02:00
slawkens
60d2cfea99 Fix #169 2021-08-11 22:47:59 +02:00
slawkens
84c39676ee Fix account character create if auto_login is enabled 2021-07-27 18:42:52 +02:00
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 ef2a4082980ef55f811803eff155c1d356465b26.
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 0ba886bc6bc898689e4c0630f724f7c620070981.
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 523afccb51f5e19f0da301e7f475e799d27d5303)
2020-06-03 20:42:52 +02:00
slawkens
a0d38b1f36 Fix #128 (Remove MyISAM engine) from migration scripts
(cherry picked from commit 2c09b0ae8637572dcb4d84e8ed51929092561ee0)
2020-06-03 20:42:41 +02:00
slawkens
6b49ecc99a Fix message() function when executed in CLI
(cherry picked from commit 8de8ad13bf2f0851b958d8fad82ea29938e4e7b2)
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 70bd442bb004f405f117f45787f4c5c357490835)
2020-06-03 20:42:29 +02:00
slawkens
f519784cae Fix #126 (Max count and chance not shown)
(cherry picked from commit 5250b3189b287048a710f78cc7f43174e30e8dee)
2020-06-03 20:42:10 +02:00
slawkens
601cbd5ab7 dummy me.. thanks @gerotib
(cherry picked from commit 2534651e20b50b808c6e043f3516ac4ec4c08585)
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 e2ab3013403075647118441d32000ed8e327caae)
2020-06-03 20:41:53 +02:00
slawkens
bf8d07226e Fix #125 (wrong mana of character samples)
Should be 90.

(cherry picked from commit 700f835243c368d8b9ce2654cc01921e59d16593)
2020-06-03 20:41:36 +02:00
slawkens
fcddfb6adf Remove duplicated code
(cherry picked from commit 9ce7162a045b8544977d78bf3268694861f79380)
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 cd58008a0f667e97122d6c0e3b164df7979ade3f)
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 1f6bd975d08c451ef626da354510ad6b078719b7)
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 dbe83f8a747a792add9045e645f9be78e7a13148)
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 fb326d03545c6403da98da50b37a05e276e11ad0)
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 8e04328482d1888256dd22362332078fb23f6a61)
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 d148b71f0f7559029ac2e6afee0af2bd9493dc8a)
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 4e68838172e8ddfaa20fe4592c66d992f353255f)
2020-06-03 20:35:13 +02:00
slawkens
8d79efd6ad Add system/data to .gitignore
(cherry picked from commit 1799ef42a7ec7d446b922c5a07697c367c60e80f)
2020-06-03 20:34:47 +02:00
slawkens
99bcd54afe Fix cancel change email request
Thanks to OtLand user anyeor

(cherry picked from commit df59b104db5924b26501090901c75096c3538f4b)
2020-06-03 20:34:36 +02:00
slawkens
6ce6eee529 Fix exception when characters.frags enabled on TFS 1.x
(cherry picked from commit ee6e68d0bf9417f3193bcfd4ea2920d8430806db)
2020-06-03 20:34:19 +02:00
slawkens
054b40e358 Add example quest
(cherry picked from commit 7c208b38ed9376044787502a8634c6f099451423)
2020-06-03 20:33:53 +02:00
118 changed files with 1458 additions and 1831 deletions

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

20
.gitignore vendored
View File

@ -1,11 +1,19 @@
Thumbs.db
.DS_Store
.idea
# composer
composer.lock
vendor
# npm
node_modules
# created by release.sh
releases
tmp
releases
config.local.php
PERSONAL_NOTES
# all custom templates
templates/*
@ -23,10 +31,18 @@ system/cache/*
!system/cache/signatures/index.html
!system/cache/plugins/index.html
# php sessions
system/php_sessions/*
!system/php_sessions//index.html
# logs
system/logs/*
!system/logs/index.html
# data
system/data/*
!system/data/index.html
# plugins
plugins/*
!plugins/.htaccess

View File

@ -7,13 +7,14 @@ php:
- 7.2
- 7.3
- 7.4
- 8.0
cache:
directories:
- $HOME/.composer/cache
before_script:
- composer require jakub-onderka/php-parallel-lint --no-suggest --no-progress --no-interaction --no-ansi --quiet --optimize-autoloader
- 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 .
- php vendor/bin/parallel-lint --no-progress --no-colors --exclude vendor --exclude "system/libs/pot/OTS_DB_PDOQuery_PHP71.php" .

View File

@ -1,19 +1,136 @@
# Changelog
## [0.8.2 - x.x.2020]
## [0.8.7 - 31.08.2022]
### Added
* login.php for client 12.x is now part of official repo
* browsehappy code
* config use character sample skill (#201, @gpedro)
* custom words blocked (#190, @gpedro)
### Changed
* save php sessions in myaac dir
* don't count deleted players when creating new character
### Fixed
* patch vulnerability in change_rank.php (#194, @gesior, @thatmichaelguy)
* fix guild invite page (#196, @worthdavi)
* players not showing on highscores page (#195)
* highscores page bug with high pages
* $player->getStorage() does not work at all (#169, @gesior)
* copying sample character when it have items with quotes (#200, @gpedro)
* IPv6 issue when env is set to dev (#171)
* admin page changed feet to match body colour (#174, @silic0nalph4)
* exception being thrown when creating duplicated character name (#191)
* rules page formatting (#177, @silic0nalph4)
* account character create if auto_login is enabled
* undefined variable notice on database_log enabled
* removed VERSION file
## [0.8.6 - 10.07.2021]
This update contains very important security fix.
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
* Updating template menus on template change
* 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
* Fix OTS_House houseid parameter
* 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]

View File

@ -1,18 +1,24 @@
# myaac
# [MyAAC](https://my-aac.org)
[![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)
[![Downloads Count](https://img.shields.io/github/downloads/slawkens/myaac/total)](https://github.com/slawkens/myaac/releases)
[![PHP Versions](https://img.shields.io/travis/php-v/slawkens/myaac/master)](https://github.com/slawkens/myaac/blob/d8b3b4135827ee17e3c6d41f08a925e718c587ed/.travis.yml#L3)
[![OpenTibia Discord](https://img.shields.io/discord/288399552581468162)](https://discord.gg/2J39Wus)
[![Closed Issues](https://img.shields.io/github/issues-closed-raw/slawkens/myaac)](https://github.com/slawkens/myaac/issues?q=is%3Aissue+is%3Aclosed)
MyAAC is a free and open-source Automatic Account Creator (AAC) written in PHP. It is a fork of the [Gesior](https://github.com/gesior/Gesior2012) project. It supports only MySQL databases.
Official website: https://my-aac.org
### Requirements
### REQUIREMENTS
- PHP 5.5 or later
- PHP 5.6 or later
- MySQL database
- PDO PHP Extension
- XML PHP Extension
- ZIP PHP Extension
- (optional) mod_rewrite to use friendly_urls
### INSTALLATION AND CONFIGURATION
### Installation
Just decompress and untar the source (which you should have done by now,
if you're reading this), into your webserver's document root.
@ -32,15 +38,39 @@ Official website: https://my-aac.org
Visit http://your_domain/install (http://localhost/install) and follow instructions in the browser.
### KNOWN PROBLEMS
### Configuration
- none -
Check *config.php* to get more informations.
Use *config.local.php* for your local configuration changes.
### OTHER NOTES
### Branches
If you have a great idea or want contribute to the project - visit our website at https://www.my-aac.org
This repository follows the Git Flow Workflow.
Cheatsheet: [Git-Flow-Cheetsheet](https://danielkummer.github.io/git-flow-cheatsheet)
### LICENSING
That means, we use:
* master branch, for current stable release
* develop branch, for development version (next release)
* feature branches, for features etc.
This program and all associated files are released under the GNU Public
License, see LICENSE for details.
### Known Problems
- Some compatibility issues with some exotical distibutions.
### Contributing
Contributions are more than welcome.
Pull requests should be made to the Dev branch as that is the working branch, master is for release code.
Look: [Contributing](https://github.com/otsoft/myaac/wiki/Contributing) in our wiki.
### Other Notes
If you have a great idea or want contribute to the project - visit our website at https://www.my-aac.org
### License
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.

View File

@ -1 +0,0 @@
0.8.2-dev

View File

@ -27,6 +27,12 @@ define('PAGE', $page);
require SYSTEM . 'functions.php';
require SYSTEM . 'init.php';
if(config('env') === 'dev') {
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);
}
// event system
require_once SYSTEM . 'hooks.php';
$hooks = new Hooks();
@ -34,6 +40,7 @@ $hooks->load();
require SYSTEM . 'status.php';
require SYSTEM . 'login.php';
require SYSTEM . 'migrate.php';
require ADMIN . 'includes/functions.php';
$twig->addGlobal('config', $config);
@ -45,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';

View File

@ -182,7 +182,7 @@ if ($id > 0) {
}
$lastDay = 0;
if($p_days != 0 && $p_days != PHP_INT_MAX ) {
if($p_days != 0 && $p_days != OTS_Account::GRATIS_PREMIUM_DAYS) {
$lastDay = time();
} else if ($lastDay != 0) {
$lastDay = 0;

View File

@ -650,7 +650,7 @@ else if ($id > 0 && isset($player) && $player->isLoaded())
<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(); ?>"
value="<?php echo $player->getLookFeet(); ?>"
class="slider form-control" id="look_feet" name="look_feet">
</div>
</div>
@ -885,11 +885,9 @@ else if ($id > 0 && isset($player) && $player->isLoaded())
var look_feet = $('#look_feet').val();
var look_type = $('#look_type').val();
var look_addons = '';
<?php if($hasLookAddons): ?>
var look_addons = '&addons=' + $('#look_addons').val();
<?php
else: ?>
var look_addons = '';
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;

View File

@ -26,7 +26,7 @@ if ($version_compare == 0) {
success('MyAAC latest version is ' . $myaac_version . '. You\'re using the latest version.
<br/>View CHANGELOG ' . generateLink(ADMIN_URL . '?p=changelog', 'here'));
} else if ($version_compare < 0) {
echo 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 . '.
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=changelog', 'here'));
} else {
warning('You\'re using outdated version.<br/>

View File

@ -23,15 +23,15 @@
* @copyright 2019 MyAAC
* @link https://my-aac.org
*/
if (version_compare(phpversion(), '5.5', '<')) die('PHP version 5.5 or higher is required.');
session_start();
if (version_compare(phpversion(), '5.6', '<')) die('PHP version 5.6 or higher is required.');
define('MYAAC', true);
define('MYAAC_VERSION', '0.8.2-dev');
define('DATABASE_VERSION', 30);
define('MYAAC_VERSION', '0.8.7');
define('DATABASE_VERSION', 33);
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
define('FLAG_ADMIN', 1);
@ -85,6 +85,9 @@ define('TFS_03', 4);
define('TFS_FIRST', TFS_02);
define('TFS_LAST', TFS_03);
session_save_path(SYSTEM . 'php_sessions');
session_start();
// basedir
$basedir = '';
$tmp = explode('/', $_SERVER['SCRIPT_NAME']);
@ -95,23 +98,23 @@ for($i = 1; $i < $size; $i++)
$basedir = str_replace(array('/admin', '/install'), '', $basedir);
define('BASE_DIR', $basedir);
if(isset($_SERVER['HTTP_HOST'][0])) {
$baseHost = $_SERVER['HTTP_HOST'];
}
else {
if(isset($_SERVER['SERVER_NAME'][0])) {
$baseHost = $_SERVER['SERVER_NAME'];
}
else {
$baseHost = $_SERVER['SERVER_ADDR'];
if(!IS_CLI) {
if (isset($_SERVER['HTTP_HOST'][0])) {
$baseHost = $_SERVER['HTTP_HOST'];
} else {
if (isset($_SERVER['SERVER_NAME'][0])) {
$baseHost = $_SERVER['SERVER_NAME'];
} else {
$baseHost = $_SERVER['SERVER_ADDR'];
}
}
define('SERVER_URL', 'http' . (isset($_SERVER['HTTPS'][0]) && strtolower($_SERVER['HTTPS']) === 'on' ? 's' : '') . '://' . $baseHost);
define('BASE_URL', SERVER_URL . BASE_DIR . '/');
define('ADMIN_URL', SERVER_URL . BASE_DIR . '/admin/');
//define('CURRENT_URL', BASE_URL . $_SERVER['REQUEST_URI']);
require SYSTEM . 'exception.php';
}
define('SERVER_URL', 'http' . (isset($_SERVER['HTTPS'][0]) && strtolower($_SERVER['HTTPS']) === 'on' ? 's' : '') . '://' . $baseHost);
define('BASE_URL', SERVER_URL . BASE_DIR . '/');
define('ADMIN_URL', SERVER_URL . BASE_DIR . '/admin/');
//define('CURRENT_URL', BASE_URL . $_SERVER['REQUEST_URI']);
require SYSTEM . 'exception.php';
require SYSTEM . 'autoload.php';

View File

@ -86,8 +86,8 @@ $config = array(
),
// images
'outfit_images_url' => 'http://outfit-images.ots.me/outfit.php', // set to animoutfit.php for animated outfit
'item_images_url' => 'http://item-images.ots.me/1092/', // set to images/items if you host your own items in images folder
'outfit_images_url' => 'https://outfit-images.ots.me/outfit.php', // set to animoutfit.php for animated outfit
'item_images_url' => 'https://item-images.ots.me/1092/', // set to images/items if you host your own items in images folder
// account
'account_management' => true, // disable if you're using other method to manage users (fe. tfs account manager)
@ -151,12 +151,17 @@ $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,
// town list used when creating character
// won't be displayed if there is only one item (rookgaard for example)
'character_towns' => array(1),
// characters lenght
// This is the minimum and the maximum length that a player can create a character. It is highly recommend the maximum lenght be 21.
// characters length
// This is the minimum and the maximum length that a player can create a character. It is highly recommend the maximum length to be 21.
'character_name_min_length' => 4,
'character_name_max_length' => 21,
@ -221,7 +226,10 @@ $config = array(
'frags' => false,
'deleted' => false, // should deleted characters from same account be still listed on the list of characters? When enabled it will show that character is "[DELETED]"
),
'quests' => array(), // quests list (displayed in character view), name => storage
'quests' => array(
//'Some Quest' => 123,
//'Some Quest Two' => 456,
), // quests list (displayed in character view), name => storage
'signature_enabled' => true,
'signature_type' => 'tibian', // signature engine to use: tibian, mango, gesior
'signature_cache_time' => 5, // how long to store cached file (in minutes), default 5 minutes
@ -273,5 +281,13 @@ $config = array(
'date_timezone' => 'Europe/Berlin', // more info at http://php.net/manual/en/timezones.php
'footer_show_load_time' => true, // display load time of the page in the footer
'npc' => array()
'npc' => array(),
// character name blocked
'character_name_blocked' => array(
'prefix' => array(),
'names' => array(),
'words' => array(),
),
);

View File

@ -38,7 +38,7 @@ else
$uri = str_replace(array('index.php/', '?'), '', $uri);
define('URI', $uri);
if(preg_match("/^[A-Za-z0-9-_%\'+]+\.png$/i", $uri)) {
if(preg_match("/^[A-Za-z0-9-_%'+]+\.png$/i", $uri)) {
$tmp = explode('.', $uri);
$_REQUEST['name'] = urldecode($tmp[0]);
@ -48,7 +48,7 @@ if(preg_match("/^[A-Za-z0-9-_%\'+]+\.png$/i", $uri)) {
}
if(preg_match("/^(.*)\.(gif|jpg|png|jpeg|tiff|bmp|css|js|less|map|html|php|zip|rar|gz|ttf|woff|ico)$/i", $_SERVER['REQUEST_URI'])) {
header('HTTP/1.0 404 Not Found');
http_response_code(404);
exit;
}
@ -56,11 +56,17 @@ if(file_exists(BASE . 'config.local.php')) {
require_once BASE . 'config.local.php';
}
ini_set('log_errors', 1);
if(config('env') === 'dev') {
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);
}
else {
ini_set('display_errors', 0);
ini_set('display_startup_errors', 0);
error_reporting(E_ALL & ~E_DEPRECATED & ~E_STRICT);
}
if((!isset($config['installed']) || !$config['installed']) && file_exists(BASE . 'install'))
{
@ -186,26 +192,7 @@ 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.');
}
// database migrations
$tmp = '';
if(fetchDatabaseConfig('database_version', $tmp)) { // we got version
$tmp = (int)$tmp;
if($tmp < DATABASE_VERSION) { // import if older
$db->revalidateCache();
for($i = $tmp + 1; $i <= DATABASE_VERSION; $i++) {
require SYSTEM . 'migrations/' . $i . '.php';
updateDatabaseConfig('database_version', $i);
}
}
}
else { // register first version
registerDatabaseConfig('database_version', 0);
$db->revalidateCache();
for($i = 1; $i <= DATABASE_VERSION; $i++) {
require SYSTEM . 'migrations/' . $i . '.php';
updateDatabaseConfig('database_version', $i);
}
}
require SYSTEM . 'migrate.php';
$hooks->trigger(HOOK_STARTUP);
@ -347,7 +334,7 @@ if($load_it)
}
} else {
$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';

View File

@ -1,3 +1,5 @@
SET @myaac_database_version = 33;
CREATE TABLE `myaac_account_actions`
(
`account_id` INT(11) NOT NULL,
@ -57,6 +59,8 @@ CREATE TABLE `myaac_config`
UNIQUE (`name`)
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8;
INSERT INTO `myaac_config` (`name`, `value`) VALUES ('database_version', @myaac_database_version);
CREATE TABLE `myaac_faq`
(
`id` INT(11) NOT NULL AUTO_INCREMENT,
@ -320,9 +324,9 @@ CREATE TABLE `myaac_spells`
CREATE TABLE `myaac_visitors`
(
`ip` VARCHAR(16) NOT NULL,
`ip` VARCHAR(45) NOT NULL,
`lastvisit` INT(11) NOT NULL DEFAULT 0,
`page` VARCHAR(100) NOT NULL,
`page` VARCHAR(2048) NOT NULL,
UNIQUE (`ip`)
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8;

View File

@ -1,6 +1,10 @@
<?php
defined('MYAAC') or die('Direct access not allowed!');
// configuration
$extensions_required = [
'pdo', 'pdo_mysql', 'xml', 'zip'
];
/*
*
* @param string $name
@ -35,9 +39,11 @@ version_check('register_long_arrays', !$ini_register_globals, $ini_register_glob
$ini_safe_mode = ini_get_bool('safe_mode');
version_check('safe_mode', !$ini_safe_mode, $ini_safe_mode ? $locale['on'] : $locale['off'], true);
version_check(str_replace('$EXTENSION$', 'PDO', $locale['step_requirements_extension']) , extension_loaded('pdo'), extension_loaded('pdo') ? $locale['loaded'] : $locale['not_loaded']);
version_check(str_replace('$EXTENSION$', 'XML', $locale['step_requirements_extension']), extension_loaded('xml'), extension_loaded('xml') ? $locale['loaded'] : $locale['not_loaded']);
version_check(str_replace('$EXTENSION$', 'ZIP', $locale['step_requirements_extension']), extension_loaded('zip'), extension_loaded('zip') ? $locale['loaded'] : $locale['not_loaded']);
foreach ($extensions_required as $ext) {
$loaded = extension_loaded($ext);
version_check(str_replace('$EXTENSION$', strtoupper($ext), $locale['step_requirements_extension']) , $loaded, $loaded ? $locale['loaded'] : $locale['not_loaded']);
}
if($failed)
{

View File

@ -48,7 +48,6 @@ else {
try {
$db->query(file_get_contents(BASE . 'install/includes/schema.sql'));
registerDatabaseConfig('database_version', DATABASE_VERSION);
$locale['step_database_success_schema'] = str_replace('$PREFIX$', TABLE_PREFIX, $locale['step_database_success_schema']);
success($locale['step_database_success_schema']);
}

View File

@ -34,10 +34,10 @@ function insert_sample_if_not_exist($p) {
$success = true;
insert_sample_if_not_exist(array('name' => 'Rook Sample', 'level' => 1, 'vocation_id' => 0, 'health' => 150, 'healthmax' => 150, 'experience' => 0, 'looktype' => 130, 'mana' => 0, 'manamax' => 0, 'soul' => 100, 'cap' => 400));
insert_sample_if_not_exist(array('name' => 'Sorcerer Sample', 'level' => 8, 'vocation_id' => 1, 'health' => 185, 'healthmax' => 185, 'experience' => 4200, 'looktype' => 130, 'mana' => 35, 'manamax' => 35, 'soul' => 100, 'cap' => 470));
insert_sample_if_not_exist(array('name' => 'Druid Sample', 'level' => 8, 'vocation_id' => 2, 'health' => 185, 'healthmax' => 185, 'experience' => 4200, 'looktype' => 130, 'mana' => 35, 'manamax' => 35, 'soul' => 100, 'cap' => 470));
insert_sample_if_not_exist(array('name' => 'Paladin Sample', 'level' => 8, 'vocation_id' => 3, 'health' => 185, 'healthmax' => 185, 'experience' => 4200, 'looktype' => 129, 'mana' => 35, 'manamax' => 35, 'soul' => 100, 'cap' => 470));
insert_sample_if_not_exist(array('name' => 'Knight Sample', 'level' => 8, 'vocation_id' => 4, 'health' => 185, 'healthmax' => 185, 'experience' => 4200, 'looktype' => 131, 'mana' => 35, 'manamax' => 35, 'soul' => 100, 'cap' => 470));
insert_sample_if_not_exist(array('name' => 'Sorcerer Sample', 'level' => 8, 'vocation_id' => 1, 'health' => 185, 'healthmax' => 185, 'experience' => 4200, 'looktype' => 130, 'mana' => 90, 'manamax' => 90, 'soul' => 100, 'cap' => 470));
insert_sample_if_not_exist(array('name' => 'Druid Sample', 'level' => 8, 'vocation_id' => 2, 'health' => 185, 'healthmax' => 185, 'experience' => 4200, 'looktype' => 130, 'mana' => 90, 'manamax' => 90, 'soul' => 100, 'cap' => 470));
insert_sample_if_not_exist(array('name' => 'Paladin Sample', 'level' => 8, 'vocation_id' => 3, 'health' => 185, 'healthmax' => 185, 'experience' => 4200, 'looktype' => 129, 'mana' => 90, 'manamax' => 90, 'soul' => 100, 'cap' => 470));
insert_sample_if_not_exist(array('name' => 'Knight Sample', 'level' => 8, 'vocation_id' => 4, 'health' => 185, 'healthmax' => 185, 'experience' => 4200, 'looktype' => 131, 'mana' => 90, 'manamax' => 90, 'soul' => 100, 'cap' => 470));
if($success) {
success($locale['step_database_imported_players']);
@ -91,6 +91,7 @@ require_once SYSTEM . 'migrations/22.php';
// add myaac_pages pages
require_once SYSTEM . 'migrations/27.php';
require_once SYSTEM . 'migrations/30.php';
$locale['step_finish_desc'] = str_replace('$ADMIN_PANEL$', generateLink(str_replace('tools/', '',ADMIN_URL), $locale['step_finish_admin_panel'], true), $locale['step_finish_desc']);
$locale['step_finish_desc'] = str_replace('$HOMEPAGE$', generateLink(str_replace('tools/', '', BASE_URL), $locale['step_finish_homepage'], true), $locale['step_finish_desc']);

285
login.php Normal file
View File

@ -0,0 +1,285 @@
<?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

@ -1,25 +1,25 @@
server {
listen 80;
root /home/otserv/www/public;
index index.php;
server_name your-domain.com;
listen 80;
root /home/otserv/www/public;
index index.php;
server_name your-domain.com;
location ~ /system {
deny all;
return 404;
}
location / {
try_files $uri $uri/ /index.php;
}
location ~ /\.ht {
deny all;
}
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_read_timeout 240;
fastcgi_pass unix:/var/run/php/php7.2-fpm.sock;
}
location / {
try_files $uri $uri/ /index.php;
}
location ~ /\.ht {
deny all;
}
location /system {
deny all;
return 404;
}
}
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_read_timeout 240;
fastcgi_pass unix:/var/run/php/php7.3-fpm.sock;
}
}

View File

@ -13,16 +13,18 @@ fi
if [ $1 = "prepare" ]; then
# define release version
version=`cat VERSION`
version=`php system/get_version_for_release.php`
echo "Preparing to release version $version of the MyAAC Project!"
# make required directories
mkdir -p releases
mkdir -p tmp
# get myaac from git archive
git archive --format zip --output tmp/myaac.zip master
# make required directories
mkdir -p releases
mkdir -p tmp && cd tmp
cd tmp/ || exit
dir="myaac-$version"
if [ -d "$dir" ] ; then
@ -39,9 +41,9 @@ fi
if [ $1 = "pack" ]; then
# define release version
version=`cat VERSION`
version=`php system/get_version_for_release.php`
cd tmp
cd tmp || exit
# tar.gz
echo "Creating .tar.gz package.."
@ -60,4 +62,4 @@ if [ $1 = "pack" ]; then
echo "Done. Released files can be found in 'releases' directory."
exit
fi
fi

View File

@ -9,7 +9,7 @@
*/
defined('MYAAC') or die('Direct access not allowed!');
$config['clients'] = array(
$config['clients'] = [
710,
740,
750,
@ -54,7 +54,9 @@ $config['clients'] = array(
1000,
1010,
1020,
1021,
1030,
1031,
1034,
1041,
@ -62,6 +64,7 @@ $config['clients'] = array(
1053,
1054,
1058,
1070,
1075,
1077,
1079,
@ -74,5 +77,16 @@ $config['clients'] = array(
1097,
1098,
1100,
);
?>
1102,
1140,
1150,
1180,
1200,
1202,
1215,
1220,
1230,
1240,
1251,
1260,
];

View File

@ -14,11 +14,20 @@ defined('MYAAC') or die('Direct access not allowed!');
function message($message, $type, $return)
{
if($return)
return '<div class="' . $type . '" style="margin-bottom:10px;">' . $message . '</div>';
if(IS_CLI) {
if($return) {
return $message;
}
echo '<div class="' . $type . '" style="margin-bottom:10px;">' . $message . '</div>';
return true;
echo $message;
return true;
}
if($return)
return '<div class="' . $type . '" style="margin-bottom:10px;">' . $message . '</div>';
echo '<div class="' . $type . '" style="margin-bottom:10px;">' . $message . '</div>';
return true;
}
function success($message, $return = false) {
return message($message, 'success', $return);
@ -442,7 +451,7 @@ function tickers()
*/
function template_place_holder($type)
{
global $template_place_holders;
global $twig, $template_place_holders;
$ret = '';
if(array_key_exists($type, $template_place_holders) && is_array($template_place_holders[$type]))
@ -451,6 +460,9 @@ 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();
}
@ -922,6 +934,12 @@ function load_config_lua($filename)
if(count($lines) > 0) {
foreach($lines as $ln => $line)
{
$line = trim($line);
if(@$line[0] === '{' || @$line[0] === '}') {
// arrays are not supported yet
// just ignore the error
continue;
}
$tmp_exp = explode('=', $line, 2);
if(strpos($line, 'dofile') !== false)
{
@ -948,16 +966,17 @@ function load_config_lua($filename)
$result[$key] = (string) substr(substr($value, 1), 0, -1);
elseif(in_array($value, array('true', 'false')))
$result[$key] = ($value === 'true') ? true : false;
elseif(@$value[0] === '{' && @$value[strlen($value) - 1] === '}') {
elseif(@$value[0] === '{') {
// arrays are not supported yet
// just ignore the error
continue;
}
else
{
foreach($result as $tmp_key => $tmp_value) // load values definied by other keys, like: dailyFragsToBlackSkull = dailyFragsToRedSkull
$value = str_replace($tmp_key, $tmp_value, $value);
$ret = @eval("return $value;");
if((string) $ret == '') // = parser error
if((string) $ret == '' && trim($value) !== '""') // = parser error
{
throw new RuntimeException('ERROR: Loading config.lua file. Line <b>' . ($ln + 1) . '</b> of LUA config file is not valid [key: <b>' . $key . '</b>]');
}
@ -982,6 +1001,10 @@ function str_replace_first($search, $replace, $subject) {
}
function get_browser_real_ip() {
if (isset($_SERVER['HTTP_CF_CONNECTING_IP'])) {
$_SERVER['REMOTE_ADDR'] = $_SERVER['HTTP_CF_CONNECTING_IP'];
}
if(isset($_SERVER['REMOTE_ADDR']) && !empty($_SERVER['REMOTE_ADDR']))
return $_SERVER['REMOTE_ADDR'];
else if(isset($_SERVER['HTTP_CLIENT_IP']) && !empty($_SERVER['HTTP_CLIENT_IP']))

View File

@ -0,0 +1,4 @@
<?php
require __DIR__ . '/../common.php';
echo MYAAC_VERSION;

View File

@ -119,6 +119,8 @@ if(!isset($config['highscores_ids_hidden']) || count($config['highscores_ids_hid
$config['highscores_ids_hidden'] = array(0);
}
$config['account_create_character_create'] = config('account_create_character_create') && (!config('mail_enabled') || !config('account_mail_verify'));
// POT
require_once SYSTEM . 'libs/pot/OTS.php';
$ots = POT::getInstance();
@ -140,10 +142,8 @@ else {
if(!@file_exists($file))
$file = $config['data_path'] . 'vocations.xml';
$vocations->load($file);
if(!$vocations)
throw new RuntimeException('ERROR: Cannot load <i>vocations.xml</i> file.');
if(!$vocations->load($file))
throw new RuntimeException('ERROR: Cannot load <i>vocations.xml</i> - the file is malformed. Check the file with xml syntax validator.');
$config['vocations'] = array();
foreach($vocations->getElementsByTagName('vocation') as $vocation) {
@ -180,7 +180,8 @@ else {
// load towns from database (TFS 1.3) //
////////////////////////////////////////
$towns = array();
$tmp = '';
$towns = [];
if($cache->enabled() && $cache->fetch('towns', $tmp)) {
$towns = unserialize($tmp);
}
@ -193,20 +194,14 @@ else {
}
unset($query);
if($cache->enabled()) {
$cache->set('towns', serialize($towns), 600);
}
}
else if($cache->enabled()) {
$cache->set('towns', serialize(array()), 600);
else {
$towns = config('towns');
}
}
$configTowns = config('towns');
if($configTowns !== null && (!isset($configTowns[1]) || $configTowns[1] !== 'Sample town')) {
$towns = array_replace(
$towns, $configTowns
);
if($cache->enabled()) {
$cache->set('towns', serialize($towns), 600);
}
}
config(['towns', $towns]);

View File

@ -11,6 +11,57 @@
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
@ -19,42 +70,27 @@ class CreateCharacter
* @param array $errors
* @return bool
*/
public function check($name, $sex, &$vocation, &$town, &$errors) {
$minLength = config('character_name_min_length');
$maxLength = config('character_name_max_length');
public function check($name, $sex, &$vocation, &$town, &$errors)
{
$this->checkName($name, $errors);
if(empty($name))
$errors['name'] = 'Please enter a name for your character!';
else if(strlen($name) > $maxLength)
$errors['name'] = 'Name is too long. Max. lenght <b>'.$maxLength.'</b> letters.';
else if(strlen($name) < $minLength)
$errors['name'] = 'Name is too short. Min. lenght <b>'.$minLength.'</b> letters.';
else {
if(!admin() && !Validator::newCharacterName($name)) {
$errors['name'] = Validator::getLastError();
}
$exist = new OTS_Player();
$exist->find($name);
if($exist->isLoaded()) {
$errors['name'] = 'Character with this name already exist.';
}
}
if(empty($sex) && $sex != "0")
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];
@ -102,7 +138,7 @@ class CreateCharacter
if(empty($errors))
{
$number_of_players_on_account = $account->getPlayersList()->count();
$number_of_players_on_account = $account->getPlayersList(false)->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>!';
}
@ -120,7 +156,7 @@ class CreateCharacter
return false;
}
global $db, $twig;
global $db;
if($sex == "0")
$char_to_copy->setLookType(136);
@ -157,8 +193,14 @@ class CreateCharacter
$player->setManaSpent($char_to_copy->getManaSpent());
$player->setSoul($char_to_copy->getSoul());
for($skill = POT::SKILL_FIRST; $skill <= POT::SKILL_LAST; $skill++)
$player->setSkill($skill, 10);
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);
}
$player->setLookBody($char_to_copy->getLookBody());
$player->setLookFeet($char_to_copy->getLookFeet());
@ -186,7 +228,7 @@ class CreateCharacter
}
$player->save();
$player->setCustomField("created", time());
$player->setCustomField('created', time());
$player = new OTS_Player();
$player->find($name);
@ -197,18 +239,26 @@ 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.', 10, 0)');
$db->query('INSERT INTO `player_skills` (`player_id`, `skillid`, `value`, `count`) VALUES ('.$player->getId().', '.$i.', ' . $value . ', 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)
$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']."');");
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);");
}
global $twig;
$twig->display('success.html.twig', array(
'title' => 'Character Created',
'description' => 'The character <b>' . $name . '</b> has been created.<br/>
@ -219,4 +269,4 @@ class CreateCharacter
$account->logAction('Created character <b>' . $name . '</b>.');
return true;
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -55,7 +55,12 @@ class InvitesDriver implements IOTS_GuildAction
// invites player to current guild
public function addRequest(OTS_Player $player)
{
$this->db->query('INSERT INTO ' . $this->db->tableName('guild_invites') .' (' . $this->db->fieldName('player_id') . ', ' . $this->db->fieldName('guild_id') . ') VALUES ('.$this->db->quote($player->getId()).', '.$this->db->quote($this->guild->id).')');
$extra_keys = $extra_values = '';
if($this->db->hasColumn('guild_invites', 'date')) {
$extra_keys = ', `date`';
$extra_values = ', '.$this->db->quote(time());
}
$this->db->query('INSERT INTO `guild_invites` (`player_id`, `guild_id`' . $extra_keys . ') VALUES ('.$this->db->quote($player->getId()).', '.$this->db->quote($this->guild->id). $extra_values . ')');
}
// un-invites player

View File

@ -42,6 +42,8 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable
private $data = array('email' => '', 'blocked' => false, 'rlname' => '','location' => '', 'country' => '','web_flags' => 0, 'lastday' => 0, 'premdays' => 0, 'created' => 0);
public static $cache = array();
const GRATIS_PREMIUM_DAYS = 65535;
/**
* Creates new account.
*
@ -185,7 +187,7 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable
}
// SELECT query on database
$this->data = $this->db->query('SELECT `id`, ' . ($this->db->hasColumn('accounts', 'name') ? '`name`,' : '') . '`password`, `email`, `blocked`, `rlname`, `location`, `country`, `web_flags`, ' . ($this->db->hasColumn('accounts', 'premdays') ? '`premdays`, ' : '') . ($this->db->hasColumn('accounts', 'lastday') ? '`lastday`, ' : ($this->db->hasColumn('accounts', 'premend') ? '`premend`,' : '')) . '`created` FROM `accounts` WHERE `id` = ' . (int) $id)->fetch();
$this->data = $this->db->query('SELECT `id`, ' . ($this->db->hasColumn('accounts', 'name') ? '`name`,' : '') . '`password`, `email`, `blocked`, `rlname`, `location`, `country`, `web_flags`, ' . ($this->db->hasColumn('accounts', 'premdays') ? '`premdays`, ' : '') . ($this->db->hasColumn('accounts', 'lastday') ? '`lastday`, ' : ($this->db->hasColumn('accounts', 'premend') ? '`premend`,' : ($this->db->hasColumn('accounts', 'premium_ends_at') ? '`premium_ends_at`,' : ''))) . '`created` FROM `accounts` WHERE `id` = ' . (int) $id)->fetch();
self::$cache[$id] = $this->data;
}
@ -272,6 +274,12 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable
$this->data['premend'] = 0;
}
}
else if($this->db->hasColumn('accounts', 'premium_ends_at')) {
$field = 'premium_ends_at';
if(!isset($this->data['premium_ends_at'])) {
$this->data['premium_ends_at'] = 0;
}
}
// UPDATE query on database
$this->db->exec('UPDATE `accounts` SET ' . ($this->db->hasColumn('accounts', 'name') ? '`name` = ' . $this->db->quote($this->data['name']) . ',' : '') . '`password` = ' . $this->db->quote($this->data['password']) . ', `email` = ' . $this->db->quote($this->data['email']) . ', `blocked` = ' . (int) $this->data['blocked'] . ', `rlname` = ' . $this->db->quote($this->data['rlname']) . ', `location` = ' . $this->db->quote($this->data['location']) . ', `country` = ' . $this->db->quote($this->data['country']) . ', `web_flags` = ' . (int) $this->data['web_flags'] . ', ' . ($this->db->hasColumn('accounts', 'premdays') ? '`premdays` = ' . (int) $this->data['premdays'] . ',' : '') . '`' . $field . '` = ' . (int) $this->data[$field] . ' WHERE `id` = ' . $this->data['id']);
@ -359,12 +367,14 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable
public function getPremDays()
{
if(!isset($this->data['lastday']) && !isset($this->data['premend'])) {
if(!isset($this->data['lastday']) && !isset($this->data['premend']) && !isset($this->data['premium_ends_at'])) {
throw new E_OTS_NotLoaded();
}
if(isset($this->data['premend'])) {
return round(($this->data['premend'] - time()) / (24 * 60 * 60), 2);
if(isset($this->data['premium_ends_at']) || isset($this->data['premend'])) {
$col = isset($this->data['premium_ends_at']) ? 'premium_ends_at' : 'premend';
$ret = ceil(($this->data[$col] - time()) / (24 * 60 * 60));
return $ret > 0 ? $ret : 0;
}
if($this->data['premdays'] == 0) {
@ -372,8 +382,14 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable
}
global $config;
if(isset($config['lua']['freePremium']) && getBoolean($config['lua']['freePremium'])) return -1;
return $this->data['premdays'] - (date("z", time()) + (365 * (date("Y", time()) - date("Y", $this->data['lastday']))) - date("z", $this->data['lastday']));
if(isset($config['lua']['freePremium']) && getBoolean($config['lua']['freePremium'])) return -1;
if($this->data['premdays'] == self::GRATIS_PREMIUM_DAYS){
return self::GRATIS_PREMIUM_DAYS;
}
$ret = ceil($this->data['premdays'] - (date("z", time()) + (365 * (date("Y", time()) - date("Y", $this->data['lastday']))) - date("z", $this->data['lastday'])));
return $ret > 0 ? $ret : 0;
}
public function getLastLogin()
@ -391,6 +407,10 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable
global $config;
if(isset($config['lua']['freePremium']) && getBoolean($config['lua']['freePremium'])) return true;
if(isset($this->data['premium_ends_at'])) {
return $this->data['premium_ends_at'] > time();
}
if(isset($this->data['premend'])) {
return $this->data['premend'] > time();
}
@ -419,6 +439,7 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable
{
$this->data['premdays'] = (int) $premdays;
$this->data['premend'] = time() + ($premdays * 24 * 60 * 60);
$this->data['premium_ends_at'] = time() + ($premdays * 24 * 60 * 60);
}
public function setRLName($name)
@ -712,7 +733,7 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable
* @return OTS_Players_List List of players from current account.
* @throws E_OTS_NotLoaded If account is not loaded.
*/
public function getPlayersList()
public function getPlayersList($withDeleted = true)
{
if( !isset($this->data['id']) )
{
@ -723,6 +744,15 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable
$filter = new OTS_SQLFilter();
$filter->compareField('account_id', (int) $this->data['id']);
if(!$withDeleted) {
global $db;
if($db->hasColumn('players', 'deletion')) {
$filter->compareField('deletion', 0);
} else {
$filter->compareField('deleted', 0);
}
}
// creates list object
$list = new OTS_Players_List();
$list->setFilter($filter);

View File

@ -23,6 +23,7 @@
*/
abstract class OTS_Base_DB extends PDO implements IOTS_DB
{
use OTS_DB_PDOQuery;
/**
* Tables prefix.
*
@ -74,7 +75,7 @@ abstract class OTS_Base_DB extends PDO implements IOTS_DB
return $this->fieldName($this->prefix . $name);
}
public function query($query)
private function doQuery(...$args)
{
$this->queries++;
@ -82,10 +83,10 @@ abstract class OTS_Base_DB extends PDO implements IOTS_DB
$startTime = microtime(true);
}
$ret = parent::query($query);
$ret = parent::query(...$args);
if($this->logged) {
$totalTime = microtime(true) - $startTime;
$this->log .= round($totalTime, 4) . ' ms - ' . $query . PHP_EOL;
$this->log .= round($totalTime, 4) . ' ms - ' . $args[0] . PHP_EOL;
}
return $ret;

View File

@ -0,0 +1,16 @@
<?php
if (PHP_VERSION_ID >= 80000) {
require LIBS . 'pot/OTS_DB_PDOQuery_PHP71.php';
} else {
trait OTS_DB_PDOQuery
{
/**
* @return PDOStatement
*/
public function query()
{
return $this->doQuery(...func_get_args());
}
}
}

View File

@ -0,0 +1,12 @@
<?php
trait OTS_DB_PDOQuery
{
/**
* @return PDOStatement
*/
public function query(?string $query = null, ?int $fetchMode = null, mixed ...$fetchModeArgs)
{
return $this->doQuery($query, $fetchMode, ...$fetchModeArgs);
}
}

View File

@ -57,7 +57,7 @@ class OTS_HousesList implements IteratorAggregate, Countable, ArrayAccess
* @param array $properties List of object properties.
* @throws DOMException On DOM operation error.
*/
public function __set_state($properties)
public static function __set_state($properties)
{
$object = new self();

View File

@ -86,7 +86,7 @@ class OTS_MonstersList implements Iterator, Countable, ArrayAccess
*
* @param array $properties List of object properties.
*/
public function __set_state($properties)
public static function __set_state($properties)
{
$object = new self();

View File

@ -234,12 +234,6 @@ class OTS_Player extends OTS_Row_DAO
$this->data = $this->db->query('SELECT `id`, `name`, `account_id`, `group_id`, `sex`, `vocation`, `experience`, `level`, `maglevel`, `health`, `healthmax`, `mana`, `manamax`, `manaspent`, `soul`, `lookbody`, `lookfeet`, `lookhead`, `looklegs`, `looktype`' . ($this->db->hasColumn('players', 'lookaddons') ? ', `lookaddons`' : '') . ', `posx`, `posy`, `posz`, `cap`, `lastlogin`, `lastlogout`, `lastip`, `save`, `conditions`, `' . $__load['skull_time'] . '` as `skulltime`, `' . $__load['skull_type'] . '` as `skull`' . $__load['guild_info'] . ', `town_id`' . $__load['loss_experience'] . $__load['loss_items'] . ', `balance`' . ($__load['blessings'] ? ', `blessings`' : '') . ($__load['direction'] ? ', `direction`' : '') . ($__load['stamina'] ? ', `stamina`' : '') . ($__load['world_id'] ? ', `world_id`' : '') . ($__load['online'] ? ', `online`' : '') . ', `' . ($__load['deletion'] ? 'deletion' : 'deleted') . '`' . ($__load['promotion'] ? ', `promotion`' : '') . ($__load['marriage'] ? ', `marriage`' : '') . ', `comment`, `created`, `hidden` FROM `players` WHERE `id` = ' . (int)$id)->fetch();
}
if(!isset($this->data['guildnick']))
$this->data['guildnick'] = '';
if(!isset($this->data['rank_id']))
$this->data['rank_id'] = 0;
// loads skills
if( $this->isLoaded() && $load_skills)
{
@ -1917,15 +1911,13 @@ class OTS_Player extends OTS_Row_DAO
* @throws E_OTS_NotLoaded If player is not loaded.
* @deprecated 0.0.4 Use getRank().
*/
public function getRankId()
{
if( !isset($this->data['rank_id']) )
{
throw new E_OTS_NotLoaded();
}
public function getRankId()
{
if(!isset($this->data['guildnick']) || !isset($this->data['rank_id']))
$this->loadRank();
return $this->data['rank_id'];
}
return $this->data['rank_id'];
}
/**
* Assigned guild rank.
@ -2497,7 +2489,7 @@ class OTS_Player extends OTS_Row_DAO
$value = $this->db->query('SELECT ' . $this->db->fieldName('value') . ' FROM ' . $this->db->tableName('player_storage') . ' WHERE ' . $this->db->fieldName('key') . ' = ' . (int) $key . ' AND ' . $this->db->fieldName('player_id') . ' = ' . $this->data['id'])->fetch();
if($value !== false)
if($value === false)
{
return null;
}
@ -3636,4 +3628,4 @@ class OTS_Player extends OTS_Row_DAO
/**#@-*/
?>
?>

View File

@ -69,10 +69,10 @@ class OTS_SpellsList implements IteratorAggregate, Countable
* <p>
* Allows object importing from {@link http://www.php.net/manual/en/function.var-export.php var_export()}.
* </p>
*
*
* @param array $properties List of object properties.
*/
public function __set_state($properties)
public static function __set_state($properties)
{
$object = new self();

View File

@ -59,7 +59,7 @@ class OTS_VocationsList implements IteratorAggregate, Countable, ArrayAccess
* @param array $properties List of object properties.
* @throws DOMException On DOM operation error.
*/
public function __set_state($properties)
public static function __set_state($properties)
{
$object = new self();

View File

@ -1,85 +0,0 @@
<?php
/**#@+
* @version 0.0.2
* @since 0.0.2
*/
/**
* POT compatibility assurance package.
*
* This package makes you sure that POT scripts won't cause FATAL errors on PHP older PHP 5.x versions. However remember that some PHP features won't be enabled with it. For example if you have PHP 5.0.x, this package will define Countable interface for you so PHP will know it, but it won't allow you to use count($countableObject) structure.
*
* Note that you need to include this file before any other POT file or they will cause FATAL errors.
*
* @package POT
* @version 0.1.2
* @subpackage compat
* @author Wrzasq <wrzasq@gmail.com>
* @copyright 2007 - 2008 (C) by Wrzasq
* @license http://www.gnu.org/licenses/lgpl-3.0.txt GNU Lesser General Public License, Version 3
* @tutorial POT/PHP_5.0.pkg
*/
// OutOfBoundsException class for 5.0.x
if( !class_exists('OutOfBoundsException') )
{
/**
* @ignore
* @version 0.1.0
* @since 0.1.0
*/
class OutOfBoundsException extends Exception
{
}
}
// LogicException class for 5.0.x
if( !class_exists('LogicException') )
{
/**
* @ignore
* @version 0.1.2
* @since 0.1.2
*/
class LogicException extends Exception
{
}
}
// Countable for PHP 5.0.x
if( !interface_exists('Countable') )
{
/**
* @ignore
*/
interface Countable
{
public function count();
}
}
// spl_autoload_register() walkaround
if( !function_exists('spl_autoload_register') )
{
/**
* @ignore
*/
function spl_autoload_register($callback)
{
if( !function_exists('__autoload') )
{
/**
* @ignore
*/
function __autoload($class)
{
POT::getInstance()->loadClass($class);
}
}
}
}
/**#@-*/
?>

285
system/libs/rfc6238.php Normal file
View File

@ -0,0 +1,285 @@
<?php
/** https://github.com/Voronenko/PHPOTP/blob/08cda9cb9c30b7242cf0b3a9100a6244a2874927/code/base32static.php
* Encode in Base32 based on RFC 4648.
* Requires 20% more space than base64
* Great for case-insensitive filesystems like Windows and URL's (except for = char which can be excluded using the pad option for urls)
*
* @package default
* @author Bryan Ruiz
**/
class Base32Static {
private static $map = array(
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', // 7
'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', // 15
'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', // 23
'Y', 'Z', '2', '3', '4', '5', '6', '7', // 31
'=' // padding character
);
private static $flippedMap = array(
'A'=>'0', 'B'=>'1', 'C'=>'2', 'D'=>'3', 'E'=>'4', 'F'=>'5', 'G'=>'6', 'H'=>'7',
'I'=>'8', 'J'=>'9', 'K'=>'10', 'L'=>'11', 'M'=>'12', 'N'=>'13', 'O'=>'14', 'P'=>'15',
'Q'=>'16', 'R'=>'17', 'S'=>'18', 'T'=>'19', 'U'=>'20', 'V'=>'21', 'W'=>'22', 'X'=>'23',
'Y'=>'24', 'Z'=>'25', '2'=>'26', '3'=>'27', '4'=>'28', '5'=>'29', '6'=>'30', '7'=>'31'
);
/**
* Use padding false when encoding for urls
*
* @return base32 encoded string
* @author Bryan Ruiz
**/
public static function encode($input, $padding = true) {
if(empty($input)) return "";
$input = str_split($input);
$binaryString = "";
for($i = 0; $i < count($input); $i++) {
$binaryString .= str_pad(base_convert(ord($input[$i]), 10, 2), 8, '0', STR_PAD_LEFT);
}
$fiveBitBinaryArray = str_split($binaryString, 5);
$base32 = "";
$i=0;
while($i < count($fiveBitBinaryArray)) {
$base32 .= self::$map[base_convert(str_pad($fiveBitBinaryArray[$i], 5,'0'), 2, 10)];
$i++;
}
if($padding && ($x = strlen($binaryString) % 40) != 0) {
if($x == 8) $base32 .= str_repeat(self::$map[32], 6);
else if($x == 16) $base32 .= str_repeat(self::$map[32], 4);
else if($x == 24) $base32 .= str_repeat(self::$map[32], 3);
else if($x == 32) $base32 .= self::$map[32];
}
return $base32;
}
public static function decode($input) {
if(empty($input)) return;
$paddingCharCount = substr_count($input, self::$map[32]);
$allowedValues = array(6,4,3,1,0);
if(!in_array($paddingCharCount, $allowedValues)) return false;
for($i=0; $i<4; $i++){
if($paddingCharCount == $allowedValues[$i] &&
substr($input, -($allowedValues[$i])) != str_repeat(self::$map[32], $allowedValues[$i])) return false;
}
$input = str_replace('=','', $input);
$input = str_split($input);
$binaryString = "";
for($i=0; $i < count($input); $i = $i+8) {
$x = "";
if(!in_array($input[$i], self::$map)) return false;
for($j=0; $j < 8; $j++) {
$x .= str_pad(base_convert(@self::$flippedMap[@$input[$i + $j]], 10, 2), 5, '0', STR_PAD_LEFT);
}
$eightBits = str_split($x, 8);
for($z = 0; $z < count($eightBits); $z++) {
$binaryString .= ( ($y = chr(base_convert($eightBits[$z], 2, 10))) || ord($y) == 48 ) ? $y:"";
}
}
return $binaryString;
}
}
// http://www.faqs.org/rfcs/rfc6238.html
// https://github.com/Voronenko/PHPOTP/blob/08cda9cb9c30b7242cf0b3a9100a6244a2874927/code/rfc6238.php
// Local changes: http -> https, consistent indentation, 200x200 -> 300x300 QR image size, PHP end tag
class TokenAuth6238 {
/**
* verify
*
* @param string $secretkey Secret clue (base 32).
* @return bool True if success, false if failure
*/
public static function verify($secretkey, $code, $rangein30s = 3) {
$key = base32static::decode($secretkey);
$unixtimestamp = time()/30;
for($i=-($rangein30s); $i<=$rangein30s; $i++) {
$checktime = (int)($unixtimestamp+$i);
$thiskey = self::oath_hotp($key, $checktime);
if ((int)$code == self::oath_truncate($thiskey,6)) {
return true;
}
}
return false;
}
public static function getTokenCode($secretkey,$rangein30s = 3) {
$result = "";
$key = base32static::decode($secretkey);
$unixtimestamp = time()/30;
for($i=-($rangein30s); $i<=$rangein30s; $i++) {
$checktime = (int)($unixtimestamp+$i);
$thiskey = self::oath_hotp($key, $checktime);
$result = $result." # ".self::oath_truncate($thiskey,6);
}
return $result;
}
public static function getTokenCodeDebug($secretkey,$rangein30s = 3) {
$result = "";
print "<br/>SecretKey: $secretkey <br/>";
$key = base32static::decode($secretkey);
print "Key(base 32 decode): $key <br/>";
$unixtimestamp = time()/30;
print "UnixTimeStamp (time()/30): $unixtimestamp <br/>";
for($i=-($rangein30s); $i<=$rangein30s; $i++) {
$checktime = (int)($unixtimestamp+$i);
print "Calculating oath_hotp from (int)(unixtimestamp +- 30sec offset): $checktime basing on secret key<br/>";
$thiskey = self::oath_hotp($key, $checktime, true);
print "======================================================<br/>";
print "CheckTime: $checktime oath_hotp:".$thiskey."<br/>";
$result = $result." # ".self::oath_truncate($thiskey,6,true);
}
return $result;
}
public static function getBarCodeUrl($username, $domain, $secretkey, $issuer) {
$url = "https://chart.apis.google.com/chart";
$url = $url."?chs=300x300&chld=M|0&cht=qr&chl=otpauth://totp/";
$url = $url.$username . "@" . $domain . "%3Fsecret%3D" . $secretkey . '%26issuer%3D' . rawurlencode($issuer);
return $url;
}
public static function generateRandomClue($length = 16) {
$b32 = "234567QWERTYUIOPASDFGHJKLZXCVBNM";
$s = "";
for ($i = 0; $i < $length; $i++)
$s .= $b32[rand(0,31)];
return $s;
}
private static function hotp_tobytestream($key) {
$result = array();
$last = strlen($key);
for ($i = 0; $i < $last; $i = $i + 2) {
$x = $key[$i] + $key[$i + 1];
$x = strtoupper($x);
$x = hexdec($x);
$result = $result.chr($x);
}
return $result;
}
private static function oath_hotp ($key, $counter, $debug=false) {
$result = "";
$orgcounter = $counter;
$cur_counter = array(0,0,0,0,0,0,0,0);
if ($debug) {
print "Packing counter $counter (".dechex($counter).")into binary string - pay attention to hex representation of key and binary representation<br/>";
}
for($i=7;$i>=0;$i--) { // C for unsigned char, * for repeating to the end of the input data
$cur_counter[$i] = pack ('C*', $counter);
if ($debug) {
print $cur_counter[$i]."(".dechex(ord($cur_counter[$i])).")"." from $counter <br/>";
}
$counter = $counter >> 8;
}
if ($debug) {
foreach ($cur_counter as $char) {
print ord($char) . " ";
}
print "<br/>";
}
$binary = implode($cur_counter);
// Pad to 8 characters
str_pad($binary, 8, chr(0), STR_PAD_LEFT);
if ($debug) {
print "Prior to HMAC calculation pad with zero on the left until 8 characters.<br/>";
print "Calculate sha1 HMAC(Hash-based Message Authentication Code http://en.wikipedia.org/wiki/HMAC).<br/>";
print "hash_hmac ('sha1', $binary, $key)<br/>";
}
$result = hash_hmac ('sha1', $binary, $key);
if ($debug) {
print "Result: $result <br/>";
}
return $result;
}
private static function oath_truncate($hash, $length = 6, $debug=false) {
$result="";
// Convert to dec
if($debug) {
print "converting hex hash into characters<br/>";
}
$hashcharacters = str_split($hash,2);
if($debug) {
print_r($hashcharacters);
print "<br/>and convert to decimals:<br/>";
}
for ($j=0; $j<count($hashcharacters); $j++) {
$hmac_result[]=hexdec($hashcharacters[$j]);
}
if($debug) {
print_r($hmac_result);
}
// http://php.net/manual/ru/function.hash-hmac.php
// adopted from brent at thebrent dot net 21-May-2009 08:17 comment
$offset = $hmac_result[19] & 0xf;
if($debug) {
print "Calculating offset as 19th element of hmac:".$hmac_result[19]."<br/>";
print "offset:".$offset;
}
$result = (
(($hmac_result[$offset+0] & 0x7f) << 24 ) |
(($hmac_result[$offset+1] & 0xff) << 16 ) |
(($hmac_result[$offset+2] & 0xff) << 8 ) |
($hmac_result[$offset+3] & 0xff)
) % pow(10,$length);
return $result;
}
}
?>

View File

@ -85,7 +85,13 @@ class Validator
return false;
}
if(!preg_match("/[A-Z0-9]/i", $name))
if(preg_match('/ {2,}/', $name))
{
self::$lastError = 'Invalid account name format. Use only A-Z and numbers 0-9 and no double spaces.';
return false;
}
if(!preg_match("/^[A-Z0-9]+$/i", $name))
{
self::$lastError = 'Invalid account name format. Use only A-Z and numbers 0-9.';
return false;
@ -133,18 +139,8 @@ class Validator
return false;
}
if (strlen($password) < 8 || strlen($password) > 30) {
self::$lastError = 'The password must have at least 8 and maximum 30 letters!';
return false;
}
if(strspn($password, "qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM1234567890") != strlen($password)) {
self::$lastError = 'Password contains illegal letters (a-z, A-Z and 0-9 only!).';
return false;
}
if(!ctype_alnum($password)) {
self::$lastError = 'Password contains illegal letters (a-z, A-Z and 0-9 only!).';
if (strlen($password) < 8 || strlen($password) > 29) {
self::$lastError = 'The password must have at least 8 and maximum 29 letters!';
return false;
}
@ -154,7 +150,7 @@ class Validator
}
if(!preg_match('/[0-9]/', $password)) {
self::$lastError = 'The password must contain at least one letter other than A-Z or a-z!';
self::$lastError = 'The password must contain at least one number!';
return false;
}
@ -179,13 +175,13 @@ class Validator
$length = strlen($name);
if($length < 3)
{
self::$lastError = 'Character name is too short. Min. lenght <b>3</b> characters.';
self::$lastError = 'Character name is too short. Min. length <b>3</b> characters.';
return false;
}
if($length > 25)
{
self::$lastError = 'Character name is too long. Max. lenght <b>25</b> characters.';
self::$lastError = 'Character name is too long. Max. length <b>25</b> characters.';
return false;
}
@ -194,6 +190,13 @@ class Validator
self::$lastError = "Invalid name format. Use only A-Z, spaces and '.";
return false;
}
if(preg_match('/ {2,}/', $name))
{
self::$lastError = 'Invalid character name format. Use only A-Z and numbers 0-9 and no double spaces.';
return false;
}
if(!preg_match("/[A-z ']/", $name))
{
self::$lastError = "Invalid name format. Use only A-Z, spaces and '.";
@ -215,8 +218,12 @@ class Validator
global $db, $config;
$name_lower = strtolower($name);
$custom_first_words_blocked = [];
if (isset($config['character_name_blocked']['prefix']) && $config['character_name_blocked']['prefix']) {
$custom_first_words_blocked = $config['character_name_blocked']['prefix'];
}
$first_words_blocked = array('admin ', 'administrator ', 'gm ', 'cm ', 'god ','tutor ', "'", '-');
$first_words_blocked = array_merge($custom_first_words_blocked, array('admin ', 'administrator ', 'gm ', 'cm ', 'god ','tutor ', "'", '-'));
foreach($first_words_blocked as $word)
{
if($word == substr($name_lower, 0, strlen($word))) {
@ -240,12 +247,22 @@ class Validator
return false;
}
if(preg_match('/ {2,}/', $name))
{
self::$lastError = 'Invalid character name format. Use only A-Z and numbers 0-9 and no double spaces.';
return false;
}
if(strtolower($config['lua']['serverName']) == $name_lower) {
self::$lastError = 'Your name cannot be same as server name.';
return false;
}
$names_blocked = array('admin', 'administrator', 'gm', 'cm', 'god', 'tutor');
$custom_names_blocked = [];
if (isset($config['character_name_blocked']['names']) && $config['character_name_blocked']['names']) {
$custom_names_blocked = $config['character_name_blocked']['names'];
}
$names_blocked = array_merge($custom_names_blocked, array('admin', 'administrator', 'gm', 'cm', 'god', 'tutor'));
foreach($names_blocked as $word)
{
if($word == $name_lower) {
@ -254,7 +271,11 @@ class Validator
}
}
$words_blocked = array('admin', 'administrator', 'gamemaster', 'game master', 'game-master', "game'master", '--', "''","' ", " '", '- ', ' -', "-'", "'-", 'fuck', 'sux', 'suck', 'noob', 'tutor');
$custom_words_blocked = [];
if (isset($config['character_name_blocked']['words']) && $config['character_name_blocked']['words']) {
$custom_words_blocked = $config['character_name_blocked']['words'];
}
$words_blocked = array_merge($custom_words_blocked, array('admin', 'administrator', 'gamemaster', 'game master', 'game-master', "game'master", '--', "''","' ", " '", '- ', ' -', "-'", "'-", 'fuck', 'sux', 'suck', 'noob', 'tutor'));
foreach($words_blocked as $word)
{
if(!(strpos($name_lower, $word) === false)) {
@ -272,14 +293,6 @@ class Validator
}
}
for($i = 0; $i < $name_length; $i++)
{
if(isset($name_lower[$i - 1]) && $name_lower[$i - 1] == ' ' && isset($name_lower[$i + 1]) && $name_lower[$i + 1] == ' ') {
self::$lastError = 'Your name contains too many spaces.';
return false;
}
}
$player = new OTS_Player();
$player->find($name);
if($player->isLoaded()) {
@ -322,22 +335,6 @@ class Validator
}
}
if(strspn($name, "qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM- '") != $name_length) {
self::$lastError = 'This name contains invalid letters, words or format. Please use only a-Z, - , \' and space.';
return false;
}
if($name_length < 3 || $name_length > 28) {
self::$lastError = 'Your name cannot be shorter than 3 characters and longer than 28 characters.';
return false;
}
if(!preg_match("/[A-z ']{3,28}/", $name)) {
self::$lastError = 'Your name containst illegal characters.';
return false;
}
return true;
}

22
system/migrate.php Normal file
View File

@ -0,0 +1,22 @@
<?php
// database migrations
$tmp = '';
if(fetchDatabaseConfig('database_version', $tmp)) { // we got version
$tmp = (int)$tmp;
if($tmp < DATABASE_VERSION) { // import if older
$db->revalidateCache();
for($i = $tmp + 1; $i <= DATABASE_VERSION; $i++) {
require SYSTEM . 'migrations/' . $i . '.php';
updateDatabaseConfig('database_version', $i);
}
}
}
else { // register first version
registerDatabaseConfig('database_version', 0);
$db->revalidateCache();
for($i = 1; $i <= DATABASE_VERSION; $i++) {
require SYSTEM . 'migrations/' . $i . '.php';
updateDatabaseConfig('database_version', $i);
}
}

View File

@ -10,7 +10,7 @@
`type` INT(2) NOT NULL DEFAULT 0,
`file` VARCHAR(100) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE = MyISAM;
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8;
");
?>

View File

@ -1,7 +1,7 @@
<?php
if(!$db->hasColumn(TABLE_PREFIX . 'hooks', 'ordering'))
$db->query("ALTER TABLE `" . TABLE_PREFIX . "hooks` ADD `ordering` INT(11) NOT NULL DEFAULT 0 AFTER `file`;");
if(!$db->hasTable(TABLE_PREFIX . 'admin_menu'))
$db->query("
CREATE TABLE `myaac_admin_menu`
@ -13,5 +13,5 @@ CREATE TABLE `myaac_admin_menu`
`flags` INT(11) NOT NULL DEFAULT 0,
`enabled` INT(1) NOT NULL DEFAULT 1,
PRIMARY KEY (`id`)
) ENGINE = MyISAM;");
?>
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8;
");

View File

@ -22,7 +22,8 @@ CREATE TABLE `" . TABLE_PREFIX . "items`
`plural` VARCHAR(50) NOT NULL DEFAULT '',
`attributes` VARCHAR(500) NOT NULL DEFAULT '',
PRIMARY KEY (`id`)
) ENGINE = MyISAM;");
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8;
");
// new weapons table
if(!$db->hasTable(TABLE_PREFIX . 'weapons'))
@ -34,7 +35,8 @@ CREATE TABLE `" . TABLE_PREFIX . "weapons`
`maglevel` INT(11) NOT NULL DEFAULT 0,
`vocations` VARCHAR(100) NOT NULL DEFAULT '',
PRIMARY KEY (`id`)
) ENGINE = MyISAM;");
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8;
");
// modify vocations to support json data
$db->query("ALTER TABLE `" . TABLE_PREFIX . "spells` MODIFY `vocations` VARCHAR(100) NOT NULL DEFAULT '';");

View File

@ -12,8 +12,9 @@ CREATE TABLE `myaac_menu`
`ordering` INT(11) NOT NULL DEFAULT 0,
`enabled` INT(1) NOT NULL DEFAULT 1,
PRIMARY KEY (`id`)
) ENGINE = MyISAM;");
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8;
");
$db->query("
/* MENU_CATEGORY_NEWS kathrine */
INSERT INTO `myaac_menu` (`template`, `name`, `link`, `category`, `ordering`) VALUES ('kathrine', 'Latest News', 'news', 1, 0);

View File

@ -11,7 +11,8 @@ CREATE TABLE `z_polls` (
`answers` int(11) NOT NULL DEFAULT 0,
`votes_all` int(11) NOT NULL DEFAULT 0,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;');
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8;
');
if(!$db->hasTable('z_polls_answers'))
$db->query('
@ -20,7 +21,8 @@ $db->query('
`answer_id` int(11) NOT NULL,
`answer` varchar(255) NOT NULL,
`votes` int(11) NOT NULL DEFAULT 0
) ENGINE=MyISAM DEFAULT CHARSET=latin1;');
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8;
');
if(!$db->hasColumn('accounts', 'vote'))
$db->query('ALTER TABLE `accounts` ADD `vote` INT( 11 ) DEFAULT 0 NOT NULL ;');

18
system/migrations/31.php Normal file
View File

@ -0,0 +1,18 @@
<?php
if(!$db->hasColumn(TABLE_PREFIX . 'monsters', 'elements')) {
$db->exec("ALTER TABLE `" . TABLE_PREFIX . "monsters` ADD `elements` TEXT NOT NULL AFTER `immunities`;");
$db->exec("ALTER TABLE `" . TABLE_PREFIX . "monsters` ADD `pushable` TINYINT(1) NOT NULL DEFAULT '0' AFTER `convinceable`;");
$db->exec("ALTER TABLE `" . TABLE_PREFIX . "monsters` ADD `canpushitems` TINYINT(1) NOT NULL DEFAULT '0' AFTER `pushable`;");
$db->exec("ALTER TABLE `" . TABLE_PREFIX . "monsters` ADD `canpushcreatures` TINYINT(1) NOT NULL DEFAULT '0' AFTER `canpushitems`;");
$db->exec("ALTER TABLE `" . TABLE_PREFIX . "monsters` ADD `canwalkonenergy` TINYINT(1) NOT NULL DEFAULT '0' AFTER `canpushitems`;");
$db->exec("ALTER TABLE `" . TABLE_PREFIX . "monsters` ADD `canwalkonpoison` TINYINT(1) NOT NULL DEFAULT '0' AFTER `canwalkonenergy`;");
$db->exec("ALTER TABLE `" . TABLE_PREFIX . "monsters` ADD `canwalkonfire` TINYINT(1) NOT NULL DEFAULT '0' AFTER `canwalkonpoison`;");
$db->exec("ALTER TABLE `" . TABLE_PREFIX . "monsters` ADD `runonhealth` TINYINT(1) NOT NULL DEFAULT '0' AFTER `canwalkonfire`;");
$db->exec("ALTER TABLE `" . TABLE_PREFIX . "monsters` ADD `hostile` TINYINT(1) NOT NULL DEFAULT '0' AFTER `runonhealth`;");
$db->exec("ALTER TABLE `" . TABLE_PREFIX . "monsters` ADD `attackable` TINYINT(1) NOT NULL DEFAULT '0' AFTER `hostile`;");
$db->exec("ALTER TABLE `" . TABLE_PREFIX . "monsters` ADD `rewardboss` TINYINT(1) NOT NULL DEFAULT '0' AFTER `attackable`;");
$db->exec("ALTER TABLE `" . TABLE_PREFIX . "monsters` ADD `defense` INT(11) NOT NULL DEFAULT '0' AFTER `rewardboss`;");
$db->exec("ALTER TABLE `" . TABLE_PREFIX . "monsters` ADD `armor` INT(11) NOT NULL DEFAULT '0' AFTER `defense`;");
$db->exec("ALTER TABLE `" . TABLE_PREFIX . "monsters` ADD `summons` TEXT NOT NULL AFTER `loot`;");
}

4
system/migrations/32.php Normal file
View File

@ -0,0 +1,4 @@
<?php
// Increase size of page in myaac_visitors table
$db->exec('ALTER TABLE `' . TABLE_PREFIX . "visitors` MODIFY `page` VARCHAR(2048) NOT NULL;");

6
system/migrations/33.php Normal file
View File

@ -0,0 +1,6 @@
<?php
// Increase size of ip in myaac_visitors table
// according to this answer: https://stackoverflow.com/questions/166132/maximum-length-of-the-textual-representation-of-an-ipv6-address
// the size of ipv6 can be maximal 45 chars
$db->exec('ALTER TABLE `' . TABLE_PREFIX . "visitors` MODIFY `ip` VARCHAR(45) NOT NULL;");

View File

@ -66,7 +66,7 @@ if($email_new_time < 10) {
else
{
if($email_new_time < time()) {
if($_POST['changeemailsave'] == 1) {
if (isset($_POST['changeemailsave']) && $_POST['changeemailsave'] == 1) {
$account_logged->setCustomField("email_new", "");
$account_logged->setCustomField("email_new_time", 0);
$account_logged->setEmail($email_new);
@ -110,14 +110,14 @@ else
));
}
}
else
else if(!isset($_POST['emailchangecancel']) || $_POST['emailchangecancel'] != 1)
{
$custom_buttons = '
<table style="width:100%;" >
<tr align="center">
<td>
<table border="0" cellspacing="0" cellpadding="0" >
<form action="{{ ' .getLink('account/email') . ' }}" method="post" >
<form action="' .getLink('account/email') . '" method="post" >
<tr>
<td style="border:0px;" >
<input type="hidden" name="emailchangecancel" value="1" >

View File

@ -21,19 +21,15 @@ else
if($points < $config['account_change_character_name_points'])
$errors[] = 'You need ' . $config['account_change_character_name_points'] . ' premium points to change name. You have <b>'.$points.'<b> premium points.';
$minLength = config('character_name_min_length');
$maxLength = config('character_name_max_length');
if(empty($errors) && empty($name))
$errors[] = 'Please enter a new name for your character!';
else if(strlen($name) > 25)
$errors[] = 'Name is too long. Max. lenght <b>25</b> letters.';
else if(strlen($name) < 3)
$errors[] = 'Name is too short. Min. lenght <b>3</b> letters.';
else {
$exist = new OTS_Player();
$exist->find($name);
if($exist->isLoaded()) {
$errors[] = 'Character with this name already exist.';
}
}
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.';
if(empty($errors))
{

View File

@ -22,23 +22,37 @@ if(isset($_POST['deletecharactersave']) && $_POST['deletecharactersave'] == 1) {
$player_account = $player->getAccount();
if($account_logged->getId() == $player_account->getId()) {
if($password_verify == $account_logged->getPassword()) {
if(!$player->isOnline())
{
//dont show table "delete character" again
$show_form = false;
//delete player
if($db->hasColumn('players', 'deletion'))
$player->setCustomField('deletion', 1);
else
$player->setCustomField('deleted', 1);
$account_logged->logAction('Deleted character <b>' . $player->getName() . '</b>.');
$twig->display('success.html.twig', array(
'title' => 'Character Deleted',
'description' => 'The character <b>' . $player_name . '</b> has been deleted.'
));
if(!$player->isOnline()) {
if(!$player->isDeleted()) {
if(fieldExist('id', 'houses')) {
$house = $db->query('SELECT `id` FROM `houses` WHERE `owner` = '.$player->getId());
if($house->rowCount() > 0) {
$errors[] = 'You cannot delete a character when they own a home.';
}
}
if(empty($errors)) {
//dont show table "delete character" again
$show_form = false;
//delete player
if ($db->hasColumn('players', 'deletion'))
$player->setCustomField('deletion', 1);
else
$player->setCustomField('deleted', 1);
$account_logged->logAction('Deleted character <b>' . $player->getName() . '</b>.');
$twig->display('success.html.twig', array(
'title' => 'Character Deleted',
'description' => 'The character <b>' . $player_name . '</b> has been deleted.'
));
}
}
else {
$errors[] = 'This player has been already deleted.';
}
}
else
else {
$errors[] = 'This character is online.';
}
}
else {
$errors[] = 'Wrong password to account.';
@ -66,4 +80,4 @@ if($show_form) {
}
$twig->display('account.delete_character.html.twig');
}
?>
?>

View File

@ -22,6 +22,7 @@ if(isset($_POST['registeraccountsave']) && $_POST['registeraccountsave'] == "1")
$account_logged->setCustomField("key", $new_rec_key);
$account_logged->logAction('Generated recovery key.');
$message = '';
if($config['mail_enabled'] && $config['send_mail_when_generate_reckey'])
{
@ -55,4 +56,4 @@ if($show_form) {
$twig->display('account.generate_recovery_key.html.twig');
}
?>
?>

View File

@ -40,7 +40,7 @@ else
$message = '<br />Your recovery key were send on email address <b>'.$account_logged->getEMail().'</b> for '.$config['generate_new_reckey_price'].' premium points.';
}
else
$message = '<br /><p class="error">An error occorred while sending email ( <b>'.$account_logged->getEMail().'</b> ) with recovery key! Recovery key not changed. Try again later. For Admin: More info can be found in system/logs/mailer-error.log</p>';
$message = '<br /><p class="error">An error occurred while sending email ( <b>'.$account_logged->getEMail().'</b> ) with recovery key! Recovery key not changed. Try again later. For Admin: More info can be found in system/logs/mailer-error.log</p>';
$twig->display('success.html.twig', array(
'title' => 'Account Registered',

View File

@ -60,7 +60,8 @@ $errors = array();
if($action == '')
{
$freePremium = isset($config['lua']['freePremium']) && getBoolean($config['lua']['freePremium']);
$freePremium = isset($config['lua']['freePremium']) && getBoolean($config['lua']['freePremium']) || $account_logged->getPremDays() == OTS_Account::GRATIS_PREMIUM_DAYS;
$dayOrDays = $account_logged->getPremDays() == 1 ? 'day' : 'days';
/**
* @var OTS_Account $account_logged
*/
@ -68,7 +69,7 @@ $errors = array();
if(!$account_logged->isPremium())
$account_status = '<b><span style="color: red">Free Account</span></b>';
else
$account_status = '<b><span style="color: green">Premium Account, ' . ($freePremium ? 'Unlimited' : $account_logged->getPremDays() . ' days left') . '</span></b>';
$account_status = '<b><span style="color: green">' . ($freePremium ? 'Gratis Premium Account' : 'Premium Account, ' . $account_logged->getPremDays() . ' '.$dayOrDays.' left') . '</span></b>';
if(empty($recovery_key))
$account_registered = '<b><span style="color: red">No</span></b>';

View File

@ -197,6 +197,7 @@ if($player->isLoaded() && !$player->isDeleted())
foreach($quests as &$storage) {
$storage = isset($player_storage[$storage]) && $player_storage[$storage] > 0;
}
unset($storage);
}
if($config['characters']['equipment'])
@ -326,7 +327,7 @@ WHERE killers.death_id = '".$death['id']."' ORDER BY killers.final_hit DESC, kil
$frags = array();
$frag_add_content = '';
if($config['characters']['frags'])
if($config['characters']['frags'] && $db->hasTable('killers'))
{
//frags list by Xampy
$i = 0;
@ -371,7 +372,7 @@ WHERE killers.death_id = '".$death['id']."' ORDER BY killers.final_hit DESC, kil
$_player = new OTS_Player();
$fields = array('id', 'name', 'vocation', 'level', 'online', 'deleted', 'hidden');
$_player->load($p['id'], $fields, false);
if($_player->isLoaded()) {
if($_player->isLoaded() && !$_player->isHidden()) {
$account_players[] = $_player;
}
}
@ -432,7 +433,7 @@ else
if($db->hasColumn('players', 'deletion'))
$deleted = 'deletion';
$query = $db->query('SELECT `name`, `level`, `vocation`' . $promotion . ' FROM `players` WHERE `name` LIKE ' . $db->quote('%' . $name . '%') . ' AND ' . $deleted . ' != 1;');
$query = $db->query('SELECT `name`, `level`, `vocation`' . $promotion . ' FROM `players` WHERE `name` LIKE ' . $db->quote('%' . $name . '%') . ' AND ' . $deleted . ' != 1 LIMIT ' . (int)config('characters_search_limit') . ';');
if($query->rowCount() > 0)
{
echo 'Did you mean:<ul>';
@ -450,4 +451,4 @@ else
}
if(!empty($search_errors))
$twig->display('error_box.html.twig', array('errors' => $search_errors));
$twig->display('error_box.html.twig', array('errors' => $search_errors));

View File

@ -223,6 +223,14 @@ if($save)
}
else
{
if(config('account_create_character_create')) {
// character creation
$character_created = $createCharacter->doCreate($character_name, $character_sex, $character_vocation, $character_town, $new_account, $errors);
if (!$character_created) {
error('There was an error creating your character. Please create your character later in account management page.');
}
}
if($config['account_create_auto_login']) {
$_POST['account_login'] = USE_ACCOUNT_NAME ? $account_name : $account_id;
$_POST['password_login'] = $password2;
@ -265,14 +273,6 @@ if($save)
error('An error occurred while sending email. For Admin: More info can be found in system/logs/mailer-error.log');
}
}
if(config('account_create_character_create')) {
// character creation
$character_created = $createCharacter->doCreate($character_name, $character_sex, $character_vocation, $character_town, $new_account, $errors);
if (!$character_created) {
error('There was an error creating your character. Please create your character later in account management page.');
}
}
}
return;

View File

@ -62,7 +62,8 @@ if (empty($_REQUEST['creature'])) {
echo '</tbody></table>';
} else {
$monster_name = stripslashes(trim(ucwords($_REQUEST['creature'])));
$monster_name = urldecode(stripslashes(trim(ucwords($_REQUEST['creature']))));
$monster = $db->query('SELECT * FROM `' . TABLE_PREFIX . 'monsters` WHERE `hidden` != 1 AND `name` = ' . $db->quote($monster_name) . ';')->fetch();
if (isset($monster['name'])) {
$title = $monster['name'] . " - Creatures";
@ -146,7 +147,7 @@ if (empty($_REQUEST['creature'])) {
$name = getItemNameById($item['id']);
$tooltip = $name . '<br/>Chance: ' . round($item['chance'] / 1000, 2) . '%<br/>Max count: ' . $item['count'];
echo getItemImage($item['id']);
echo '<img src="' . $config['item_images_url'] . $item['id'] . '.gif" class="item_image" title="' . $tooltip . '" width="32" height="32" border="0" alt=" ' . $name . '" />';
$i++;
}
@ -170,4 +171,4 @@ if (empty($_REQUEST['creature'])) {
</script>
<script src="<?php echo BASE_URL; ?>tools/js/jquery.dataTables.min.js"></script>
<script src="<?php echo BASE_URL; ?>tools/js/jquery.dataTables.min.js"></script>

View File

@ -43,7 +43,15 @@ echo '<br /><br />Page: '.$links_to_pages.'<br />';
$last_threads = $db->query("SELECT `players`.`id` as `player_id`, `players`.`name`, `" . FORUM_TABLE_PREFIX . "forum`.`post_text`, `" . FORUM_TABLE_PREFIX . "forum`.`post_topic`, `" . FORUM_TABLE_PREFIX . "forum`.`id`, `" . FORUM_TABLE_PREFIX . "forum`.`last_post`, `" . FORUM_TABLE_PREFIX . "forum`.`replies`, `" . FORUM_TABLE_PREFIX . "forum`.`views`, `" . FORUM_TABLE_PREFIX . "forum`.`post_date` FROM `players`, `" . FORUM_TABLE_PREFIX . "forum` WHERE `players`.`id` = `" . FORUM_TABLE_PREFIX . "forum`.`author_guid` AND `" . FORUM_TABLE_PREFIX . "forum`.`section` = ".(int) $section_id." AND `" . FORUM_TABLE_PREFIX . "forum`.`first_post` = `" . FORUM_TABLE_PREFIX . "forum`.`id` ORDER BY `" . FORUM_TABLE_PREFIX . "forum`.`last_post` DESC LIMIT ".$config['forum_threads_per_page']." OFFSET ".($_page * $config['forum_threads_per_page']))->fetchAll();
if(isset($last_threads[0]))
{
echo '<table width="100%"><tr bgcolor="'.$config['vdarkborder'].'" align="center"><td><span style="color: white; font-size: 10px"><b>Thread</b></span></td><td><span style="color: white; font-size: 10px"><b>Thread Starter</b></span></td><td><span style="color: white; font-size: 10px"><b>Replies</b></span></td><td><span style="color: white; font-size: 10px"><b>Views</b></span></td><td><span style="color: white; font-size: 10px"><b>Last Post</b></span></td></tr>';
echo '<table width="100%">
<tr bgcolor="'.$config['vdarkborder'].'" align="center">
<td class="white">
<span style="font-size: 10px"><b>Thread</b></span></td>
<td><span style="font-size: 10px"><b>Thread Starter</b></span></td>
<td><span style="font-size: 10px"><b>Replies</b></span></td>
<td><span style="font-size: 10px"><b>Views</b></span></td>
<td><span style="font-size: 10px"><b>Last Post</b></span></td>
</tr>';
$player = new OTS_Player();
foreach($last_threads as $thread)
@ -83,4 +91,4 @@ if(isset($last_threads[0]))
else
echo '<h3>No threads in this board.</h3>';
?>
?>

View File

@ -39,13 +39,10 @@ if(isset($_REQUEST['todo']) && $_REQUEST['todo'] == 'save') {
$player->find($name);
if(!$player->isLoaded()) {
$errors[] = 'Player with name <b>'.$name.'</b> doesn\'t exist.';
}
else
{
$rank_of_player = $player->getRank();
if($rank_of_player->isLoaded()) {
$errors[] = 'Character with name <b>'.$name.'</b> is already in guild. You must leave guild before you join other guild.';
}
}else if ($player->getAccountID() != $account_logged->getId()) {
$errors[] = 'Character with name <b> ' . $name. ' </b> is not in your account.';
}else if ($player->getRank()->isLoaded()){
$errors[] = 'Character with name <b>'.$name.'</b> is already in guild. You must leave guild before you join other guild.';
}
}
}
@ -63,9 +60,8 @@ if(isset($_REQUEST['todo']) && $_REQUEST['todo'] == 'save') {
}
}
}
if(!$is_invited) {
$errors[] = 'Character '.$player->getName.' isn\'t invited to guild <b>'.$guild->getName().'</b>.';
$errors[] = 'Character '.$player->getName() .' isn\'t invited to guild <b>'.$guild->getName().'</b>.';
}
}
}
@ -124,4 +120,4 @@ else {
}
}
?>
?>

View File

@ -51,8 +51,7 @@ if(empty($errors)) {
}
$twig->display('guilds.change_description.html.twig', array(
'guild' => $guild,
'rows' => bcsub($config['guild_description_lines_limit'],1)
'guild' => $guild
));
}
else {
@ -72,4 +71,4 @@ if(!empty($errors)) {
));
}
?>
?>

View File

@ -86,7 +86,7 @@ if($guild_vice)
else
{
$player_in_guild = false;
if($guild->getName() === $player_to_change->getRank()->getGuild()->getName() || $guild_leader)
if($guild->getName() === $player_to_change->getRank()->getGuild()->getName())
{
$player_in_guild = true;
$player_has_lower_rank = false;

View File

@ -77,8 +77,12 @@ if(empty($guild_errors)) {
$new_rank->setName('New Rank level '.$rank->getLevel());
$new_rank->save();
}
foreach($players_with_rank as $player_in_guild) {
$player_in_guild->setRank($new_rank);
$player = new OTS_Player();
$player->load($player_in_guild['id']);
if ($player->isLoaded())
$player->setRank($new_rank);
}
}
$rank->delete();
@ -120,4 +124,4 @@ if(!empty($guild_errors)) {
));
}
?>
?>

View File

@ -18,6 +18,10 @@ $list = isset($_GET['list']) ? $_GET['list'] : '';
$_page = isset($_GET['page']) ? $_GET['page'] : 0;
$vocation = isset($_GET['vocation']) ? $_GET['vocation'] : NULL;
if(!is_numeric($_page) || $_page < 0 || $_page > PHP_INT_MAX) {
$_page = 0;
}
$add_sql = '';
$config_vocations = $config['vocations'];
if($config['highscores_vocation_box'] && isset($vocation))
@ -45,7 +49,7 @@ $skill = POT::SKILL__LEVEL;
if(is_numeric($list))
{
$list = (int) $list;
if($list >= POT::SKILL_FIRST && $list <= SKILL__LAST)
if($list >= POT::SKILL_FIRST && $list <= POT::SKILL__LAST)
$skill = $list;
}
else

View File

@ -143,8 +143,20 @@ if(isset($_POST['town']) && isset($_POST['state']) && isset($_POST['order']) &&
if($type == 'guildhalls' && !$db->hasColumn('houses', 'guild'))
$type = 'all';
if(!empty($type) && $type != 'all')
$whereby .= ' AND `guild` ' . ($type == 'guildhalls' ? '!' : '') . '= 0';
if (!empty($type) && $type != 'all')
{
$guildColumn = '';
if ($db->hasColumn('houses', 'guild')) {
$guildColumn = 'guild';
}
else if ($db->hasColumn('houses', 'guildid')) {
$guildColumn = 'guildid';
}
if($guildColumn !== '') {
$whereby .= ' AND `' . $guildColumn . '` ' . ($type == 'guildhalls' ? '!' : '') . '= 0';
}
}
$houses_info = $db->query('SELECT * FROM `houses` WHERE ' . $whereby. ' ORDER BY ' . $orderby);
@ -179,7 +191,7 @@ if(isset($_POST['town']) && isset($_POST['state']) && isset($_POST['order']) &&
$housesSearch = true;
}
$guild = $db->hasTable('houses', 'guild') ? ' or guildhall' : '';
$guild = $db->hasColumn('houses', 'guild') ? ' or guildhall' : '';
$twig->display('houses.html.twig', array(
'state' => $state,
'order' => $order,

View File

@ -111,7 +111,7 @@ elseif($action == 'sendcode')
else
{
$account->setCustomField('email_next', (time() + 60));
echo '<br /><p class="error">An error occorred while sending email! Try again later or contact with admin. For Admin: More info can be found in system/logs/mailer-error.log</p>';
echo '<br /><p class="error">An error occurred while sending email! Try again later or contact with admin. For Admin: More info can be found in system/logs/mailer-error.log</p>';
}
}
else
@ -330,7 +330,7 @@ elseif($action == 'step3')
}
else
{
echo '<br /><p class="error">An error occorred while sending email! You will not receive e-mail with this informations. For Admin: More info can be found in system/logs/mailer-error.log</p>';
echo '<br /><p class="error">An error occurred while sending email! You will not receive e-mail with this informations. For Admin: More info can be found in system/logs/mailer-error.log</p>';
}
}
else
@ -513,7 +513,7 @@ elseif($action == 'setnewpassword')
}
else
{
echo '<br /><p class="error">New password work! An error occorred while sending email! You will not receive e-mail with new password. For Admin: More info can be found in system/logs/mailer-error.log';
echo '<br /><p class="error">New password work! An error occurred while sending email! You will not receive e-mail with new password. For Admin: More info can be found in system/logs/mailer-error.log';
}
echo '</TD></TR>
</TABLE>

View File

View File

@ -25,7 +25,13 @@ if($config['template_allow_change'])
}
setSession('template', $template_name);
header('Location:' . getSession('last_uri'));
$newLocation = $lastUri = getSession('last_uri');
if($lastUri === $_SERVER['REQUEST_URI']) { // avoid ERR_TOO_MANY_REDIRECTS error in browsers
$newLocation = SERVER_URL;
}
header('Location:' . $newLocation);
}
}
else {

View File

@ -54,6 +54,10 @@
<td></td><td><span id="email_error" class="FormFieldError">{% if errors.email is defined %}{{ errors.email }}{% endif %}</span></td>
</tr>
{% if config.mail_enabled and config.account_mail_verify %}
<tr><td></td><td><span><strong>Please use real address!<br/>We will send a link to validate your Email.</strong></span></td></tr>
{% endif %}
{{ hook('HOOK_ACCOUNT_CREATE_AFTER_EMAIL') }}
{% if config.account_country %}
@ -82,7 +86,7 @@
<span{% if errors.password is defined %} class="red"{% endif %}>Password:</span>
</td>
<td>
<input type="password" name="password" id="password" value="" size="30" maxlength="50" />
<input type="password" name="password" id="password" value="" size="30" maxlength="29" />
<img id="password_indicator" src="images/global/general/{% if not save or errors.password is defined %}n{% endif %}ok.gif" style="display: none;" />
</td>
</tr>
@ -92,7 +96,7 @@
<span{% if errors.password is defined %} class="red"{% endif %}>Repeat password:</span>
</td>
<td>
<input type="password" name="password2" id="password2" value="" size="30" maxlength="50" />
<input type="password" name="password2" id="password2" value="" size="30" maxlength="29" />
<img id="password2_indicator" src="images/global/general/{% if not save or errors.password is defined %}n{% endif %}ok.gif" style="display: none;" />
</td>
</tr>

View File

@ -2,7 +2,7 @@ Please choose a name{% if config.character_samples|length > 1 %}, vocation{% end
{% if config.character_towns|length > 1 %}, town{% endif %}
and sex for your character. <br/>
In any case the name must not violate the naming conventions stated in the <a href="?subtopic=rules" target="_blank" >{{ config.lua.serverName }} Rules</a>, or your character might get deleted or name locked.
{% if account_logged.getPlayersList()|length >= config.characters_per_account %}
{% if account_logged.getPlayersList(false)|length >= config.characters_per_account %}
<b><span style="color: red"> You have maximum number of characters per account on your account. Delete one before you make new.</span></b>
{% endif %}
<br/><br/>
@ -145,4 +145,4 @@ In any case the name must not violate the naming conventions stated in the <a hr
</td>
</tr>
</table>
<script type="text/javascript" src="tools/check_name.js"></script>
<script type="text/javascript" src="tools/check_name.js"></script>

View File

@ -25,7 +25,7 @@
<div class="col-sm-10" id="body-parent">
<textarea class="form-control" id="body" name="body" maxlength="65000" cols="50" rows="5">{{ body|raw }}</textarea>
</div>
</div>
</div>
<div class="form-group">
<label for="select-type" class="col-sm-2 control-label">Type</label>
@ -37,7 +37,7 @@
<option value="{{ constant('ARTICLE') }}" {% if type is defined and type == constant('ARTICLE') %}selected="yes"{% endif %}{% if action == 'edit' and type != constant('ARTICLE') %} disabled{% endif %}>Article</option>
</select>
</div>
</div>
</div>
<div id="article-text" class="form-group"{% if type is not defined or type != constant('ARTICLE') %} style="display: none;"{% endif %}>
<label for="article_text" class="col-sm-2 control-label">Article short text</label>
@ -65,8 +65,8 @@
<option value="{{ player.getId() }}">{{ player.getName() }}</option>
</select>
</div>
</div>
{% endif %}
</div>
{% endif %}
{% endif %}
<div class="form-group">
@ -79,7 +79,7 @@
{% endfor %}
</select>
</div>
</div>
</div>
{% if action != 'edit' %}
<div class="form-group">
@ -95,19 +95,19 @@
</div>
</div>
{% elseif comments is not null %}
<input type="hidden" name="forum_section" id="forum_section" value="{{ comments }}" />
<input type="hidden" name="forum_section" id="forum_section" value="{{ comments }}" />
{% endif %}
<div class="form-group">
<label for="category" class="col-sm-2 control-label">Category</label>
<div class="col-sm-10">
{% for id, cat in categories %}
<input type="radio" name="category" id="category" value="{{ id }}" {% if (category == 0 and id == 1) or (category == id) %}checked="yes"{% endif %}/>
<input type="radio" name="category" id="category" value="{{ id }}" {% if (category == 0 and id == 1) or (category == id) %}checked="yes"{% endif %}/>
<img src="{{ constant('BASE_URL') }}/images/news/icon_{{ cat.icon_id }}_small.gif" />
{% endfor %}
</div>
</div>
</div>
</div>
</div>
<div class="box-footer">
@ -158,7 +158,7 @@
toolbar1: 'formatselect | bold italic strikethrough forecolor backcolor | emoticons link | alignleft aligncenter alignright alignjustify | numlist bullist outdent indent | removeformat code',
image_advtab: true,
setup: function(ed){
ed.on('NodeChange', function(e) {
ed.on('Change', function(e) {
if(ed.getContent() != lastContent) {
unsaved = true;
}
@ -170,20 +170,20 @@
$(":input").change(function(){ //trigers change in all input fields including text type
unsaved = true;
});
$("#news-edit-form").submit(function( event ) {
unsaved = false;
});
lastContent = $("#body").val();
});
function unloadPage(){
function unloadPage(){
if(unsaved){
return "You have unsaved changes on this page. Do you want to leave this page and discard your changes or stay on this page?";
}
}
window.onbeforeunload = unloadPage;
</script>
window.onbeforeunload = unloadPage;
</script>
{% endif %}

View File

@ -14,7 +14,7 @@
<div class="box-body">
<div class="form-group">
<label for="exampleInputFile">File input</label>
<input type="file" name="plugin">
<input type="file" name="plugin" accept=".zip">
</div>
</div>
<div class="box-footer">

View File

@ -11,7 +11,7 @@
<thead>
<tr>
<th>Name</th>
<th>Description</th>
<th>Version</th>
<th>Author</th>
<th>Filename</th>
<th style="width: 55px;">Options</th>

View File

@ -0,0 +1,3 @@
<!--[if lt IE 7]>
<p class="browsehappy">You are using an <strong>outdated</strong> browser. Please <a href="http://browsehappy.com/">upgrade your browser</a> to improve your experience.</p>
<![endif]-->

View File

@ -9,7 +9,7 @@
<div class="AttentionSign" style="background-image:url({{ template_path }}/images/content/attentionsign.gif);"></div>
<b>The Following Errors Have Occurred:</b><br/>
{% for error in errors %}
<li>{{ error|raw }}</li>
<li>{{ error|striptags('<b>')|raw }}</li>
{% endfor %}
</div>
<div class="BoxFrameHorizontal" style="background-image:url({{ template_path }}/images/content/box-frame-horizontal.gif);"></div>

View File

@ -1,21 +1,21 @@
<b>Boards</b>
<table width="100%">
<tr bgcolor="{{ config.vdarkborder }}">
<tr bgcolor="{{ config.vdarkborder }}" class="white">
<td>
<span style="color: white; font-size: 10px"><b>Board</b></span>
<span style="font-size: 10px"><b>Board</b></span>
</td>
<td>
<span style="color: white; font-size: 10px"><b>Posts</b></span>
<span style="font-size: 10px"><b>Posts</b></span>
</td>
<td>
<span style="color: white; font-size: 10px"><b>Threads</b></span>
<span style="font-size: 10px"><b>Threads</b></span>
</td>
<td align="center">
<span style="color: white; font-size: 10px"><b>Last Post</b></span>
<span style="font-size: 10px"><b>Last Post</b></span>
</td>
{% if canEdit %}
<td>
<span style="color: white; font-size: 10px"><b>Options</b></span>
<span style="font-size: 10px"><b>Options</b></span>
</td>
{% endif %}
</tr>

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