mirror of
				https://github.com/slawkens/myaac.git
				synced 2025-11-04 01:36:23 +01:00 
			
		
		
		
	Compare commits
	
		
			188 Commits
		
	
	
		
			v1.6
			...
			feature/re
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					6500c29799 | ||
| 
						 | 
					456b68a88b | ||
| 
						 | 
					26c5aa2e51 | ||
| 
						 | 
					bc4107bd16 | ||
| 
						 | 
					d24bde2c1d | ||
| 
						 | 
					a2f8759a52 | ||
| 
						 | 
					4b8c3ffae2 | ||
| 
						 | 
					97321c9e80 | ||
| 
						 | 
					2580edadf8 | ||
| 
						 | 
					8f47b36dc8 | ||
| 
						 | 
					6cd38ee1ec | ||
| 
						 | 
					9d92a11fb7 | ||
| 
						 | 
					44110a9496 | ||
| 
						 | 
					727f68a575 | ||
| 
						 | 
					07fd034fe4 | ||
| 
						 | 
					13ea68cc0c | ||
| 
						 | 
					598cec2fe4 | ||
| 
						 | 
					89fae38caa | ||
| 
						 | 
					16849e7578 | ||
| 
						 | 
					470555f268 | ||
| 
						 | 
					7f60b3d31d | ||
| 
						 | 
					12e40b2592 | ||
| 
						 | 
					38902c30d1 | ||
| 
						 | 
					3e61692780 | ||
| 
						 | 
					c88b08eb1e | ||
| 
						 | 
					82d417b590 | ||
| 
						 | 
					b797908e49 | ||
| 
						 | 
					90c8463797 | ||
| 
						 | 
					c91bb5d409 | ||
| 
						 | 
					fe821c5808 | ||
| 
						 | 
					9acad15451 | ||
| 
						 | 
					8c3cb0e06f | ||
| 
						 | 
					2eae44e075 | ||
| 
						 | 
					8272f1373c | ||
| 
						 | 
					901df48d13 | ||
| 
						 | 
					2da0024c68 | ||
| 
						 | 
					0d8f68a48e | ||
| 
						 | 
					0cb9d3a208 | ||
| 
						 | 
					d8b73f55a3 | ||
| 
						 | 
					3bb272ebbb | ||
| 
						 | 
					64acf70d38 | ||
| 
						 | 
					97f9d3d6f6 | ||
| 
						 | 
					596dde4077 | ||
| 
						 | 
					ac9303402d | ||
| 
						 | 
					f54b1bdd2a | ||
| 
						 | 
					c898fe25ef | ||
| 
						 | 
					73c07d470d | ||
| 
						 | 
					56bd7ec5ed | ||
| 
						 | 
					4c6277c124 | ||
| 
						 | 
					228780f0ad | ||
| 
						 | 
					4e9999cc0d | ||
| 
						 | 
					8bc328d6fb | ||
| 
						 | 
					ac41b82579 | ||
| 
						 | 
					df7b6e29fb | ||
| 
						 | 
					e0cc19ad86 | ||
| 
						 | 
					85e7005fd3 | ||
| 
						 | 
					3c0cb53e17 | ||
| 
						 | 
					d0112d1a67 | ||
| 
						 | 
					523210c5b7 | ||
| 
						 | 
					29e2484ad5 | ||
| 
						 | 
					ed9beaf2b6 | ||
| 
						 | 
					9ae07acfc1 | ||
| 
						 | 
					dc6b60d0b6 | ||
| 
						 | 
					5aa9bbf1c8 | ||
| 
						 | 
					05b5e703ed | ||
| 
						 | 
					849944ff20 | ||
| 
						 | 
					413ad42afa | ||
| 
						 | 
					233bf001ce | ||
| 
						 | 
					d2f1f41576 | ||
| 
						 | 
					2f9ae38c19 | ||
| 
						 | 
					a6032093b2 | ||
| 
						 | 
					b1b536ce68 | ||
| 
						 | 
					25695a039d | ||
| 
						 | 
					e27d974c46 | ||
| 
						 | 
					4eab805d26 | ||
| 
						 | 
					3f24f961b1 | ||
| 
						 | 
					0b86459940 | ||
| 
						 | 
					7a9b11434e | ||
| 
						 | 
					9725a3c2bd | ||
| 
						 | 
					46adeefce3 | ||
| 
						 | 
					e4b66f34ac | ||
| 
						 | 
					2465bb6f9a | ||
| 
						 | 
					42671c5c19 | ||
| 
						 | 
					fec773ba4b | ||
| 
						 | 
					1b9f68c9ec | ||
| 
						 | 
					7a08f91d3f | ||
| 
						 | 
					4b948e9510 | ||
| 
						 | 
					17ca93d020 | ||
| 
						 | 
					bcc4b48eb0 | ||
| 
						 | 
					f8c4332e03 | ||
| 
						 | 
					235e0f394d | ||
| 
						 | 
					3451715e96 | ||
| 
						 | 
					d85681880e | ||
| 
						 | 
					4701461b1f | ||
| 
						 | 
					482f4067b2 | ||
| 
						 | 
					2f26748112 | ||
| 
						 | 
					98073a110a | ||
| 
						 | 
					11dae90fa9 | ||
| 
						 | 
					20f99903ae | ||
| 
						 | 
					b6e1620f14 | ||
| 
						 | 
					9cb7792623 | ||
| 
						 | 
					0db908be18 | ||
| 
						 | 
					785d38312b | ||
| 
						 | 
					e1c04ed28e | ||
| 
						 | 
					c836308601 | ||
| 
						 | 
					0efe47ce71 | ||
| 
						 | 
					3b47e9df2f | ||
| 
						 | 
					43415cf35d | ||
| 
						 | 
					cf7fd20452 | ||
| 
						 | 
					080cc2781f | ||
| 
						 | 
					20d69a641c | ||
| 
						 | 
					2d4be327b2 | ||
| 
						 | 
					bb097b69ce | ||
| 
						 | 
					6e5a4ff8c7 | ||
| 
						 | 
					caf326a658 | ||
| 
						 | 
					bccf8e056d | ||
| 
						 | 
					7d27e5a0ba | ||
| 
						 | 
					9b6f410459 | ||
| 
						 | 
					c06b0017f1 | ||
| 
						 | 
					d8132d4d76 | ||
| 
						 | 
					1566deb84a | ||
| 
						 | 
					536b29be95 | ||
| 
						 | 
					5271633bdb | ||
| 
						 | 
					ce5b1cf2a6 | ||
| 
						 | 
					83f84172e0 | ||
| 
						 | 
					34fead906e | ||
| 
						 | 
					ec11c14024 | ||
| 
						 | 
					2fe9924437 | ||
| 
						 | 
					f0f2e3785f | ||
| 
						 | 
					36ca755243 | ||
| 
						 | 
					f17269e44c | ||
| 
						 | 
					dcb96f4ce1 | ||
| 
						 | 
					a89f9a8484 | ||
| 
						 | 
					45d6047031 | ||
| 
						 | 
					c92148d467 | ||
| 
						 | 
					b4b62442fe | ||
| 
						 | 
					047742848b | ||
| 
						 | 
					fe8281594e | ||
| 
						 | 
					0bff910a05 | ||
| 
						 | 
					6d43fc181f | ||
| 
						 | 
					13d33822b5 | ||
| 
						 | 
					f78ebad136 | ||
| 
						 | 
					d90fa323d7 | ||
| 
						 | 
					181131f7f3 | ||
| 
						 | 
					0da524fefe | ||
| 
						 | 
					6cf4b9dac5 | ||
| 
						 | 
					5cfa3a697f | ||
| 
						 | 
					bb830bce44 | ||
| 
						 | 
					566c2a9151 | ||
| 
						 | 
					0f48f12e2e | ||
| 
						 | 
					0ea247ce7e | ||
| 
						 | 
					b329da52aa | ||
| 
						 | 
					c720ccc451 | ||
| 
						 | 
					8dc42b6544 | ||
| 
						 | 
					dca904e61d | ||
| 
						 | 
					29faa4f695 | ||
| 
						 | 
					4767120043 | ||
| 
						 | 
					9a90e4aae2 | ||
| 
						 | 
					ba4ed6a04b | ||
| 
						 | 
					a7efacdbac | ||
| 
						 | 
					577037becc | ||
| 
						 | 
					b8abc11b96 | ||
| 
						 | 
					4def6a6cae | ||
| 
						 | 
					e6100a1b72 | ||
| 
						 | 
					522f6c11d8 | ||
| 
						 | 
					00c3635c5f | ||
| 
						 | 
					c074a48f24 | ||
| 
						 | 
					e222957893 | ||
| 
						 | 
					d423ddd07a | ||
| 
						 | 
					4d4f7759d3 | ||
| 
						 | 
					9510640ba9 | ||
| 
						 | 
					98b13c91a4 | ||
| 
						 | 
					0c95bcfd06 | ||
| 
						 | 
					524e982a0e | ||
| 
						 | 
					fffb427eae | ||
| 
						 | 
					10cd71a663 | ||
| 
						 | 
					0812fe025d | ||
| 
						 | 
					309c1fb715 | ||
| 
						 | 
					8d29fdb98b | ||
| 
						 | 
					f782850307 | ||
| 
						 | 
					835dda9659 | ||
| 
						 | 
					dcc703b1eb | ||
| 
						 | 
					9d8e9d27bd | ||
| 
						 | 
					db09980de1 | ||
| 
						 | 
					2dba778167 | ||
| 
						 | 
					67f54eacbc | ||
| 
						 | 
					cde8891b9b | ||
| 
						 | 
					50a8b8169f | 
							
								
								
									
										2
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							@@ -4,7 +4,7 @@ Thumbs.db
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
/.htaccess
 | 
					/.htaccess
 | 
				
			||||||
lua
 | 
					/lua
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# composer
 | 
					# composer
 | 
				
			||||||
composer.phar
 | 
					composer.phar
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										141
									
								
								CHANGELOG-1.x.md
									
									
									
									
									
								
							
							
						
						
									
										141
									
								
								CHANGELOG-1.x.md
									
									
									
									
									
								
							@@ -1,5 +1,146 @@
 | 
				
			|||||||
# Changelog
 | 
					# Changelog
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## [1.8.4 - 27.10.2025]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### Changed
 | 
				
			||||||
 | 
					* Reimport myaac_ tables on every install, this fixes errors when one table is missing or is duplicated (https://github.com/slawkens/myaac/commit/2580edadf84779f09fd395c21f92019b2c762f83)
 | 
				
			||||||
 | 
					* Use custom env init on migrate, migrate:run and migrate:to (https://github.com/slawkens/myaac/commit/13ea68cc0c9349380c8e4051d702a6c2c8256f44, https://github.com/slawkens/myaac/commit/07fd034fe4cb0ffdb88667b1e400f414d0c6d06f)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### Fixed
 | 
				
			||||||
 | 
					* Show if there is mysql error on import schema (https://github.com/slawkens/myaac/commit/44110a9496b4385e42c31b75de301037e711b6c3)
 | 
				
			||||||
 | 
					* Fix the premium checks, introduced in v1.8.3 (https://github.com/slawkens/myaac/commit/9d92a11fb7cb6d7a1619d79c12faaa0b1c01f980)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## [1.8.3 - 21.10.2025]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### Added
 | 
				
			||||||
 | 
					* Feature: resend email verify (https://github.com/slawkens/myaac/commit/fe821c58085483e70491dcf76376ad5b96de3fdd)
 | 
				
			||||||
 | 
					* New config: hooks_debug (To view where hooks are located in .twig files) (https://github.com/slawkens/myaac/commit/8c3cb0e06f9709c1de3398b48221241e7cbdd310)
 | 
				
			||||||
 | 
					* Functions: Add db->getColumnInfo(table, column) (https://github.com/slawkens/myaac/commit/c898fe25efff6793a01d11c26fc153cb23fcb858)
 | 
				
			||||||
 | 
					* Plugins: Add option to use ?subtopic=x for plugins pages (https://github.com/slawkens/myaac/commit/97f9d3d6f6c28aef6d824973058d7133f56e09c4)
 | 
				
			||||||
 | 
					* getTopPlayers() Function - Add lookmount & promotion (https://github.com/slawkens/myaac/commit/2da0024c68f1cedc38a16ebbc6f52ffa55e65f7a, https://github.com/slawkens/myaac/commit/901df48d134079d648a18f9d82b60182e818ac02)
 | 
				
			||||||
 | 
					* New hooks for account/change-password (https://github.com/slawkens/myaac/commit/470555f2687809a0c12491bbb27597e64b8929c1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### Changed
 | 
				
			||||||
 | 
					* Feature: show vip days in account management (https://github.com/slawkens/myaac/commit/c88b08eb1ec1f560cbfdaaa16b24e3a0f26da7b3, by @andreoam)
 | 
				
			||||||
 | 
					* Allow links in error_box.html.twig (https://github.com/slawkens/myaac/commit/9acad15451071639acf7a7d4e81619b0a9742b12)
 | 
				
			||||||
 | 
					* Canary - Comment code to update lastday in login.php (https://github.com/slawkens/myaac/commit/38902c30d114fdbce259467f5820f97037b393e9)
 | 
				
			||||||
 | 
					* Cache::remember $ttl = -1 = infinite (https://github.com/slawkens/myaac/commit/64acf70d3854182d88aaf0b67f77cea2a254f179)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### Fixed
 | 
				
			||||||
 | 
					* Online - Allow for html code (example - img) in online_datacenter (https://github.com/slawkens/myaac/commit/3bb272ebbbd2eb7769d174b7082061d14a17bd44)
 | 
				
			||||||
 | 
					* Guilds - Fix guild create with freePremium enabled (https://github.com/slawkens/myaac/commit/c91bb5d4097647dca2196d3dea87bc90c89181d2)
 | 
				
			||||||
 | 
					* Canary - Fix premDays count (https://github.com/slawkens/myaac/commit/3e61692780d4add93b7b0e9f12f7a283bd8f4b7a)
 | 
				
			||||||
 | 
					* Template Change: Ignore set last visit for AJAX pages - Fixes template change redirect (https://github.com/slawkens/myaac/commit/89fae38caa7e4f645957fcf1a9330a36358ac04f)
 | 
				
			||||||
 | 
					* Admin Panel - Accounts: Fix lastip v6 (TFS master) (https://github.com/slawkens/myaac/commit/f54b1bdd2af4c16c64ddff0e87a6c96bc4cf9eeb)
 | 
				
			||||||
 | 
					* Functions - Prevent injection in $db->hasColumn (https://github.com/slawkens/myaac/commit/56bd7ec5ed904666074492f2e4f13e4fce226bee)
 | 
				
			||||||
 | 
					* Compat Config: Add missing config: email_lai_sec_interval (https://github.com/slawkens/myaac/commit/2eae44e0755e624a91be68b4d1ec26d01eb4d9a1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## [1.8.2 - 26.09.2025]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### Added
 | 
				
			||||||
 | 
					* Routes: Possibility to override routes with plugins pages, like characters.php - No need to define routes in plugin.json anymore (https://github.com/slawkens/myaac/commit/3f24f961b1cdeff5c60387e837ae454448bc5e1b)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### Changed
 | 
				
			||||||
 | 
					* Style: Better look for myaac-table (https://github.com/slawkens/myaac/commit/a6032093b21e5bb3f0e75d2704da87d6dea6469d, https://github.com/slawkens/myaac/commit/5aa9bbf1c8e580d973ec82ac012489f8e7bc437e)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### Fixed
 | 
				
			||||||
 | 
					* Install: Fix when config.local.php cannot be saved (https://github.com/slawkens/myaac/commit/4eab805d26d8c5562b29ed699769919d77dabced)
 | 
				
			||||||
 | 
					* Create Account: Fix an exception when email cannot be sent (https://github.com/slawkens/myaac/commit/d0112d1a67e8b854b65ad131f0375b79305df8d3)
 | 
				
			||||||
 | 
					* Login Page: Add missing csrf() - fix create account button (https://github.com/slawkens/myaac/commit/3c0cb53e17dd0b85394cfa0fdc9cf9ad8d4551df)
 | 
				
			||||||
 | 
					* tibiacom template: Fix account lost menu (https://github.com/slawkens/myaac/commit/ed9beaf2b6ca069e304e569c52e5b9188b58f05c)
 | 
				
			||||||
 | 
					* tibiacom template: Fix Menu div wrong tag/closing (#329) (https://github.com/slawkens/myaac/commit/85e7005fd3f0be51466151a3c122b96085fdfe68)
 | 
				
			||||||
 | 
					* tibiacom template: Replace firstChild with firstElementChild (Thanks to @un000000) (https://github.com/slawkens/myaac/commit/df7b6e29fb8875da97f431468c81ee99116271d9)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## [1.8.1 - 05.09.2025]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### Added
 | 
				
			||||||
 | 
					* New Commands: plugin:enable/disable/uninstall {plugin-name} (https://github.com/slawkens/myaac/commit/7a08f91d3fc0897c1ff76089ef3c649a2c6d2003, https://github.com/slawkens/myaac/commit/fec773ba4b740f35c0a3ef92ca8444a4c7d02082)
 | 
				
			||||||
 | 
					* Gifts: Added Transferable Coins to the store dropdown menu in the admin area (by @andreoam, #321) (https://github.com/slawkens/myaac/commit/42671c5c199dd9e91c774d8c9d30da9e12f1b695)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### Changed
 | 
				
			||||||
 | 
					* Commands: Allow settings to be changed/reset by plugin name (https://github.com/slawkens/myaac/commit/f8c4332e03e838d285ea0afb4b72b7c23e324d45, https://github.com/slawkens/myaac/commit/4b948e9510f7ba69d00f84d7fdaea8b3bf05b630)
 | 
				
			||||||
 | 
					* Templates: Menus should be saved for each template separately (https://github.com/slawkens/myaac/commit/482f4067b2a2e7513d9ba214274a361ffaf123d8)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### Fixed
 | 
				
			||||||
 | 
					* Online: Fix skulls display (#320) (https://github.com/slawkens/myaac/commit/98073a110ae13f9592ec9d2c4d1d1aace87587a9)
 | 
				
			||||||
 | 
					* Online: Fix if there is no world_id in the server_record table (https://github.com/slawkens/myaac/commit/b6e1620f14c20eecfc9001a7d86dfb67942985c6) (Reported by @gesior in #318)
 | 
				
			||||||
 | 
					* tibiacom: some fixes to menus (https://github.com/slawkens/myaac/commit/20f99903ae80c74ad66c1cf5a5ea8d0b0fc2fd70, https://github.com/slawkens/myaac/commit/11dae90fa94fbbf47447017db5e5847c33d6aadf)
 | 
				
			||||||
 | 
					* Guilds: Fix for some servers that don't have guild_invites table (https://github.com/slawkens/myaac/commit/9725a3c2bdb7003f5cb48febb77604c31a9b805b)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## [1.8 - 02.08.2025]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### Added
 | 
				
			||||||
 | 
					* Templates - Kathrine: Possibility to add custom menu categories (https://github.com/slawkens/myaac/commit/ec11c1402417c25980582467546d1c1e9bb8267f)
 | 
				
			||||||
 | 
					* Admin Panel - Accounts Editor: Add Coins Transferable (https://github.com/slawkens/myaac/commit/45d6047031c9c3a0e7e512dc5d15c75629aec5a2, https://github.com/slawkens/myaac/commit/bb097b69ce106500a49686d6f4fe604348eaa310)
 | 
				
			||||||
 | 
					* Highscores:
 | 
				
			||||||
 | 
					  * Revamped: (https://github.com/slawkens/myaac/commit/d8132d4d76e03d5aa0c042be426320655a601392)
 | 
				
			||||||
 | 
					    * Show real rank, if 2 or more players have the same skill, show them with same rank
 | 
				
			||||||
 | 
					    * New setting: highscores_online_status
 | 
				
			||||||
 | 
					    * Additional fields passed to twig: updatedAt, totalResults, page, baseLink
 | 
				
			||||||
 | 
					  * Add new Setting: Display Skills Box (https://github.com/slawkens/myaac/commit/36ca755243ef1c83f6ac87465b426d4d8d3b0bb9)
 | 
				
			||||||
 | 
					* Functions: Add getExperienceForLevel (level) (https://github.com/slawkens/myaac/commit/1566deb84a082176b8c683fda205d828bc38fbcc)
 | 
				
			||||||
 | 
					* Commands - cache:clear : Add warning about APCu clear in CLI (https://github.com/slawkens/myaac/commit/83f84172e02e8ea2ccb6dca29bc033e44c35aebc)
 | 
				
			||||||
 | 
					* Models - PlayerOnline: Add missing $fillable into model (https://github.com/slawkens/myaac/commit/43415cf35db1c1307f2684c1728693d65065ffff)
 | 
				
			||||||
 | 
					* Twig: add cache variable (https://github.com/slawkens/myaac/commit/0efe47ce71c4b364a9e96bc5a55b1655326ae6da)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### Changed
 | 
				
			||||||
 | 
					* pages/online: add cache, resulting in 20x performance boost
 | 
				
			||||||
 | 
					  * (for an example server with 2k players) (https://github.com/slawkens/myaac/commit/c8363086015cbb6e8786c398c7b9ac3959a26ec4)
 | 
				
			||||||
 | 
					* Admin Bar: Move admin bar code into body_start place_holder (https://github.com/slawkens/myaac/commit/f17269e44ce9dd38447bd2e2a8e1bdb065d4161f)
 | 
				
			||||||
 | 
					* Cache::remember: $ttl = 0 means no cache (https://github.com/slawkens/myaac/commit/3b47e9df2f4051807c5ff87892f7fa3d348f9c55)
 | 
				
			||||||
 | 
					* Templates: Load config.ini with $process_sections set to true (https://github.com/slawkens/myaac/commit/a89f9a84847630eb75b4890fdcc8b7a7bfa6b8ac)
 | 
				
			||||||
 | 
					* Twig: Allow for timestamp as integer in the timeago twig function
 | 
				
			||||||
 | 
					  (https://github.com/slawkens/myaac/commit/34fead906ea13b9f09d7a3c41ed88109d34d386c)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### Fixed
 | 
				
			||||||
 | 
					* Settings: Fixed two exceptions (https://github.com/slawkens/myaac/commit/6e5a4ff8c78ff5373aba091baa66cae029557643, https://github.com/slawkens/myaac/commit/20d69a641c0a933d14889a89da6d32f6a4bc6c7d)
 | 
				
			||||||
 | 
					* Models\Account + OTS_Account -> isPremium -> ignore config.freePremium (https://github.com/slawkens/myaac/commit/5271633bdbfbbfed0b1d59c403093ce6fc2b7d20)
 | 
				
			||||||
 | 
					* Admin Panel - Mailer:
 | 
				
			||||||
 | 
					  * Fix send to email link redirecting from accounts page (https://github.com/slawkens/myaac/commit/080cc2781f034c844af658229e495e9a47fd2298)
 | 
				
			||||||
 | 
					  * Option to send only to verified accounts - only if setting('core.account_mail_verify') enabled (https://github.com/slawkens/myaac/commit/cf7fd20452e863980045bb5d6012ec86c6e8e01f)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### Internal
 | 
				
			||||||
 | 
					* Rewrite to use constants (account transferable coins) (https://github.com/slawkens/myaac/commit/bccf8e056df985bbe1bab5f7ab5492f714d6b62b)
 | 
				
			||||||
 | 
					* Refactor to use HAS_ACCOUNT_COINS (https://github.com/slawkens/myaac/commit/caf326a6584a234775ebc6c8000ea02b3fecd160)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## [1.7.1 - 27.06.2025]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### Changed
 | 
				
			||||||
 | 
					* Rename plugin:install:install to plugin:setup, also add alias to previous command (https://github.com/slawkens/myaac/commit/13d33822b59df349199e885a78a3d6beb0863d0b)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### Fixed
 | 
				
			||||||
 | 
					* Fix commands: setup + cache:clear (https://github.com/slawkens/myaac/commit/0da524fefe93b3028392e9014550eea3324d3a22, https://github.com/slawkens/myaac/commit/fe8281594e989f00280ba1adc734a9198c6b5cc1)
 | 
				
			||||||
 | 
					* Fix polls link in tibiacom template (https://github.com/slawkens/myaac/commit/d90fa323d7c77d81768df60feeb1c374b1650a0c)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## [1.7 - 22.06.2025]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### Added
 | 
				
			||||||
 | 
					* Feature: plugins versions check (#310)
 | 
				
			||||||
 | 
					* New hooks: HOOK_ACCOUNT_MANAGE_AFTER_CHARACTERS, HOOK_GUILDS_AFTER_MANAGE_BUTTON (https://github.com/slawkens/myaac/commit/c074a48f245df55646b6705737f667b6a84149b2, https://github.com/slawkens/myaac/commit/e6100a1b72de8695bba1dae9ba4e28bfdce47b10)
 | 
				
			||||||
 | 
					* Add OTS_Toolbox::getVocationName(id, promotion) + OTS_Player->isNameLocked() (https://github.com/slawkens/myaac/commit/e222957893c4a1de0dc8dbba55bce1a43418d275, https://github.com/slawkens/myaac/commit/522f6c11d835afd36fd07a07074d96d7e219b488)
 | 
				
			||||||
 | 
					* Add missing csrf in more places, causing white page with error about Request (https://github.com/slawkens/myaac/commit/dca904e61d21d856bf809070e7652803a2df0f58, https://github.com/slawkens/myaac/commit/c720ccc451ff90ef40b2a1595468d061ffd7e1e4)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### Changed
 | 
				
			||||||
 | 
					* Revamped online page (https://github.com/slawkens/myaac/commit/9a90e4aae280e607430511c6727d9a714b11f4c5, https://github.com/slawkens/myaac/commit/4767120043b09141870383e249f3729638d53dc2)
 | 
				
			||||||
 | 
					* Better $title inventing (https://github.com/slawkens/myaac/commit/0c95bcfd06b68b21512e477646ef7bd3a0d4912b)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### Fixed
 | 
				
			||||||
 | 
					* Use apcu cache clear (https://github.com/slawkens/myaac/commit/b329da52aae9d0e21120a6444d3caf442420ce50, https://github.com/slawkens/myaac/commit/566c2a9151ab6392286f74e26853faa19a1b4f24)
 | 
				
			||||||
 | 
					* fix: boostedcreatures for 13.40 (by @GooseWithAKnife) (#307)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## [1.6.1 - 11.06.2025]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### Fixed
 | 
				
			||||||
 | 
					* Fixed "Request has been cancelled due to security reasons", cause of missing csrf() in twig files (https://github.com/slawkens/myaac/commit/10cd71a6630ffec91b43a26a6d685b66c5836a6a)
 | 
				
			||||||
 | 
					* Fix: Ignore duplicated route exception (https://github.com/slawkens/myaac/commit/9d8e9d27bd87167d8d4005942a6af62bfe4c0892)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### Changed
 | 
				
			||||||
 | 
					* Move counter & visitors code before router (In case someone wants to include that info on page) (https://github.com/slawkens/myaac/commit/f78285030708ad3c74ab048711f73bbf3ee5281e)
 | 
				
			||||||
 | 
					* Set TinyMCE license key to gpl (Avoid warning message in browser console) (https://github.com/slawkens/myaac/commit/8d29fdb98b92dbc3d2853ef88a185c67036b4a77)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### Removed
 | 
				
			||||||
 | 
					* Remove deprecated TinyMCE plugin - template (https://github.com/slawkens/myaac/commit/309c1fb715b882e67cb673b1544a03befbf64a22)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## [1.6 - 03.06.2025]
 | 
					## [1.6 - 03.06.2025]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### Added
 | 
					### Added
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										4
									
								
								aac
									
									
									
									
									
								
							
							
						
						
									
										4
									
								
								aac
									
									
									
									
									
								
							@@ -25,7 +25,9 @@ foreach ($commandsGlob as $item) {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	$commandPre = '\\MyAAC\Commands\\';
 | 
						$commandPre = '\\MyAAC\Commands\\';
 | 
				
			||||||
	$application->add(new ($commandPre . $name));
 | 
						if (!trait_exists($class = $commandPre . $name)) {
 | 
				
			||||||
 | 
							$application->add(new $class);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
$pluginCommands = Plugins::getCommands();
 | 
					$pluginCommands = Plugins::getCommands();
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -26,7 +26,6 @@ if (setting('core.account_country'))
 | 
				
			|||||||
$nameOrNumberColumn = getAccountIdentityColumn();
 | 
					$nameOrNumberColumn = getAccountIdentityColumn();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
$hasSecretColumn = $db->hasColumn('accounts', 'secret');
 | 
					$hasSecretColumn = $db->hasColumn('accounts', 'secret');
 | 
				
			||||||
$hasCoinsColumn = $db->hasColumn('accounts', 'coins');
 | 
					 | 
				
			||||||
$hasPointsColumn = $db->hasColumn('accounts', 'premium_points');
 | 
					$hasPointsColumn = $db->hasColumn('accounts', 'premium_points');
 | 
				
			||||||
$hasTypeColumn = $db->hasColumn('accounts', 'type');
 | 
					$hasTypeColumn = $db->hasColumn('accounts', 'type');
 | 
				
			||||||
$hasGroupColumn = $db->hasColumn('accounts', 'group_id');
 | 
					$hasGroupColumn = $db->hasColumn('accounts', 'group_id');
 | 
				
			||||||
@@ -137,10 +136,17 @@ else if (isset($_REQUEST['search'])) {
 | 
				
			|||||||
				$errors['email'] = Validator::getLastError();
 | 
									$errors['email'] = Validator::getLastError();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			// tibia coins
 | 
								// tibia coins
 | 
				
			||||||
			if ($hasCoinsColumn) {
 | 
								if (HAS_ACCOUNT_COINS) {
 | 
				
			||||||
				$t_coins = $_POST['t_coins'];
 | 
									$t_coins = $_POST['t_coins'];
 | 
				
			||||||
				verify_number($t_coins, 'Tibia coins', 12);
 | 
									verify_number($t_coins, 'Tibia coins', 12);
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								// transferable tibia coins
 | 
				
			||||||
 | 
								if (HAS_ACCOUNT_COINS_TRANSFERABLE || HAS_ACCOUNT_TRANSFERABLE_COINS) {
 | 
				
			||||||
 | 
									$t_coins_transferable = $_POST['t_coins_transferable'];
 | 
				
			||||||
 | 
									verify_number($t_coins_transferable, 'Transferable Tibia coins', 12);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			// prem days
 | 
								// prem days
 | 
				
			||||||
			$p_days = (int)$_POST['p_days'];
 | 
								$p_days = (int)$_POST['p_days'];
 | 
				
			||||||
			verify_number($p_days, 'Prem days', 11);
 | 
								verify_number($p_days, 'Prem days', 11);
 | 
				
			||||||
@@ -185,12 +191,18 @@ else if (isset($_REQUEST['search'])) {
 | 
				
			|||||||
				if ($hasSecretColumn) {
 | 
									if ($hasSecretColumn) {
 | 
				
			||||||
					$account->setCustomField('secret', $secret);
 | 
										$account->setCustomField('secret', $secret);
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				$account->setCustomField('key', $key);
 | 
									$account->setCustomField('key', $key);
 | 
				
			||||||
				$account->setEMail($email);
 | 
									$account->setEMail($email);
 | 
				
			||||||
				if ($hasCoinsColumn) {
 | 
					
 | 
				
			||||||
 | 
									if (HAS_ACCOUNT_COINS) {
 | 
				
			||||||
					$account->setCustomField('coins', $t_coins);
 | 
										$account->setCustomField('coins', $t_coins);
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									if (HAS_ACCOUNT_COINS_TRANSFERABLE || HAS_ACCOUNT_TRANSFERABLE_COINS) {
 | 
				
			||||||
 | 
										$account->setCustomField(ACCOUNT_COINS_TRANSFERABLE_COLUMN, $t_coins_transferable);
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				$lastDay = 0;
 | 
									$lastDay = 0;
 | 
				
			||||||
				if($p_days != 0 && $p_days != OTS_Account::GRATIS_PREMIUM_DAYS) {
 | 
									if($p_days != 0 && $p_days != OTS_Account::GRATIS_PREMIUM_DAYS) {
 | 
				
			||||||
					$lastDay = time();
 | 
										$lastDay = time();
 | 
				
			||||||
@@ -223,9 +235,6 @@ else if (isset($_REQUEST['search'])) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
					$password = encrypt($password);
 | 
										$password = encrypt($password);
 | 
				
			||||||
					$account->setPassword($password);
 | 
										$account->setPassword($password);
 | 
				
			||||||
 | 
					 | 
				
			||||||
					if (USE_ACCOUNT_SALT)
 | 
					 | 
				
			||||||
						$account->setCustomField('salt', $salt);
 | 
					 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				$account->save();
 | 
									$account->save();
 | 
				
			||||||
@@ -395,12 +404,18 @@ else if (isset($_REQUEST['search'])) {
 | 
				
			|||||||
										<label for="email">Email:</label><?php echo (setting('core.mail_enabled') ? ' (<a href="' . ADMIN_URL . '?p=mailer&mail_to=' . $account->getEMail() . '">Send Mail</a>)' : ''); ?>
 | 
															<label for="email">Email:</label><?php echo (setting('core.mail_enabled') ? ' (<a href="' . ADMIN_URL . '?p=mailer&mail_to=' . $account->getEMail() . '">Send Mail</a>)' : ''); ?>
 | 
				
			||||||
										<input type="text" class="form-control" id="email" name="email" autocomplete="off" value="<?php echo $account->getEMail(); ?>"/>
 | 
															<input type="text" class="form-control" id="email" name="email" autocomplete="off" value="<?php echo $account->getEMail(); ?>"/>
 | 
				
			||||||
									</div>
 | 
														</div>
 | 
				
			||||||
									<?php if ($hasCoinsColumn): ?>
 | 
														<?php if (HAS_ACCOUNT_COINS): ?>
 | 
				
			||||||
										<div class="col-12 col-sm-12 col-lg-6">
 | 
															<div class="col-12 col-sm-12 col-lg-6">
 | 
				
			||||||
											<label for="t_coins">Tibia Coins:</label>
 | 
																<label for="t_coins">Tibia Coins:</label>
 | 
				
			||||||
											<input type="text" class="form-control" id="t_coins" name="t_coins" autocomplete="off" maxlength="11" value="<?php echo $account->getCustomField('coins') ?>"/>
 | 
																<input type="text" class="form-control" id="t_coins" name="t_coins" autocomplete="off" maxlength="11" value="<?php echo $account->getCustomField('coins') ?>"/>
 | 
				
			||||||
										</div>
 | 
															</div>
 | 
				
			||||||
									<?php endif; ?>
 | 
														<?php endif; ?>
 | 
				
			||||||
 | 
														<?php if (HAS_ACCOUNT_COINS_TRANSFERABLE || HAS_ACCOUNT_TRANSFERABLE_COINS): ?>
 | 
				
			||||||
 | 
															<div class="col-12 col-sm-12 col-lg-6">
 | 
				
			||||||
 | 
																<label for="t_coins_transferable">Transferable Tibia Coins:</label>
 | 
				
			||||||
 | 
																<input type="text" class="form-control" id="t_coins_transferable" name="t_coins_transferable" autocomplete="off" maxlength="11" value="<?php echo $account->getCustomField(ACCOUNT_COINS_TRANSFERABLE_COLUMN) ?>"/>
 | 
				
			||||||
 | 
															</div>
 | 
				
			||||||
 | 
														<?php endif; ?>
 | 
				
			||||||
									<div class="col-12 col-sm-12 col-lg-6">
 | 
														<div class="col-12 col-sm-12 col-lg-6">
 | 
				
			||||||
										<label for="p_days">Premium Days:</label>
 | 
															<label for="p_days">Premium Days:</label>
 | 
				
			||||||
										<input type="text" class="form-control" id="p_days" name="p_days" autocomplete="off" maxlength="11" value="<?php echo $account->getPremDays(); ?>"/>
 | 
															<input type="text" class="form-control" id="p_days" name="p_days" autocomplete="off" maxlength="11" value="<?php echo $account->getPremDays(); ?>"/>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -25,9 +25,10 @@ if (!setting('core.mail_enabled')) {
 | 
				
			|||||||
	return;
 | 
						return;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
$mail_to = isset($_POST['mail_to']) ? stripslashes(trim($_POST['mail_to'])) : null;
 | 
					$mail_to = isset($_REQUEST['mail_to']) ? stripslashes(trim($_REQUEST['mail_to'])) : null;
 | 
				
			||||||
$mail_subject = isset($_POST['mail_subject']) ? stripslashes($_POST['mail_subject']) : null;
 | 
					$mail_subject = isset($_POST['mail_subject']) ? stripslashes($_POST['mail_subject']) : null;
 | 
				
			||||||
$mail_content = isset($_POST['mail_content']) ? stripslashes($_POST['mail_content']) : null;
 | 
					$mail_content = isset($_POST['mail_content']) ? stripslashes($_POST['mail_content']) : null;
 | 
				
			||||||
 | 
					$mail_verified_only = $_POST['mail_verified_only'] ?? false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
if (isset($_POST['submit'])) {
 | 
					if (isset($_POST['submit'])) {
 | 
				
			||||||
	if (empty($mail_subject)) {
 | 
						if (empty($mail_subject)) {
 | 
				
			||||||
@@ -58,14 +59,14 @@ if (!empty($mail_content) && !empty($mail_subject) && empty($mail_to)) {
 | 
				
			|||||||
	$success = 0;
 | 
						$success = 0;
 | 
				
			||||||
	$failed = 0;
 | 
						$failed = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	$add = '';
 | 
						$query = Account::where('email', '!=', '');
 | 
				
			||||||
	if (setting('core.account_mail_verify')) {
 | 
					
 | 
				
			||||||
		note('Note: Sending only to users with verified E-Mail.');
 | 
						if ($mail_verified_only) {
 | 
				
			||||||
		$add = ' AND `email_verified` = 1';
 | 
							info('Note: Sending only to users with verified E-Mail.');
 | 
				
			||||||
 | 
							$query->where('email_verified', 1);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	$query = Account::where('email', '!=', '')->get(['email']);
 | 
						foreach ($query->get(['email']) as $email) {
 | 
				
			||||||
	foreach ($query as $email) {
 | 
					 | 
				
			||||||
		if (_mail($email->email, $mail_subject, $mail_content)) {
 | 
							if (_mail($email->email, $mail_subject, $mail_content)) {
 | 
				
			||||||
			$success++;
 | 
								$success++;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
@@ -84,5 +85,6 @@ if (!empty($mail_content) && !empty($mail_subject) && empty($mail_to)) {
 | 
				
			|||||||
$twig->display('admin.mailer.html.twig', [
 | 
					$twig->display('admin.mailer.html.twig', [
 | 
				
			||||||
	'mail_to' => $mail_to,
 | 
						'mail_to' => $mail_to,
 | 
				
			||||||
	'mail_subject' => $mail_subject,
 | 
						'mail_subject' => $mail_subject,
 | 
				
			||||||
	'mail_content' => $mail_content
 | 
						'mail_content' => $mail_content,
 | 
				
			||||||
 | 
						'mail_verified_only' => $mail_verified_only,
 | 
				
			||||||
]);
 | 
					]);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -6,6 +6,7 @@
 | 
				
			|||||||
 * @package   MyAAC
 | 
					 * @package   MyAAC
 | 
				
			||||||
 * @author    Slawkens <slawkens@gmail.com>
 | 
					 * @author    Slawkens <slawkens@gmail.com>
 | 
				
			||||||
 * @author    Lee
 | 
					 * @author    Lee
 | 
				
			||||||
 | 
					 * @author    gpedro
 | 
				
			||||||
 * @copyright 2020 MyAAC
 | 
					 * @copyright 2020 MyAAC
 | 
				
			||||||
 * @link      https://my-aac.org
 | 
					 * @link      https://my-aac.org
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
@@ -18,11 +19,10 @@ $title = 'Mass Account Actions';
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
csrfProtect();
 | 
					csrfProtect();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
$hasCoinsColumn = $db->hasColumn('accounts', 'coins');
 | 
					 | 
				
			||||||
$hasPointsColumn = $db->hasColumn('accounts', 'premium_points');
 | 
					$hasPointsColumn = $db->hasColumn('accounts', 'premium_points');
 | 
				
			||||||
$freePremium = $config['lua']['freePremium'];
 | 
					$freePremium = getBoolean(configLua('freePremium'));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function admin_give_points($points)
 | 
					function admin_give_points($points): void
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	global $hasPointsColumn;
 | 
						global $hasPointsColumn;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -38,11 +38,9 @@ function admin_give_points($points)
 | 
				
			|||||||
	displayMessage($points . ' points added to all accounts.', true);
 | 
						displayMessage($points . ' points added to all accounts.', true);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function admin_give_coins($coins)
 | 
					function admin_give_coins($coins): void
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	global $hasCoinsColumn;
 | 
						if (!HAS_ACCOUNT_COINS) {
 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (!$hasCoinsColumn) {
 | 
					 | 
				
			||||||
		displayMessage('Coins not supported.');
 | 
							displayMessage('Coins not supported.');
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -55,7 +53,7 @@ function admin_give_coins($coins)
 | 
				
			|||||||
	displayMessage($coins . ' coins added to all accounts.', true);
 | 
						displayMessage($coins . ' coins added to all accounts.', true);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function admin_give_premdays($days)
 | 
					function admin_give_premdays($days): void
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	global $db, $freePremium;
 | 
						global $db, $freePremium;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -66,6 +64,7 @@ function admin_give_premdays($days)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	$value = $days * 86400;
 | 
						$value = $days * 86400;
 | 
				
			||||||
	$now = time();
 | 
						$now = time();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// othire
 | 
						// othire
 | 
				
			||||||
	if ($db->hasColumn('accounts', 'premend')) {
 | 
						if ($db->hasColumn('accounts', 'premend')) {
 | 
				
			||||||
		// append premend
 | 
							// append premend
 | 
				
			||||||
@@ -73,14 +72,11 @@ function admin_give_premdays($days)
 | 
				
			|||||||
			// set premend
 | 
								// set premend
 | 
				
			||||||
			if (Account::where('premend', '<=', $now)->update(['premend' => $now + $value])) {
 | 
								if (Account::where('premend', '<=', $now)->update(['premend' => $now + $value])) {
 | 
				
			||||||
				displayMessage($days . ' premium days added to all accounts.', true);
 | 
									displayMessage($days . ' premium days added to all accounts.', true);
 | 
				
			||||||
				return;
 | 
					 | 
				
			||||||
			} else {
 | 
								} else {
 | 
				
			||||||
				displayMessage('Failed to execute set query.');
 | 
									displayMessage('Failed to execute set query.');
 | 
				
			||||||
				return;
 | 
					 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		} else {
 | 
							} else {
 | 
				
			||||||
			displayMessage('Failed to execute append query.');
 | 
								displayMessage('Failed to execute append query.');
 | 
				
			||||||
			return;
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
@@ -95,20 +91,14 @@ function admin_give_premdays($days)
 | 
				
			|||||||
				// set lastday
 | 
									// set lastday
 | 
				
			||||||
				if (Account::where('lastday', '<=', $now)->update(['lastday' => $now + $value])) {
 | 
									if (Account::where('lastday', '<=', $now)->update(['lastday' => $now + $value])) {
 | 
				
			||||||
					displayMessage($days . ' premium days added to all accounts.', true);
 | 
										displayMessage($days . ' premium days added to all accounts.', true);
 | 
				
			||||||
					return;
 | 
					 | 
				
			||||||
				} else {
 | 
									} else {
 | 
				
			||||||
					displayMessage('Failed to execute set query.');
 | 
										displayMessage('Failed to execute set query.');
 | 
				
			||||||
					return;
 | 
					 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
 | 
					 | 
				
			||||||
				return;
 | 
					 | 
				
			||||||
			} else {
 | 
								} else {
 | 
				
			||||||
				displayMessage('Failed to execute append query.');
 | 
									displayMessage('Failed to execute append query.');
 | 
				
			||||||
				return;
 | 
					 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		} else {
 | 
							} else {
 | 
				
			||||||
			displayMessage('Failed to execute set days query.');
 | 
								displayMessage('Failed to execute set days query.');
 | 
				
			||||||
			return;
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
@@ -121,14 +111,11 @@ function admin_give_premdays($days)
 | 
				
			|||||||
			// set premium_ends_at
 | 
								// set premium_ends_at
 | 
				
			||||||
			if (Account::where('premium_ends_at', '<=', $now)->update(['premium_ends_at' => $now + $value])) {
 | 
								if (Account::where('premium_ends_at', '<=', $now)->update(['premium_ends_at' => $now + $value])) {
 | 
				
			||||||
				displayMessage($days . ' premium days added to all accounts.', true);
 | 
									displayMessage($days . ' premium days added to all accounts.', true);
 | 
				
			||||||
				return;
 | 
					 | 
				
			||||||
			} else {
 | 
								} else {
 | 
				
			||||||
				displayMessage('Failed to execute set query.');
 | 
									displayMessage('Failed to execute set query.');
 | 
				
			||||||
				return;
 | 
					 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		} else {
 | 
							} else {
 | 
				
			||||||
			displayMessage('Failed to execute append query.');
 | 
								displayMessage('Failed to execute append query.');
 | 
				
			||||||
			return;
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
@@ -167,19 +154,20 @@ if (!empty(ACTION) && isRequestMethod('post')) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
else {
 | 
					else {
 | 
				
			||||||
	$twig->display('admin.tools.account.html.twig', array(
 | 
						$twig->display('admin.tools.account.html.twig', array(
 | 
				
			||||||
		'hasCoinsColumn' => $hasCoinsColumn,
 | 
							'hasCoinsColumn' => HAS_ACCOUNT_COINS,
 | 
				
			||||||
		'hasPointsColumn' => $hasPointsColumn,
 | 
							'hasPointsColumn' => $hasPointsColumn,
 | 
				
			||||||
		'freePremium' => $freePremium,
 | 
							'freePremium' => $freePremium,
 | 
				
			||||||
	));
 | 
						));
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function displayMessage($message, $success = false) {
 | 
					function displayMessage($message, $success = false): void
 | 
				
			||||||
	global $twig, $hasCoinsColumn, $hasPointsColumn, $freePremium;
 | 
					{
 | 
				
			||||||
 | 
						global $twig, $hasPointsColumn, $freePremium;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	$success ? success($message): error($message);
 | 
						$success ? success($message): error($message);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	$twig->display('admin.tools.account.html.twig', array(
 | 
						$twig->display('admin.tools.account.html.twig', array(
 | 
				
			||||||
		'hasCoinsColumn' => $hasCoinsColumn,
 | 
							'hasCoinsColumn' => HAS_ACCOUNT_COINS,
 | 
				
			||||||
		'hasPointsColumn' => $hasPointsColumn,
 | 
							'hasPointsColumn' => $hasPointsColumn,
 | 
				
			||||||
		'freePremium' => $freePremium,
 | 
							'freePremium' => $freePremium,
 | 
				
			||||||
	));
 | 
						));
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -6,7 +6,7 @@ defined('MYAAC') or die('Direct access not allowed!');
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
$coins = 0;
 | 
					$coins = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
if ($db->hasColumn('accounts', 'coins')) {
 | 
					if (HAS_ACCOUNT_COINS) {
 | 
				
			||||||
	$whatToGet = ['id', 'coins'];
 | 
						$whatToGet = ['id', 'coins'];
 | 
				
			||||||
	if (USE_ACCOUNT_NAME) {
 | 
						if (USE_ACCOUNT_NAME) {
 | 
				
			||||||
		$whatToGet[] = 'name';
 | 
							$whatToGet[] = 'name';
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -669,12 +669,18 @@ else if (isset($_REQUEST['search'])) {
 | 
				
			|||||||
									<div class="col-12 col-sm-12 col-lg-6">
 | 
														<div class="col-12 col-sm-12 col-lg-6">
 | 
				
			||||||
										<label for="lastip" class="control-label">Last IP:</label>
 | 
															<label for="lastip" class="control-label">Last IP:</label>
 | 
				
			||||||
										<input type="text" class="form-control" id="lastip" name="lastip" autocomplete="off" maxlength="10" value="<?php
 | 
															<input type="text" class="form-control" id="lastip" name="lastip" autocomplete="off" maxlength="10" value="<?php
 | 
				
			||||||
										if (strlen($player->getLastIP()) > 11) {
 | 
															$lastIPColumnInfo = $db->getColumnInfo('players', 'lastip');
 | 
				
			||||||
 | 
															if ($lastIPColumnInfo && is_array($lastIPColumnInfo)) {
 | 
				
			||||||
 | 
																if (str_contains($lastIPColumnInfo['type'], 'varbinary')) {
 | 
				
			||||||
												echo inet_ntop($player->getLastIP());
 | 
																	echo inet_ntop($player->getLastIP());
 | 
				
			||||||
											}
 | 
																}
 | 
				
			||||||
											else {
 | 
																else {
 | 
				
			||||||
												echo longToIp($player->getLastIP());
 | 
																	echo longToIp($player->getLastIP());
 | 
				
			||||||
											}
 | 
																}
 | 
				
			||||||
 | 
															}
 | 
				
			||||||
 | 
															else {
 | 
				
			||||||
 | 
																echo 'Error';
 | 
				
			||||||
 | 
															}
 | 
				
			||||||
										?>" readonly/>
 | 
															?>" readonly/>
 | 
				
			||||||
									</div>
 | 
														</div>
 | 
				
			||||||
								</div>
 | 
													</div>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -51,6 +51,56 @@ else {
 | 
				
			|||||||
		} else {
 | 
							} else {
 | 
				
			||||||
			error('Error while disabling plugin ' . $disable . ': ' . Plugins::getError());
 | 
								error('Error while disabling plugin ' . $disable . ': ' . Plugins::getError());
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						else if (isset($_GET['check-updates'])) {
 | 
				
			||||||
 | 
							$repoUri = $config['admin_plugins_api_uri'] ?? 'https://plugins.my-aac.org/api/';
 | 
				
			||||||
 | 
							success("Fetching latest info from $repoUri..");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							$adminPlugins = new \MyAAC\Admin\Plugins();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							$adminPlugins->setApiBaseUri($repoUri);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							try {
 | 
				
			||||||
 | 
								$plugins = $adminPlugins->getLatestVersions();
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							catch (Exception $e) {
 | 
				
			||||||
 | 
								error($e->getMessage());
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (isset($plugins) && count($plugins) > 0) {
 | 
				
			||||||
 | 
								$outdated = [];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								foreach (get_plugins(true) as $plugin) {
 | 
				
			||||||
 | 
									$string = file_get_contents(BASE . 'plugins/' . $plugin . '.json');
 | 
				
			||||||
 | 
									$plugin_info = json_decode($string, true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									if (!$plugin_info) {
 | 
				
			||||||
 | 
										continue;
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									$disabled = (str_contains($plugin, 'disabled.'));
 | 
				
			||||||
 | 
									$pluginOriginal = ($disabled ? str_replace('disabled.', '', $plugin) : $plugin);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									$info = $plugins[$pluginOriginal] ?? false;
 | 
				
			||||||
 | 
									if ($info && version_compare($info['version'], $plugin_info['version'], '>')) {
 | 
				
			||||||
 | 
										$outdated[] = [
 | 
				
			||||||
 | 
											'name' => $pluginOriginal,
 | 
				
			||||||
 | 
											'yourVersion' => $plugin_info['version'],
 | 
				
			||||||
 | 
											'latestVersion' => $info['version'],
 | 
				
			||||||
 | 
											'link' => $info['link'] ?? 'Unknown',
 | 
				
			||||||
 | 
											'download_link' => $info['download_link'] ?? 'Unknown',
 | 
				
			||||||
 | 
										];
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if (count($outdated) > 0) {
 | 
				
			||||||
 | 
									info('Following updates have been found for your plugins:');
 | 
				
			||||||
 | 
									$twig->display('admin.plugins.outdated.html.twig', ['plugins' => $outdated]);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								else {
 | 
				
			||||||
 | 
									success('All plugins up to date!');
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
	} else if (isset($_FILES['plugin']['name'])) {
 | 
						} else if (isset($_FILES['plugin']['name'])) {
 | 
				
			||||||
		$file = $_FILES['plugin'];
 | 
							$file = $_FILES['plugin'];
 | 
				
			||||||
		$filename = $file['name'];
 | 
							$filename = $file['name'];
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -19,8 +19,7 @@ $use_datatable = true;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
if (!setting('core.visitors_counter')): ?>
 | 
					if (!setting('core.visitors_counter')): ?>
 | 
				
			||||||
	Visitors counter is disabled.<br/>
 | 
						Visitors counter is disabled.<br/>
 | 
				
			||||||
	You can enable it by editing this configurable in <b>config.local.php</b> file:<br/>
 | 
						You can enable it in Settings -> General -> Visitors Counter.<br/>
 | 
				
			||||||
	<p style="margin-left: 3em;"><b>$config['visitors_counter'] = true;</b></p>
 | 
					 | 
				
			||||||
	<?php
 | 
						<?php
 | 
				
			||||||
	return;
 | 
						return;
 | 
				
			||||||
endif;
 | 
					endif;
 | 
				
			||||||
@@ -46,7 +45,7 @@ foreach ($tmp as &$visitor) {
 | 
				
			|||||||
		if ($dd->isBot()) {
 | 
							if ($dd->isBot()) {
 | 
				
			||||||
			$bot = $dd->getBot();
 | 
								$bot = $dd->getBot();
 | 
				
			||||||
			$message = '(Bot) %s, <a href="%s" target="_blank">%s</a>';
 | 
								$message = '(Bot) %s, <a href="%s" target="_blank">%s</a>';
 | 
				
			||||||
			$browser = sprintf($message, $bot['category'], $bot['url'], $bot['name']);
 | 
								$browser = sprintf($message, $bot['category'] ?? 'Unknown', $bot['url'] ?? '', $bot['name'] ?? 'Unknown name');
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		else {
 | 
							else {
 | 
				
			||||||
			$osFamily = OperatingSystem::getOsFamily($dd->getOs('name'));
 | 
								$osFamily = OperatingSystem::getOsFamily($dd->getOs('name'));
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,5 +1,6 @@
 | 
				
			|||||||
<?php
 | 
					<?php
 | 
				
			||||||
define('MYAAC_ADMIN', true);
 | 
					const MYAAC_ADMIN = true;
 | 
				
			||||||
 | 
					const IGNORE_SET_LAST_VISIT = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
require '../../common.php';
 | 
					require '../../common.php';
 | 
				
			||||||
require SYSTEM . 'functions.php';
 | 
					require SYSTEM . 'functions.php';
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -26,6 +26,7 @@
 | 
				
			|||||||
use MyAAC\DataLoader;
 | 
					use MyAAC\DataLoader;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const MYAAC_ADMIN = true;
 | 
					const MYAAC_ADMIN = true;
 | 
				
			||||||
 | 
					const IGNORE_SET_LAST_VISIT = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
require '../../common.php';
 | 
					require '../../common.php';
 | 
				
			||||||
require SYSTEM . 'functions.php';
 | 
					require SYSTEM . 'functions.php';
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,9 +1,9 @@
 | 
				
			|||||||
<?php
 | 
					<?php
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use MyAAC\Hooks;
 | 
					 | 
				
			||||||
use MyAAC\Settings;
 | 
					use MyAAC\Settings;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const MYAAC_ADMIN = true;
 | 
					const MYAAC_ADMIN = true;
 | 
				
			||||||
 | 
					const IGNORE_SET_LAST_VISIT = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
require '../../common.php';
 | 
					require '../../common.php';
 | 
				
			||||||
require SYSTEM . 'functions.php';
 | 
					require SYSTEM . 'functions.php';
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,5 +1,6 @@
 | 
				
			|||||||
<?php
 | 
					<?php
 | 
				
			||||||
define('MYAAC_ADMIN', true);
 | 
					const MYAAC_ADMIN = true;
 | 
				
			||||||
 | 
					const IGNORE_SET_LAST_VISIT = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
require '../../common.php';
 | 
					require '../../common.php';
 | 
				
			||||||
require SYSTEM . 'init.php';
 | 
					require SYSTEM . 'init.php';
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,5 +1,6 @@
 | 
				
			|||||||
<?php
 | 
					<?php
 | 
				
			||||||
define('MYAAC_ADMIN', true);
 | 
					const MYAAC_ADMIN = true;
 | 
				
			||||||
 | 
					const IGNORE_SET_LAST_VISIT = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
require '../../common.php';
 | 
					require '../../common.php';
 | 
				
			||||||
require SYSTEM . 'functions.php';
 | 
					require SYSTEM . 'functions.php';
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -26,8 +26,8 @@
 | 
				
			|||||||
if (version_compare(phpversion(), '8.1', '<')) die('PHP version 8.1 or higher is required.');
 | 
					if (version_compare(phpversion(), '8.1', '<')) die('PHP version 8.1 or higher is required.');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const MYAAC = true;
 | 
					const MYAAC = true;
 | 
				
			||||||
const MYAAC_VERSION = '1.6';
 | 
					const MYAAC_VERSION = '1.8.5-dev';
 | 
				
			||||||
const DATABASE_VERSION = 45;
 | 
					const DATABASE_VERSION = 46;
 | 
				
			||||||
const TABLE_PREFIX = 'myaac_';
 | 
					const TABLE_PREFIX = 'myaac_';
 | 
				
			||||||
define('START_TIME', microtime(true));
 | 
					define('START_TIME', microtime(true));
 | 
				
			||||||
define('MYAAC_OS', stripos(PHP_OS, 'WIN') === 0 ? 'WINDOWS' : (strtoupper(PHP_OS) === 'DARWIN' ? 'MAC' : 'LINUX'));
 | 
					define('MYAAC_OS', stripos(PHP_OS, 'WIN') === 0 ? 'WINDOWS' : (strtoupper(PHP_OS) === 'DARWIN' ? 'MAC' : 'LINUX'));
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -18,7 +18,8 @@
 | 
				
			|||||||
        "symfony/string": "^6.4",
 | 
					        "symfony/string": "^6.4",
 | 
				
			||||||
        "symfony/var-dumper": "^6.4",
 | 
					        "symfony/var-dumper": "^6.4",
 | 
				
			||||||
        "filp/whoops": "^2.15",
 | 
					        "filp/whoops": "^2.15",
 | 
				
			||||||
        "maximebf/debugbar": "1.*"
 | 
					        "maximebf/debugbar": "1.*",
 | 
				
			||||||
 | 
					        "guzzlehttp/guzzle": "7.9.3"
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "require-dev": {
 | 
					    "require-dev": {
 | 
				
			||||||
        "phpstan/phpstan": "^1.10"
 | 
					        "phpstan/phpstan": "^1.10"
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										537
									
								
								composer.lock
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										537
									
								
								composer.lock
									
									
									
										generated
									
									
									
								
							@@ -4,7 +4,7 @@
 | 
				
			|||||||
        "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
 | 
					        "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
 | 
				
			||||||
        "This file is @generated automatically"
 | 
					        "This file is @generated automatically"
 | 
				
			||||||
    ],
 | 
					    ],
 | 
				
			||||||
    "content-hash": "be4d1489a53a9cd8eec6bcaa7a096f30",
 | 
					    "content-hash": "5317e97a5025ebc2a977214bd3fa964c",
 | 
				
			||||||
    "packages": [
 | 
					    "packages": [
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            "name": "brick/math",
 | 
					            "name": "brick/math",
 | 
				
			||||||
@@ -493,6 +493,331 @@
 | 
				
			|||||||
            ],
 | 
					            ],
 | 
				
			||||||
            "time": "2024-09-25T12:00:00+00:00"
 | 
					            "time": "2024-09-25T12:00:00+00:00"
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            "name": "guzzlehttp/guzzle",
 | 
				
			||||||
 | 
					            "version": "7.9.3",
 | 
				
			||||||
 | 
					            "source": {
 | 
				
			||||||
 | 
					                "type": "git",
 | 
				
			||||||
 | 
					                "url": "https://github.com/guzzle/guzzle.git",
 | 
				
			||||||
 | 
					                "reference": "7b2f29fe81dc4da0ca0ea7d42107a0845946ea77"
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            "dist": {
 | 
				
			||||||
 | 
					                "type": "zip",
 | 
				
			||||||
 | 
					                "url": "https://api.github.com/repos/guzzle/guzzle/zipball/7b2f29fe81dc4da0ca0ea7d42107a0845946ea77",
 | 
				
			||||||
 | 
					                "reference": "7b2f29fe81dc4da0ca0ea7d42107a0845946ea77",
 | 
				
			||||||
 | 
					                "shasum": ""
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            "require": {
 | 
				
			||||||
 | 
					                "ext-json": "*",
 | 
				
			||||||
 | 
					                "guzzlehttp/promises": "^1.5.3 || ^2.0.3",
 | 
				
			||||||
 | 
					                "guzzlehttp/psr7": "^2.7.0",
 | 
				
			||||||
 | 
					                "php": "^7.2.5 || ^8.0",
 | 
				
			||||||
 | 
					                "psr/http-client": "^1.0",
 | 
				
			||||||
 | 
					                "symfony/deprecation-contracts": "^2.2 || ^3.0"
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            "provide": {
 | 
				
			||||||
 | 
					                "psr/http-client-implementation": "1.0"
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            "require-dev": {
 | 
				
			||||||
 | 
					                "bamarni/composer-bin-plugin": "^1.8.2",
 | 
				
			||||||
 | 
					                "ext-curl": "*",
 | 
				
			||||||
 | 
					                "guzzle/client-integration-tests": "3.0.2",
 | 
				
			||||||
 | 
					                "php-http/message-factory": "^1.1",
 | 
				
			||||||
 | 
					                "phpunit/phpunit": "^8.5.39 || ^9.6.20",
 | 
				
			||||||
 | 
					                "psr/log": "^1.1 || ^2.0 || ^3.0"
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            "suggest": {
 | 
				
			||||||
 | 
					                "ext-curl": "Required for CURL handler support",
 | 
				
			||||||
 | 
					                "ext-intl": "Required for Internationalized Domain Name (IDN) support",
 | 
				
			||||||
 | 
					                "psr/log": "Required for using the Log middleware"
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            "type": "library",
 | 
				
			||||||
 | 
					            "extra": {
 | 
				
			||||||
 | 
					                "bamarni-bin": {
 | 
				
			||||||
 | 
					                    "bin-links": true,
 | 
				
			||||||
 | 
					                    "forward-command": false
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            "autoload": {
 | 
				
			||||||
 | 
					                "files": [
 | 
				
			||||||
 | 
					                    "src/functions_include.php"
 | 
				
			||||||
 | 
					                ],
 | 
				
			||||||
 | 
					                "psr-4": {
 | 
				
			||||||
 | 
					                    "GuzzleHttp\\": "src/"
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            "notification-url": "https://packagist.org/downloads/",
 | 
				
			||||||
 | 
					            "license": [
 | 
				
			||||||
 | 
					                "MIT"
 | 
				
			||||||
 | 
					            ],
 | 
				
			||||||
 | 
					            "authors": [
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    "name": "Graham Campbell",
 | 
				
			||||||
 | 
					                    "email": "hello@gjcampbell.co.uk",
 | 
				
			||||||
 | 
					                    "homepage": "https://github.com/GrahamCampbell"
 | 
				
			||||||
 | 
					                },
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    "name": "Michael Dowling",
 | 
				
			||||||
 | 
					                    "email": "mtdowling@gmail.com",
 | 
				
			||||||
 | 
					                    "homepage": "https://github.com/mtdowling"
 | 
				
			||||||
 | 
					                },
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    "name": "Jeremy Lindblom",
 | 
				
			||||||
 | 
					                    "email": "jeremeamia@gmail.com",
 | 
				
			||||||
 | 
					                    "homepage": "https://github.com/jeremeamia"
 | 
				
			||||||
 | 
					                },
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    "name": "George Mponos",
 | 
				
			||||||
 | 
					                    "email": "gmponos@gmail.com",
 | 
				
			||||||
 | 
					                    "homepage": "https://github.com/gmponos"
 | 
				
			||||||
 | 
					                },
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    "name": "Tobias Nyholm",
 | 
				
			||||||
 | 
					                    "email": "tobias.nyholm@gmail.com",
 | 
				
			||||||
 | 
					                    "homepage": "https://github.com/Nyholm"
 | 
				
			||||||
 | 
					                },
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    "name": "Márk Sági-Kazár",
 | 
				
			||||||
 | 
					                    "email": "mark.sagikazar@gmail.com",
 | 
				
			||||||
 | 
					                    "homepage": "https://github.com/sagikazarmark"
 | 
				
			||||||
 | 
					                },
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    "name": "Tobias Schultze",
 | 
				
			||||||
 | 
					                    "email": "webmaster@tubo-world.de",
 | 
				
			||||||
 | 
					                    "homepage": "https://github.com/Tobion"
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            ],
 | 
				
			||||||
 | 
					            "description": "Guzzle is a PHP HTTP client library",
 | 
				
			||||||
 | 
					            "keywords": [
 | 
				
			||||||
 | 
					                "client",
 | 
				
			||||||
 | 
					                "curl",
 | 
				
			||||||
 | 
					                "framework",
 | 
				
			||||||
 | 
					                "http",
 | 
				
			||||||
 | 
					                "http client",
 | 
				
			||||||
 | 
					                "psr-18",
 | 
				
			||||||
 | 
					                "psr-7",
 | 
				
			||||||
 | 
					                "rest",
 | 
				
			||||||
 | 
					                "web service"
 | 
				
			||||||
 | 
					            ],
 | 
				
			||||||
 | 
					            "support": {
 | 
				
			||||||
 | 
					                "issues": "https://github.com/guzzle/guzzle/issues",
 | 
				
			||||||
 | 
					                "source": "https://github.com/guzzle/guzzle/tree/7.9.3"
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            "funding": [
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    "url": "https://github.com/GrahamCampbell",
 | 
				
			||||||
 | 
					                    "type": "github"
 | 
				
			||||||
 | 
					                },
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    "url": "https://github.com/Nyholm",
 | 
				
			||||||
 | 
					                    "type": "github"
 | 
				
			||||||
 | 
					                },
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/guzzle",
 | 
				
			||||||
 | 
					                    "type": "tidelift"
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            ],
 | 
				
			||||||
 | 
					            "time": "2025-03-27T13:37:11+00:00"
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            "name": "guzzlehttp/promises",
 | 
				
			||||||
 | 
					            "version": "2.2.0",
 | 
				
			||||||
 | 
					            "source": {
 | 
				
			||||||
 | 
					                "type": "git",
 | 
				
			||||||
 | 
					                "url": "https://github.com/guzzle/promises.git",
 | 
				
			||||||
 | 
					                "reference": "7c69f28996b0a6920945dd20b3857e499d9ca96c"
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            "dist": {
 | 
				
			||||||
 | 
					                "type": "zip",
 | 
				
			||||||
 | 
					                "url": "https://api.github.com/repos/guzzle/promises/zipball/7c69f28996b0a6920945dd20b3857e499d9ca96c",
 | 
				
			||||||
 | 
					                "reference": "7c69f28996b0a6920945dd20b3857e499d9ca96c",
 | 
				
			||||||
 | 
					                "shasum": ""
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            "require": {
 | 
				
			||||||
 | 
					                "php": "^7.2.5 || ^8.0"
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            "require-dev": {
 | 
				
			||||||
 | 
					                "bamarni/composer-bin-plugin": "^1.8.2",
 | 
				
			||||||
 | 
					                "phpunit/phpunit": "^8.5.39 || ^9.6.20"
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            "type": "library",
 | 
				
			||||||
 | 
					            "extra": {
 | 
				
			||||||
 | 
					                "bamarni-bin": {
 | 
				
			||||||
 | 
					                    "bin-links": true,
 | 
				
			||||||
 | 
					                    "forward-command": false
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            "autoload": {
 | 
				
			||||||
 | 
					                "psr-4": {
 | 
				
			||||||
 | 
					                    "GuzzleHttp\\Promise\\": "src/"
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            "notification-url": "https://packagist.org/downloads/",
 | 
				
			||||||
 | 
					            "license": [
 | 
				
			||||||
 | 
					                "MIT"
 | 
				
			||||||
 | 
					            ],
 | 
				
			||||||
 | 
					            "authors": [
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    "name": "Graham Campbell",
 | 
				
			||||||
 | 
					                    "email": "hello@gjcampbell.co.uk",
 | 
				
			||||||
 | 
					                    "homepage": "https://github.com/GrahamCampbell"
 | 
				
			||||||
 | 
					                },
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    "name": "Michael Dowling",
 | 
				
			||||||
 | 
					                    "email": "mtdowling@gmail.com",
 | 
				
			||||||
 | 
					                    "homepage": "https://github.com/mtdowling"
 | 
				
			||||||
 | 
					                },
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    "name": "Tobias Nyholm",
 | 
				
			||||||
 | 
					                    "email": "tobias.nyholm@gmail.com",
 | 
				
			||||||
 | 
					                    "homepage": "https://github.com/Nyholm"
 | 
				
			||||||
 | 
					                },
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    "name": "Tobias Schultze",
 | 
				
			||||||
 | 
					                    "email": "webmaster@tubo-world.de",
 | 
				
			||||||
 | 
					                    "homepage": "https://github.com/Tobion"
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            ],
 | 
				
			||||||
 | 
					            "description": "Guzzle promises library",
 | 
				
			||||||
 | 
					            "keywords": [
 | 
				
			||||||
 | 
					                "promise"
 | 
				
			||||||
 | 
					            ],
 | 
				
			||||||
 | 
					            "support": {
 | 
				
			||||||
 | 
					                "issues": "https://github.com/guzzle/promises/issues",
 | 
				
			||||||
 | 
					                "source": "https://github.com/guzzle/promises/tree/2.2.0"
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            "funding": [
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    "url": "https://github.com/GrahamCampbell",
 | 
				
			||||||
 | 
					                    "type": "github"
 | 
				
			||||||
 | 
					                },
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    "url": "https://github.com/Nyholm",
 | 
				
			||||||
 | 
					                    "type": "github"
 | 
				
			||||||
 | 
					                },
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/promises",
 | 
				
			||||||
 | 
					                    "type": "tidelift"
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            ],
 | 
				
			||||||
 | 
					            "time": "2025-03-27T13:27:01+00:00"
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            "name": "guzzlehttp/psr7",
 | 
				
			||||||
 | 
					            "version": "2.7.1",
 | 
				
			||||||
 | 
					            "source": {
 | 
				
			||||||
 | 
					                "type": "git",
 | 
				
			||||||
 | 
					                "url": "https://github.com/guzzle/psr7.git",
 | 
				
			||||||
 | 
					                "reference": "c2270caaabe631b3b44c85f99e5a04bbb8060d16"
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            "dist": {
 | 
				
			||||||
 | 
					                "type": "zip",
 | 
				
			||||||
 | 
					                "url": "https://api.github.com/repos/guzzle/psr7/zipball/c2270caaabe631b3b44c85f99e5a04bbb8060d16",
 | 
				
			||||||
 | 
					                "reference": "c2270caaabe631b3b44c85f99e5a04bbb8060d16",
 | 
				
			||||||
 | 
					                "shasum": ""
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            "require": {
 | 
				
			||||||
 | 
					                "php": "^7.2.5 || ^8.0",
 | 
				
			||||||
 | 
					                "psr/http-factory": "^1.0",
 | 
				
			||||||
 | 
					                "psr/http-message": "^1.1 || ^2.0",
 | 
				
			||||||
 | 
					                "ralouphie/getallheaders": "^3.0"
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            "provide": {
 | 
				
			||||||
 | 
					                "psr/http-factory-implementation": "1.0",
 | 
				
			||||||
 | 
					                "psr/http-message-implementation": "1.0"
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            "require-dev": {
 | 
				
			||||||
 | 
					                "bamarni/composer-bin-plugin": "^1.8.2",
 | 
				
			||||||
 | 
					                "http-interop/http-factory-tests": "0.9.0",
 | 
				
			||||||
 | 
					                "phpunit/phpunit": "^8.5.39 || ^9.6.20"
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            "suggest": {
 | 
				
			||||||
 | 
					                "laminas/laminas-httphandlerrunner": "Emit PSR-7 responses"
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            "type": "library",
 | 
				
			||||||
 | 
					            "extra": {
 | 
				
			||||||
 | 
					                "bamarni-bin": {
 | 
				
			||||||
 | 
					                    "bin-links": true,
 | 
				
			||||||
 | 
					                    "forward-command": false
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            "autoload": {
 | 
				
			||||||
 | 
					                "psr-4": {
 | 
				
			||||||
 | 
					                    "GuzzleHttp\\Psr7\\": "src/"
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            "notification-url": "https://packagist.org/downloads/",
 | 
				
			||||||
 | 
					            "license": [
 | 
				
			||||||
 | 
					                "MIT"
 | 
				
			||||||
 | 
					            ],
 | 
				
			||||||
 | 
					            "authors": [
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    "name": "Graham Campbell",
 | 
				
			||||||
 | 
					                    "email": "hello@gjcampbell.co.uk",
 | 
				
			||||||
 | 
					                    "homepage": "https://github.com/GrahamCampbell"
 | 
				
			||||||
 | 
					                },
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    "name": "Michael Dowling",
 | 
				
			||||||
 | 
					                    "email": "mtdowling@gmail.com",
 | 
				
			||||||
 | 
					                    "homepage": "https://github.com/mtdowling"
 | 
				
			||||||
 | 
					                },
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    "name": "George Mponos",
 | 
				
			||||||
 | 
					                    "email": "gmponos@gmail.com",
 | 
				
			||||||
 | 
					                    "homepage": "https://github.com/gmponos"
 | 
				
			||||||
 | 
					                },
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    "name": "Tobias Nyholm",
 | 
				
			||||||
 | 
					                    "email": "tobias.nyholm@gmail.com",
 | 
				
			||||||
 | 
					                    "homepage": "https://github.com/Nyholm"
 | 
				
			||||||
 | 
					                },
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    "name": "Márk Sági-Kazár",
 | 
				
			||||||
 | 
					                    "email": "mark.sagikazar@gmail.com",
 | 
				
			||||||
 | 
					                    "homepage": "https://github.com/sagikazarmark"
 | 
				
			||||||
 | 
					                },
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    "name": "Tobias Schultze",
 | 
				
			||||||
 | 
					                    "email": "webmaster@tubo-world.de",
 | 
				
			||||||
 | 
					                    "homepage": "https://github.com/Tobion"
 | 
				
			||||||
 | 
					                },
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    "name": "Márk Sági-Kazár",
 | 
				
			||||||
 | 
					                    "email": "mark.sagikazar@gmail.com",
 | 
				
			||||||
 | 
					                    "homepage": "https://sagikazarmark.hu"
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            ],
 | 
				
			||||||
 | 
					            "description": "PSR-7 message implementation that also provides common utility methods",
 | 
				
			||||||
 | 
					            "keywords": [
 | 
				
			||||||
 | 
					                "http",
 | 
				
			||||||
 | 
					                "message",
 | 
				
			||||||
 | 
					                "psr-7",
 | 
				
			||||||
 | 
					                "request",
 | 
				
			||||||
 | 
					                "response",
 | 
				
			||||||
 | 
					                "stream",
 | 
				
			||||||
 | 
					                "uri",
 | 
				
			||||||
 | 
					                "url"
 | 
				
			||||||
 | 
					            ],
 | 
				
			||||||
 | 
					            "support": {
 | 
				
			||||||
 | 
					                "issues": "https://github.com/guzzle/psr7/issues",
 | 
				
			||||||
 | 
					                "source": "https://github.com/guzzle/psr7/tree/2.7.1"
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            "funding": [
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    "url": "https://github.com/GrahamCampbell",
 | 
				
			||||||
 | 
					                    "type": "github"
 | 
				
			||||||
 | 
					                },
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    "url": "https://github.com/Nyholm",
 | 
				
			||||||
 | 
					                    "type": "github"
 | 
				
			||||||
 | 
					                },
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/psr7",
 | 
				
			||||||
 | 
					                    "type": "tidelift"
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            ],
 | 
				
			||||||
 | 
					            "time": "2025-03-27T12:30:47+00:00"
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            "name": "illuminate/collections",
 | 
					            "name": "illuminate/collections",
 | 
				
			||||||
            "version": "v10.48.25",
 | 
					            "version": "v10.48.25",
 | 
				
			||||||
@@ -1472,6 +1797,166 @@
 | 
				
			|||||||
            },
 | 
					            },
 | 
				
			||||||
            "time": "2021-11-05T16:47:00+00:00"
 | 
					            "time": "2021-11-05T16:47:00+00:00"
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            "name": "psr/http-client",
 | 
				
			||||||
 | 
					            "version": "1.0.3",
 | 
				
			||||||
 | 
					            "source": {
 | 
				
			||||||
 | 
					                "type": "git",
 | 
				
			||||||
 | 
					                "url": "https://github.com/php-fig/http-client.git",
 | 
				
			||||||
 | 
					                "reference": "bb5906edc1c324c9a05aa0873d40117941e5fa90"
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            "dist": {
 | 
				
			||||||
 | 
					                "type": "zip",
 | 
				
			||||||
 | 
					                "url": "https://api.github.com/repos/php-fig/http-client/zipball/bb5906edc1c324c9a05aa0873d40117941e5fa90",
 | 
				
			||||||
 | 
					                "reference": "bb5906edc1c324c9a05aa0873d40117941e5fa90",
 | 
				
			||||||
 | 
					                "shasum": ""
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            "require": {
 | 
				
			||||||
 | 
					                "php": "^7.0 || ^8.0",
 | 
				
			||||||
 | 
					                "psr/http-message": "^1.0 || ^2.0"
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            "type": "library",
 | 
				
			||||||
 | 
					            "extra": {
 | 
				
			||||||
 | 
					                "branch-alias": {
 | 
				
			||||||
 | 
					                    "dev-master": "1.0.x-dev"
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            "autoload": {
 | 
				
			||||||
 | 
					                "psr-4": {
 | 
				
			||||||
 | 
					                    "Psr\\Http\\Client\\": "src/"
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            "notification-url": "https://packagist.org/downloads/",
 | 
				
			||||||
 | 
					            "license": [
 | 
				
			||||||
 | 
					                "MIT"
 | 
				
			||||||
 | 
					            ],
 | 
				
			||||||
 | 
					            "authors": [
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    "name": "PHP-FIG",
 | 
				
			||||||
 | 
					                    "homepage": "https://www.php-fig.org/"
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            ],
 | 
				
			||||||
 | 
					            "description": "Common interface for HTTP clients",
 | 
				
			||||||
 | 
					            "homepage": "https://github.com/php-fig/http-client",
 | 
				
			||||||
 | 
					            "keywords": [
 | 
				
			||||||
 | 
					                "http",
 | 
				
			||||||
 | 
					                "http-client",
 | 
				
			||||||
 | 
					                "psr",
 | 
				
			||||||
 | 
					                "psr-18"
 | 
				
			||||||
 | 
					            ],
 | 
				
			||||||
 | 
					            "support": {
 | 
				
			||||||
 | 
					                "source": "https://github.com/php-fig/http-client"
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            "time": "2023-09-23T14:17:50+00:00"
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            "name": "psr/http-factory",
 | 
				
			||||||
 | 
					            "version": "1.1.0",
 | 
				
			||||||
 | 
					            "source": {
 | 
				
			||||||
 | 
					                "type": "git",
 | 
				
			||||||
 | 
					                "url": "https://github.com/php-fig/http-factory.git",
 | 
				
			||||||
 | 
					                "reference": "2b4765fddfe3b508ac62f829e852b1501d3f6e8a"
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            "dist": {
 | 
				
			||||||
 | 
					                "type": "zip",
 | 
				
			||||||
 | 
					                "url": "https://api.github.com/repos/php-fig/http-factory/zipball/2b4765fddfe3b508ac62f829e852b1501d3f6e8a",
 | 
				
			||||||
 | 
					                "reference": "2b4765fddfe3b508ac62f829e852b1501d3f6e8a",
 | 
				
			||||||
 | 
					                "shasum": ""
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            "require": {
 | 
				
			||||||
 | 
					                "php": ">=7.1",
 | 
				
			||||||
 | 
					                "psr/http-message": "^1.0 || ^2.0"
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            "type": "library",
 | 
				
			||||||
 | 
					            "extra": {
 | 
				
			||||||
 | 
					                "branch-alias": {
 | 
				
			||||||
 | 
					                    "dev-master": "1.0.x-dev"
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            "autoload": {
 | 
				
			||||||
 | 
					                "psr-4": {
 | 
				
			||||||
 | 
					                    "Psr\\Http\\Message\\": "src/"
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            "notification-url": "https://packagist.org/downloads/",
 | 
				
			||||||
 | 
					            "license": [
 | 
				
			||||||
 | 
					                "MIT"
 | 
				
			||||||
 | 
					            ],
 | 
				
			||||||
 | 
					            "authors": [
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    "name": "PHP-FIG",
 | 
				
			||||||
 | 
					                    "homepage": "https://www.php-fig.org/"
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            ],
 | 
				
			||||||
 | 
					            "description": "PSR-17: Common interfaces for PSR-7 HTTP message factories",
 | 
				
			||||||
 | 
					            "keywords": [
 | 
				
			||||||
 | 
					                "factory",
 | 
				
			||||||
 | 
					                "http",
 | 
				
			||||||
 | 
					                "message",
 | 
				
			||||||
 | 
					                "psr",
 | 
				
			||||||
 | 
					                "psr-17",
 | 
				
			||||||
 | 
					                "psr-7",
 | 
				
			||||||
 | 
					                "request",
 | 
				
			||||||
 | 
					                "response"
 | 
				
			||||||
 | 
					            ],
 | 
				
			||||||
 | 
					            "support": {
 | 
				
			||||||
 | 
					                "source": "https://github.com/php-fig/http-factory"
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            "time": "2024-04-15T12:06:14+00:00"
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            "name": "psr/http-message",
 | 
				
			||||||
 | 
					            "version": "2.0",
 | 
				
			||||||
 | 
					            "source": {
 | 
				
			||||||
 | 
					                "type": "git",
 | 
				
			||||||
 | 
					                "url": "https://github.com/php-fig/http-message.git",
 | 
				
			||||||
 | 
					                "reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71"
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            "dist": {
 | 
				
			||||||
 | 
					                "type": "zip",
 | 
				
			||||||
 | 
					                "url": "https://api.github.com/repos/php-fig/http-message/zipball/402d35bcb92c70c026d1a6a9883f06b2ead23d71",
 | 
				
			||||||
 | 
					                "reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71",
 | 
				
			||||||
 | 
					                "shasum": ""
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            "require": {
 | 
				
			||||||
 | 
					                "php": "^7.2 || ^8.0"
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            "type": "library",
 | 
				
			||||||
 | 
					            "extra": {
 | 
				
			||||||
 | 
					                "branch-alias": {
 | 
				
			||||||
 | 
					                    "dev-master": "2.0.x-dev"
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            "autoload": {
 | 
				
			||||||
 | 
					                "psr-4": {
 | 
				
			||||||
 | 
					                    "Psr\\Http\\Message\\": "src/"
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            "notification-url": "https://packagist.org/downloads/",
 | 
				
			||||||
 | 
					            "license": [
 | 
				
			||||||
 | 
					                "MIT"
 | 
				
			||||||
 | 
					            ],
 | 
				
			||||||
 | 
					            "authors": [
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    "name": "PHP-FIG",
 | 
				
			||||||
 | 
					                    "homepage": "https://www.php-fig.org/"
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            ],
 | 
				
			||||||
 | 
					            "description": "Common interface for HTTP messages",
 | 
				
			||||||
 | 
					            "homepage": "https://github.com/php-fig/http-message",
 | 
				
			||||||
 | 
					            "keywords": [
 | 
				
			||||||
 | 
					                "http",
 | 
				
			||||||
 | 
					                "http-message",
 | 
				
			||||||
 | 
					                "psr",
 | 
				
			||||||
 | 
					                "psr-7",
 | 
				
			||||||
 | 
					                "request",
 | 
				
			||||||
 | 
					                "response"
 | 
				
			||||||
 | 
					            ],
 | 
				
			||||||
 | 
					            "support": {
 | 
				
			||||||
 | 
					                "source": "https://github.com/php-fig/http-message/tree/2.0"
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            "time": "2023-04-04T09:54:51+00:00"
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            "name": "psr/log",
 | 
					            "name": "psr/log",
 | 
				
			||||||
            "version": "3.0.2",
 | 
					            "version": "3.0.2",
 | 
				
			||||||
@@ -1573,6 +2058,50 @@
 | 
				
			|||||||
            },
 | 
					            },
 | 
				
			||||||
            "time": "2021-10-29T13:26:27+00:00"
 | 
					            "time": "2021-10-29T13:26:27+00:00"
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            "name": "ralouphie/getallheaders",
 | 
				
			||||||
 | 
					            "version": "3.0.3",
 | 
				
			||||||
 | 
					            "source": {
 | 
				
			||||||
 | 
					                "type": "git",
 | 
				
			||||||
 | 
					                "url": "https://github.com/ralouphie/getallheaders.git",
 | 
				
			||||||
 | 
					                "reference": "120b605dfeb996808c31b6477290a714d356e822"
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            "dist": {
 | 
				
			||||||
 | 
					                "type": "zip",
 | 
				
			||||||
 | 
					                "url": "https://api.github.com/repos/ralouphie/getallheaders/zipball/120b605dfeb996808c31b6477290a714d356e822",
 | 
				
			||||||
 | 
					                "reference": "120b605dfeb996808c31b6477290a714d356e822",
 | 
				
			||||||
 | 
					                "shasum": ""
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            "require": {
 | 
				
			||||||
 | 
					                "php": ">=5.6"
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            "require-dev": {
 | 
				
			||||||
 | 
					                "php-coveralls/php-coveralls": "^2.1",
 | 
				
			||||||
 | 
					                "phpunit/phpunit": "^5 || ^6.5"
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            "type": "library",
 | 
				
			||||||
 | 
					            "autoload": {
 | 
				
			||||||
 | 
					                "files": [
 | 
				
			||||||
 | 
					                    "src/getallheaders.php"
 | 
				
			||||||
 | 
					                ]
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            "notification-url": "https://packagist.org/downloads/",
 | 
				
			||||||
 | 
					            "license": [
 | 
				
			||||||
 | 
					                "MIT"
 | 
				
			||||||
 | 
					            ],
 | 
				
			||||||
 | 
					            "authors": [
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    "name": "Ralph Khattar",
 | 
				
			||||||
 | 
					                    "email": "ralph.khattar@gmail.com"
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            ],
 | 
				
			||||||
 | 
					            "description": "A polyfill for getallheaders.",
 | 
				
			||||||
 | 
					            "support": {
 | 
				
			||||||
 | 
					                "issues": "https://github.com/ralouphie/getallheaders/issues",
 | 
				
			||||||
 | 
					                "source": "https://github.com/ralouphie/getallheaders/tree/develop"
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            "time": "2019-03-08T08:55:37+00:00"
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            "name": "symfony/console",
 | 
					            "name": "symfony/console",
 | 
				
			||||||
            "version": "v6.4.17",
 | 
					            "version": "v6.4.17",
 | 
				
			||||||
@@ -2910,7 +3439,7 @@
 | 
				
			|||||||
    ],
 | 
					    ],
 | 
				
			||||||
    "aliases": [],
 | 
					    "aliases": [],
 | 
				
			||||||
    "minimum-stability": "stable",
 | 
					    "minimum-stability": "stable",
 | 
				
			||||||
    "stability-flags": [],
 | 
					    "stability-flags": {},
 | 
				
			||||||
    "prefer-stable": false,
 | 
					    "prefer-stable": false,
 | 
				
			||||||
    "prefer-lowest": false,
 | 
					    "prefer-lowest": false,
 | 
				
			||||||
    "platform": {
 | 
					    "platform": {
 | 
				
			||||||
@@ -2921,6 +3450,6 @@
 | 
				
			|||||||
        "ext-xml": "*",
 | 
					        "ext-xml": "*",
 | 
				
			||||||
        "ext-dom": "*"
 | 
					        "ext-dom": "*"
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "platform-dev": [],
 | 
					    "platform-dev": {},
 | 
				
			||||||
    "plugin-api-version": "2.3.0"
 | 
					    "plugin-api-version": "2.6.0"
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										
											BIN
										
									
								
								images/order_asc.gif
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								images/order_asc.gif
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 56 B  | 
							
								
								
									
										
											BIN
										
									
								
								images/order_desc.gif
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								images/order_desc.gif
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 56 B  | 
							
								
								
									
										25
									
								
								index.php
									
									
									
									
									
								
							
							
						
						
									
										25
									
								
								index.php
									
									
									
									
									
								
							@@ -93,6 +93,7 @@ if(setting('core.backward_support')) {
 | 
				
			|||||||
	if($logged && $account_logged)
 | 
						if($logged && $account_logged)
 | 
				
			||||||
		$group_id_of_acc_logged = $account_logged->getGroupId();
 | 
							$group_id_of_acc_logged = $account_logged->getGroupId();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						$config['serverPath'] = $config['server_path'];
 | 
				
			||||||
	$config['site'] = &$config;
 | 
						$config['site'] = &$config;
 | 
				
			||||||
	$config['server'] = &$config['lua'];
 | 
						$config['server'] = &$config['lua'];
 | 
				
			||||||
	$config['site']['shop_system'] = setting('core.gifts_system');
 | 
						$config['site']['shop_system'] = setting('core.gifts_system');
 | 
				
			||||||
@@ -117,6 +118,14 @@ if(setting('core.backward_support')) {
 | 
				
			|||||||
		$config['status']['serverStatus_' . $key] = $value;
 | 
							$config['status']['serverStatus_' . $key] = $value;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if(setting('core.views_counter')) {
 | 
				
			||||||
 | 
						require_once SYSTEM . 'counter.php';
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if(setting('core.visitors_counter')) {
 | 
				
			||||||
 | 
						$visitors = new Visitors(setting('core.visitors_counter_ttl'));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
require_once SYSTEM . 'router.php';
 | 
					require_once SYSTEM . 'router.php';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// anonymous usage statistics
 | 
					// anonymous usage statistics
 | 
				
			||||||
@@ -153,22 +162,6 @@ if(setting('core.anonymous_usage_statistics')) {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
if(setting('core.views_counter'))
 | 
					 | 
				
			||||||
	require_once SYSTEM . 'counter.php';
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
if(setting('core.visitors_counter')) {
 | 
					 | 
				
			||||||
	$visitors = new Visitors(setting('core.visitors_counter_ttl'));
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * @var OTS_Account $account_logged
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
if ($logged && admin()) {
 | 
					 | 
				
			||||||
	$content .= $twig->render('admin-bar.html.twig', [
 | 
					 | 
				
			||||||
		'username' => USE_ACCOUNT_NAME ? $account_logged->getName() : $account_logged->getId()
 | 
					 | 
				
			||||||
	]);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
$title_full =  (isset($title) ? $title . ' - ' : '') . $config['lua']['serverName'];
 | 
					$title_full =  (isset($title) ? $title . ' - ' : '') . $config['lua']['serverName'];
 | 
				
			||||||
require $template_path . '/' . $template_index;
 | 
					require $template_path . '/' . $template_index;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										69
									
								
								install/includes/import_base_data.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										69
									
								
								install/includes/import_base_data.php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,69 @@
 | 
				
			|||||||
 | 
					<?php
 | 
				
			||||||
 | 
					defined('MYAAC') or die('Direct access not allowed!');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use MyAAC\Models\Changelog;
 | 
				
			||||||
 | 
					use MyAAC\Models\Config;
 | 
				
			||||||
 | 
					use MyAAC\Models\ForumBoard;
 | 
				
			||||||
 | 
					use MyAAC\Models\Gallery;
 | 
				
			||||||
 | 
					use MyAAC\Models\NewsCategory;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if (Changelog::count() === 0) {
 | 
				
			||||||
 | 
						Changelog::create([
 | 
				
			||||||
 | 
							'type' => 3,
 | 
				
			||||||
 | 
							'where' => 2,
 | 
				
			||||||
 | 
							'date' => time(),
 | 
				
			||||||
 | 
							'body' => 'MyAAC installed. (:',
 | 
				
			||||||
 | 
							'hide' => 0,
 | 
				
			||||||
 | 
						]);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if (Config::where('name', 'database_version')->count() === 0) {
 | 
				
			||||||
 | 
						Config::create([
 | 
				
			||||||
 | 
							'name' => 'database_version',
 | 
				
			||||||
 | 
							'value' => DATABASE_VERSION,
 | 
				
			||||||
 | 
						]);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if (ForumBoard::count() === 0) {
 | 
				
			||||||
 | 
						$forumBoards = [
 | 
				
			||||||
 | 
							['name' => 'News', 'description' => 'News commenting', 'closed' => 1],
 | 
				
			||||||
 | 
							['name' => 'Trade', 'description' => 'Trade offers.', 'closed' => 0],
 | 
				
			||||||
 | 
							['name' => 'Quests', 'description' => 'Quest making.', 'closed' => 0],
 | 
				
			||||||
 | 
							['name' => 'Pictures', 'description' => 'Your pictures.', 'closed' => 0],
 | 
				
			||||||
 | 
							['name' => 'Bug Report', 'description' => 'Report bugs there.', 'closed' => 0],
 | 
				
			||||||
 | 
						];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						$i = 0;
 | 
				
			||||||
 | 
						foreach ($forumBoards as $forumBoard) {
 | 
				
			||||||
 | 
							ForumBoard::create([
 | 
				
			||||||
 | 
								'name' => $forumBoard['name'],
 | 
				
			||||||
 | 
								'description' => $forumBoard['description'],
 | 
				
			||||||
 | 
								'ordering' => $i++,
 | 
				
			||||||
 | 
								'closed' => $forumBoard['closed'],
 | 
				
			||||||
 | 
							]);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if (NewsCategory::count() === 0) {
 | 
				
			||||||
 | 
						$newsCategoriesIcons = [
 | 
				
			||||||
 | 
							0, 1, 2, 3, 4
 | 
				
			||||||
 | 
						];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						foreach ($newsCategoriesIcons as $iconId) {
 | 
				
			||||||
 | 
							NewsCategory::create([
 | 
				
			||||||
 | 
								'icon_id' => $iconId,
 | 
				
			||||||
 | 
							]);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if (Gallery::count() === 0) {
 | 
				
			||||||
 | 
						Gallery::create([
 | 
				
			||||||
 | 
							'comment' => 'Demon',
 | 
				
			||||||
 | 
							'image' => 'images/gallery/demon.jpg',
 | 
				
			||||||
 | 
							'thumb' => 'images/gallery/demon_thumb.gif',
 | 
				
			||||||
 | 
							'author' => 'MyAAC',
 | 
				
			||||||
 | 
							'ordering' => 0,
 | 
				
			||||||
 | 
						]);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					success($locale['step_database_success_import_data']);
 | 
				
			||||||
@@ -1,6 +1,4 @@
 | 
				
			|||||||
SET @myaac_database_version = 45;
 | 
					CREATE TABLE IF NOT EXISTS `myaac_account_actions`
 | 
				
			||||||
 | 
					 | 
				
			||||||
CREATE TABLE `myaac_account_actions`
 | 
					 | 
				
			||||||
(
 | 
					(
 | 
				
			||||||
	`account_id` int NOT NULL,
 | 
						`account_id` int NOT NULL,
 | 
				
			||||||
	`ip` int unsigned NOT NULL DEFAULT 0,
 | 
						`ip` int unsigned NOT NULL DEFAULT 0,
 | 
				
			||||||
@@ -10,7 +8,16 @@ CREATE TABLE `myaac_account_actions`
 | 
				
			|||||||
	KEY (`account_id`)
 | 
						KEY (`account_id`)
 | 
				
			||||||
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4;
 | 
					) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
CREATE TABLE `myaac_admin_menu`
 | 
					CREATE TABLE IF NOT EXISTS `myaac_account_emails_verify`
 | 
				
			||||||
 | 
					(
 | 
				
			||||||
 | 
						`id` int NOT NULL AUTO_INCREMENT,
 | 
				
			||||||
 | 
						`account_id` int NOT NULL,
 | 
				
			||||||
 | 
						`hash` varchar(32) NOT NULL,
 | 
				
			||||||
 | 
						`sent_at` int NOT NULL DEFAULT 0,
 | 
				
			||||||
 | 
						PRIMARY KEY (`id`)
 | 
				
			||||||
 | 
					) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					CREATE TABLE IF NOT EXISTS `myaac_admin_menu`
 | 
				
			||||||
(
 | 
					(
 | 
				
			||||||
	`id` int NOT NULL AUTO_INCREMENT,
 | 
						`id` int NOT NULL AUTO_INCREMENT,
 | 
				
			||||||
	`name` varchar(255) NOT NULL DEFAULT '',
 | 
						`name` varchar(255) NOT NULL DEFAULT '',
 | 
				
			||||||
@@ -21,7 +28,7 @@ CREATE TABLE `myaac_admin_menu`
 | 
				
			|||||||
	PRIMARY KEY (`id`)
 | 
						PRIMARY KEY (`id`)
 | 
				
			||||||
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4;
 | 
					) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
CREATE TABLE `myaac_changelog`
 | 
					CREATE TABLE IF NOT EXISTS `myaac_changelog`
 | 
				
			||||||
(
 | 
					(
 | 
				
			||||||
	`id` int NOT NULL AUTO_INCREMENT,
 | 
						`id` int NOT NULL AUTO_INCREMENT,
 | 
				
			||||||
	`body` varchar(500) NOT NULL DEFAULT '',
 | 
						`body` varchar(500) NOT NULL DEFAULT '',
 | 
				
			||||||
@@ -33,9 +40,7 @@ CREATE TABLE `myaac_changelog`
 | 
				
			|||||||
	PRIMARY KEY (`id`)
 | 
						PRIMARY KEY (`id`)
 | 
				
			||||||
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4;
 | 
					) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
INSERT INTO `myaac_changelog` (`id`, `type`, `where`, `date`, `body`, `hide`) VALUES (1, 3, 2, UNIX_TIMESTAMP(), 'MyAAC installed. (:', 0);
 | 
					CREATE TABLE IF NOT EXISTS `myaac_config`
 | 
				
			||||||
 | 
					 | 
				
			||||||
CREATE TABLE `myaac_config`
 | 
					 | 
				
			||||||
(
 | 
					(
 | 
				
			||||||
	`id` int NOT NULL AUTO_INCREMENT,
 | 
						`id` int NOT NULL AUTO_INCREMENT,
 | 
				
			||||||
	`name` varchar(30) NOT NULL,
 | 
						`name` varchar(30) NOT NULL,
 | 
				
			||||||
@@ -44,9 +49,7 @@ CREATE TABLE `myaac_config`
 | 
				
			|||||||
	UNIQUE (`name`)
 | 
						UNIQUE (`name`)
 | 
				
			||||||
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4;
 | 
					) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
INSERT INTO `myaac_config` (`name`, `value`) VALUES ('database_version', @myaac_database_version);
 | 
					CREATE TABLE IF NOT EXISTS `myaac_faq`
 | 
				
			||||||
 | 
					 | 
				
			||||||
CREATE TABLE `myaac_faq`
 | 
					 | 
				
			||||||
(
 | 
					(
 | 
				
			||||||
	`id` int NOT NULL AUTO_INCREMENT,
 | 
						`id` int NOT NULL AUTO_INCREMENT,
 | 
				
			||||||
	`question` varchar(255) NOT NULL DEFAULT '',
 | 
						`question` varchar(255) NOT NULL DEFAULT '',
 | 
				
			||||||
@@ -56,7 +59,7 @@ CREATE TABLE `myaac_faq`
 | 
				
			|||||||
	PRIMARY KEY (`id`)
 | 
						PRIMARY KEY (`id`)
 | 
				
			||||||
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4;
 | 
					) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
CREATE TABLE `myaac_forum_boards`
 | 
					CREATE TABLE IF NOT EXISTS `myaac_forum_boards`
 | 
				
			||||||
(
 | 
					(
 | 
				
			||||||
	`id` int NOT NULL AUTO_INCREMENT,
 | 
						`id` int NOT NULL AUTO_INCREMENT,
 | 
				
			||||||
	`name` varchar(32) NOT NULL,
 | 
						`name` varchar(32) NOT NULL,
 | 
				
			||||||
@@ -68,13 +71,8 @@ CREATE TABLE `myaac_forum_boards`
 | 
				
			|||||||
	`hide` tinyint NOT NULL DEFAULT 0,
 | 
						`hide` tinyint NOT NULL DEFAULT 0,
 | 
				
			||||||
	PRIMARY KEY (`id`)
 | 
						PRIMARY KEY (`id`)
 | 
				
			||||||
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4;
 | 
					) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4;
 | 
				
			||||||
INSERT INTO `myaac_forum_boards` (`id`, `name`, `description`, `ordering`, `closed`) VALUES (NULL, 'News', 'News commenting', 0, 1);
 | 
					 | 
				
			||||||
INSERT INTO `myaac_forum_boards` (`id`, `name`, `description`, `ordering`) VALUES (NULL, 'Trade', 'Trade offers.', 1);
 | 
					 | 
				
			||||||
INSERT INTO `myaac_forum_boards` (`id`, `name`, `description`, `ordering`) VALUES (NULL, 'Quests', 'Quest making.', 2);
 | 
					 | 
				
			||||||
INSERT INTO `myaac_forum_boards` (`id`, `name`, `description`, `ordering`) VALUES (NULL, 'Pictures', 'Your pictures.', 3);
 | 
					 | 
				
			||||||
INSERT INTO `myaac_forum_boards` (`id`, `name`, `description`, `ordering`) VALUES (NULL, 'Bug Report', 'Report bugs there.', 4);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
CREATE TABLE `myaac_forum`
 | 
					CREATE TABLE IF NOT EXISTS `myaac_forum`
 | 
				
			||||||
(
 | 
					(
 | 
				
			||||||
	`id` int NOT NULL AUTO_INCREMENT,
 | 
						`id` int NOT NULL AUTO_INCREMENT,
 | 
				
			||||||
	`first_post` int NOT NULL DEFAULT 0,
 | 
						`first_post` int NOT NULL DEFAULT 0,
 | 
				
			||||||
@@ -98,7 +96,7 @@ CREATE TABLE `myaac_forum`
 | 
				
			|||||||
	KEY `section` (`section`)
 | 
						KEY `section` (`section`)
 | 
				
			||||||
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4;
 | 
					) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
CREATE TABLE `myaac_menu`
 | 
					CREATE TABLE IF NOT EXISTS `myaac_menu`
 | 
				
			||||||
(
 | 
					(
 | 
				
			||||||
	`id` int NOT NULL AUTO_INCREMENT,
 | 
						`id` int NOT NULL AUTO_INCREMENT,
 | 
				
			||||||
	`template` varchar(255) NOT NULL,
 | 
						`template` varchar(255) NOT NULL,
 | 
				
			||||||
@@ -112,7 +110,7 @@ CREATE TABLE `myaac_menu`
 | 
				
			|||||||
	PRIMARY KEY (`id`)
 | 
						PRIMARY KEY (`id`)
 | 
				
			||||||
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4;
 | 
					) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
CREATE TABLE `myaac_monsters` (
 | 
					CREATE TABLE IF NOT EXISTS `myaac_monsters` (
 | 
				
			||||||
	`id` int NOT NULL AUTO_INCREMENT,
 | 
						`id` int NOT NULL AUTO_INCREMENT,
 | 
				
			||||||
	`hide` tinyint NOT NULL DEFAULT 0,
 | 
						`hide` tinyint NOT NULL DEFAULT 0,
 | 
				
			||||||
	`name` varchar(255) NOT NULL,
 | 
						`name` varchar(255) NOT NULL,
 | 
				
			||||||
@@ -145,7 +143,7 @@ CREATE TABLE `myaac_monsters` (
 | 
				
			|||||||
	PRIMARY KEY (`id`)
 | 
						PRIMARY KEY (`id`)
 | 
				
			||||||
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4;
 | 
					) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
CREATE TABLE `myaac_news`
 | 
					CREATE TABLE IF NOT EXISTS `myaac_news`
 | 
				
			||||||
(
 | 
					(
 | 
				
			||||||
	`id` int NOT NULL AUTO_INCREMENT,
 | 
						`id` int NOT NULL AUTO_INCREMENT,
 | 
				
			||||||
	`title` varchar(100) NOT NULL,
 | 
						`title` varchar(100) NOT NULL,
 | 
				
			||||||
@@ -163,7 +161,7 @@ CREATE TABLE `myaac_news`
 | 
				
			|||||||
	PRIMARY KEY (`id`)
 | 
						PRIMARY KEY (`id`)
 | 
				
			||||||
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4;
 | 
					) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
CREATE TABLE `myaac_news_categories`
 | 
					CREATE TABLE IF NOT EXISTS `myaac_news_categories`
 | 
				
			||||||
(
 | 
					(
 | 
				
			||||||
	`id` int NOT NULL AUTO_INCREMENT,
 | 
						`id` int NOT NULL AUTO_INCREMENT,
 | 
				
			||||||
	`name` varchar(50) NOT NULL DEFAULT "",
 | 
						`name` varchar(50) NOT NULL DEFAULT "",
 | 
				
			||||||
@@ -173,13 +171,7 @@ CREATE TABLE `myaac_news_categories`
 | 
				
			|||||||
	PRIMARY KEY (`id`)
 | 
						PRIMARY KEY (`id`)
 | 
				
			||||||
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4;
 | 
					) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
INSERT INTO `myaac_news_categories` (`id`, `icon_id`) VALUES (NULL, 0);
 | 
					CREATE TABLE IF NOT EXISTS `myaac_notepad`
 | 
				
			||||||
INSERT INTO `myaac_news_categories` (`id`, `icon_id`) VALUES (NULL, 1);
 | 
					 | 
				
			||||||
INSERT INTO `myaac_news_categories` (`id`, `icon_id`) VALUES (NULL, 2);
 | 
					 | 
				
			||||||
INSERT INTO `myaac_news_categories` (`id`, `icon_id`) VALUES (NULL, 3);
 | 
					 | 
				
			||||||
INSERT INTO `myaac_news_categories` (`id`, `icon_id`) VALUES (NULL, 4);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
CREATE TABLE `myaac_notepad`
 | 
					 | 
				
			||||||
(
 | 
					(
 | 
				
			||||||
	`id` int NOT NULL AUTO_INCREMENT,
 | 
						`id` int NOT NULL AUTO_INCREMENT,
 | 
				
			||||||
	`account_id` int NOT NULL,
 | 
						`account_id` int NOT NULL,
 | 
				
			||||||
@@ -189,7 +181,7 @@ CREATE TABLE `myaac_notepad`
 | 
				
			|||||||
	PRIMARY KEY (`id`)
 | 
						PRIMARY KEY (`id`)
 | 
				
			||||||
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4;
 | 
					) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
CREATE TABLE `myaac_pages`
 | 
					CREATE TABLE IF NOT EXISTS `myaac_pages`
 | 
				
			||||||
(
 | 
					(
 | 
				
			||||||
	`id` INT NOT NULL AUTO_INCREMENT,
 | 
						`id` INT NOT NULL AUTO_INCREMENT,
 | 
				
			||||||
	`name` varchar(30) NOT NULL,
 | 
						`name` varchar(30) NOT NULL,
 | 
				
			||||||
@@ -205,7 +197,7 @@ CREATE TABLE `myaac_pages`
 | 
				
			|||||||
	UNIQUE (`name`)
 | 
						UNIQUE (`name`)
 | 
				
			||||||
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4;
 | 
					) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
CREATE TABLE `myaac_gallery`
 | 
					CREATE TABLE IF NOT EXISTS `myaac_gallery`
 | 
				
			||||||
(
 | 
					(
 | 
				
			||||||
	`id` int NOT NULL AUTO_INCREMENT,
 | 
						`id` int NOT NULL AUTO_INCREMENT,
 | 
				
			||||||
	`comment` varchar(255) NOT NULL DEFAULT '',
 | 
						`comment` varchar(255) NOT NULL DEFAULT '',
 | 
				
			||||||
@@ -217,9 +209,7 @@ CREATE TABLE `myaac_gallery`
 | 
				
			|||||||
	PRIMARY KEY (`id`)
 | 
						PRIMARY KEY (`id`)
 | 
				
			||||||
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4;
 | 
					) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
INSERT INTO `myaac_gallery` (`id`, `ordering`, `comment`, `image`, `thumb`, `author`) VALUES (NULL, 1, 'Demon', 'images/gallery/demon.jpg', 'images/gallery/demon_thumb.gif', 'MyAAC');
 | 
					CREATE TABLE IF NOT EXISTS `myaac_settings`
 | 
				
			||||||
 | 
					 | 
				
			||||||
CREATE TABLE `myaac_settings`
 | 
					 | 
				
			||||||
(
 | 
					(
 | 
				
			||||||
	`id` int NOT NULL AUTO_INCREMENT,
 | 
						`id` int NOT NULL AUTO_INCREMENT,
 | 
				
			||||||
	`name` varchar(255) NOT NULL DEFAULT '',
 | 
						`name` varchar(255) NOT NULL DEFAULT '',
 | 
				
			||||||
@@ -229,7 +219,7 @@ CREATE TABLE `myaac_settings`
 | 
				
			|||||||
	KEY `key` (`key`)
 | 
						KEY `key` (`key`)
 | 
				
			||||||
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4;
 | 
					) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
CREATE TABLE `myaac_spells`
 | 
					CREATE TABLE IF NOT EXISTS `myaac_spells`
 | 
				
			||||||
(
 | 
					(
 | 
				
			||||||
	`id` int NOT NULL AUTO_INCREMENT,
 | 
						`id` int NOT NULL AUTO_INCREMENT,
 | 
				
			||||||
	`spell` varchar(255) NOT NULL DEFAULT '',
 | 
						`spell` varchar(255) NOT NULL DEFAULT '',
 | 
				
			||||||
@@ -252,7 +242,7 @@ CREATE TABLE `myaac_spells`
 | 
				
			|||||||
	UNIQUE (`name`)
 | 
						UNIQUE (`name`)
 | 
				
			||||||
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4;
 | 
					) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
CREATE TABLE `myaac_visitors`
 | 
					CREATE TABLE IF NOT EXISTS `myaac_visitors`
 | 
				
			||||||
(
 | 
					(
 | 
				
			||||||
	`ip` varchar(45) NOT NULL,
 | 
						`ip` varchar(45) NOT NULL,
 | 
				
			||||||
	`lastvisit` int NOT NULL DEFAULT 0,
 | 
						`lastvisit` int NOT NULL DEFAULT 0,
 | 
				
			||||||
@@ -261,7 +251,7 @@ CREATE TABLE `myaac_visitors`
 | 
				
			|||||||
	UNIQUE (`ip`)
 | 
						UNIQUE (`ip`)
 | 
				
			||||||
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4;
 | 
					) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
CREATE TABLE `myaac_weapons`
 | 
					CREATE TABLE IF NOT EXISTS `myaac_weapons`
 | 
				
			||||||
(
 | 
					(
 | 
				
			||||||
	`id` int NOT NULL,
 | 
						`id` int NOT NULL,
 | 
				
			||||||
	`level` int NOT NULL DEFAULT 0,
 | 
						`level` int NOT NULL DEFAULT 0,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -42,10 +42,9 @@ if(!$error) {
 | 
				
			|||||||
	$configToSave['cache_prefix'] = 'myaac_' . generateRandomString(8, true, false, true);
 | 
						$configToSave['cache_prefix'] = 'myaac_' . generateRandomString(8, true, false, true);
 | 
				
			||||||
	$configToSave['database_auto_migrate'] = true;
 | 
						$configToSave['database_auto_migrate'] = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if(!$error) {
 | 
					 | 
				
			||||||
	$content = '';
 | 
						$content = '';
 | 
				
			||||||
	$saved = Settings::saveConfig($configToSave, BASE . 'config.local.php', $content);
 | 
						$saved = Settings::saveConfig($configToSave, BASE . 'config.local.php', $content);
 | 
				
			||||||
		if ($saved) {
 | 
						if ($saved || file_exists(BASE . 'config.local.php')) {
 | 
				
			||||||
		success($locale['step_database_config_saved']);
 | 
							success($locale['step_database_config_saved']);
 | 
				
			||||||
		$_SESSION['saved'] = true;
 | 
							$_SESSION['saved'] = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -74,15 +73,15 @@ if(!$error) {
 | 
				
			|||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
 | 
							$error = true;
 | 
				
			||||||
		$_SESSION['config_content'] = $content;
 | 
							$_SESSION['config_content'] = $content;
 | 
				
			||||||
		unset($_SESSION['saved']);
 | 
							unset($_SESSION['saved']);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			$locale['step_database_error_file'] = str_replace('$FILE$', '<b>' . BASE . 'config.php</b>', $locale['step_database_error_file']);
 | 
							$locale['step_database_error_file'] = str_replace('$FILE$', '<b>' . BASE . 'config.local.php</b>', $locale['step_database_error_file']);
 | 
				
			||||||
		error($locale['step_database_error_file'] . '<br/>
 | 
							error($locale['step_database_error_file'] . '<br/>
 | 
				
			||||||
			<textarea cols="70" rows="10">' . $content . '</textarea>');
 | 
								<textarea cols="70" rows="10">' . $content . '</textarea>');
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
}
 | 
					 | 
				
			||||||
?>
 | 
					?>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<div class="text-center m-3">
 | 
					<div class="text-center m-3">
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -30,17 +30,12 @@ if(!$error) {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
if($db->hasTable(TABLE_PREFIX . 'account_actions')) {
 | 
					 | 
				
			||||||
	$locale['step_database_error_table_exist'] = str_replace('$TABLE$', TABLE_PREFIX . 'account_actions', $locale['step_database_error_table_exist']);
 | 
					 | 
				
			||||||
	warning($locale['step_database_error_table_exist']);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
else {
 | 
					 | 
				
			||||||
// import schema
 | 
					// import schema
 | 
				
			||||||
try {
 | 
					try {
 | 
				
			||||||
	$locale['step_database_importing'] = str_replace('$DATABASE_NAME$', config('database_name'), $locale['step_database_importing']);
 | 
						$locale['step_database_importing'] = str_replace('$DATABASE_NAME$', config('database_name'), $locale['step_database_importing']);
 | 
				
			||||||
	success($locale['step_database_importing']);
 | 
						success($locale['step_database_importing']);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		$db->query(file_get_contents(BASE . 'install/includes/schema.sql'));
 | 
						$db->exec(file_get_contents(BASE . 'install/includes/schema.sql'));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	$locale['step_database_success_schema'] = str_replace('$PREFIX$', TABLE_PREFIX, $locale['step_database_success_schema']);
 | 
						$locale['step_database_success_schema'] = str_replace('$PREFIX$', TABLE_PREFIX, $locale['step_database_success_schema']);
 | 
				
			||||||
	success($locale['step_database_success_schema']);
 | 
						success($locale['step_database_success_schema']);
 | 
				
			||||||
@@ -49,7 +44,8 @@ else {
 | 
				
			|||||||
	error($locale['step_database_error_schema'] . ' ' . $error_);
 | 
						error($locale['step_database_error_schema'] . ' ' . $error_);
 | 
				
			||||||
	return;
 | 
						return;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
}
 | 
					
 | 
				
			||||||
 | 
					require BASE . 'install/includes/import_base_data.php';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
if(!$db->hasColumn('accounts', 'email')) {
 | 
					if(!$db->hasColumn('accounts', 'email')) {
 | 
				
			||||||
	if(query("ALTER TABLE `accounts` ADD `email` varchar(255) NOT NULL DEFAULT '';"))
 | 
						if(query("ALTER TABLE `accounts` ADD `email` varchar(255) NOT NULL DEFAULT '';"))
 | 
				
			||||||
@@ -102,18 +98,13 @@ if(!$db->hasColumn('accounts', 'web_flags')) {
 | 
				
			|||||||
		success($locale['step_database_adding_field'] . ' accounts.web_flags...');
 | 
							success($locale['step_database_adding_field'] . ' accounts.web_flags...');
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
if(!$db->hasColumn('accounts', 'email_hash')) {
 | 
					 | 
				
			||||||
	if(query("ALTER TABLE `accounts` ADD `email_hash` VARCHAR(32) NOT NULL DEFAULT '' AFTER `web_flags`;"))
 | 
					 | 
				
			||||||
		success($locale['step_database_adding_field'] . ' accounts.email_hash...');
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
if(!$db->hasColumn('accounts', 'email_verified')) {
 | 
					if(!$db->hasColumn('accounts', 'email_verified')) {
 | 
				
			||||||
	if(query("ALTER TABLE `accounts` ADD `email_verified` TINYINT(1) NOT NULL DEFAULT 0 AFTER `email_hash`;"))
 | 
						if(query("ALTER TABLE `accounts` ADD `email_verified` TINYINT(1) NOT NULL DEFAULT 0 AFTER `web_flags`;"))
 | 
				
			||||||
		success($locale['step_database_adding_field'] . ' accounts.email_verified...');
 | 
							success($locale['step_database_adding_field'] . ' accounts.email_verified...');
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
if(!$db->hasColumn('accounts', 'email_new')) {
 | 
					if(!$db->hasColumn('accounts', 'email_new')) {
 | 
				
			||||||
	if(query("ALTER TABLE `accounts` ADD `email_new` VARCHAR(255) NOT NULL DEFAULT '' AFTER `email_hash`;"))
 | 
						if(query("ALTER TABLE `accounts` ADD `email_new` VARCHAR(255) NOT NULL DEFAULT '' AFTER `email_verified`;"))
 | 
				
			||||||
		success($locale['step_database_adding_field'] . ' accounts.email_new...');
 | 
							success($locale['step_database_adding_field'] . ' accounts.email_new...');
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -88,8 +88,8 @@ switch ($action) {
 | 
				
			|||||||
	case 'boostedcreature':
 | 
						case 'boostedcreature':
 | 
				
			||||||
		$clientVersion = (int)setting('core.client');
 | 
							$clientVersion = (int)setting('core.client');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// 14.00 and up
 | 
							// 13.40 and up
 | 
				
			||||||
		if ($clientVersion >= 1400) {
 | 
							if ($clientVersion >= 1340) {
 | 
				
			||||||
			$creatureBoost = $db->query("SELECT * FROM " . $db->tableName('boosted_creature'))->fetchAll();
 | 
								$creatureBoost = $db->query("SELECT * FROM " . $db->tableName('boosted_creature'))->fetchAll();
 | 
				
			||||||
			$bossBoost     = $db->query("SELECT * FROM " . $db->tableName('boosted_boss'))->fetchAll();
 | 
								$bossBoost     = $db->query("SELECT * FROM " . $db->tableName('boosted_boss'))->fetchAll();
 | 
				
			||||||
			die(json_encode([
 | 
								die(json_encode([
 | 
				
			||||||
@@ -220,6 +220,8 @@ switch ($action) {
 | 
				
			|||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/*
 | 
				
			||||||
 | 
							 * not needed anymore?
 | 
				
			||||||
		if (fieldExist('premdays', 'accounts') && fieldExist('lastday', 'accounts')) {
 | 
							if (fieldExist('premdays', 'accounts') && fieldExist('lastday', 'accounts')) {
 | 
				
			||||||
			$save = false;
 | 
								$save = false;
 | 
				
			||||||
			$timeNow = time();
 | 
								$timeNow = time();
 | 
				
			||||||
@@ -256,6 +258,7 @@ switch ($action) {
 | 
				
			|||||||
				$account->save();
 | 
									$account->save();
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
							*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		$worlds = [$world];
 | 
							$worlds = [$world];
 | 
				
			||||||
		$playdata = compact('worlds', 'characters');
 | 
							$playdata = compact('worlds', 'characters');
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										13
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										13
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							@@ -976,15 +976,16 @@
 | 
				
			|||||||
      }
 | 
					      }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "node_modules/form-data": {
 | 
					    "node_modules/form-data": {
 | 
				
			||||||
      "version": "4.0.2",
 | 
					      "version": "4.0.4",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.2.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.4.tgz",
 | 
				
			||||||
      "integrity": "sha512-hGfm/slu0ZabnNt4oaRZ6uREyfCj6P4fT/n6A1rGV+Z0VdGXjfOhVUpkn6qVQONHGIFwmveGXyDs75+nr6FM8w==",
 | 
					      "integrity": "sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==",
 | 
				
			||||||
      "dev": true,
 | 
					      "dev": true,
 | 
				
			||||||
      "license": "MIT",
 | 
					      "license": "MIT",
 | 
				
			||||||
      "dependencies": {
 | 
					      "dependencies": {
 | 
				
			||||||
        "asynckit": "^0.4.0",
 | 
					        "asynckit": "^0.4.0",
 | 
				
			||||||
        "combined-stream": "^1.0.8",
 | 
					        "combined-stream": "^1.0.8",
 | 
				
			||||||
        "es-set-tostringtag": "^2.1.0",
 | 
					        "es-set-tostringtag": "^2.1.0",
 | 
				
			||||||
 | 
					        "hasown": "^2.0.2",
 | 
				
			||||||
        "mime-types": "^2.1.12"
 | 
					        "mime-types": "^2.1.12"
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
      "engines": {
 | 
					      "engines": {
 | 
				
			||||||
@@ -2084,9 +2085,9 @@
 | 
				
			|||||||
      "license": "MIT"
 | 
					      "license": "MIT"
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "node_modules/tmp": {
 | 
					    "node_modules/tmp": {
 | 
				
			||||||
      "version": "0.2.3",
 | 
					      "version": "0.2.4",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.3.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.4.tgz",
 | 
				
			||||||
      "integrity": "sha512-nZD7m9iCPC5g0pYmcaxogYKggSfLsdxl8of3Q/oIbqCqLLIO9IAF0GWjX1z9NZRHPiXv8Wex4yDCaZsgEw0Y8w==",
 | 
					      "integrity": "sha512-UdiSoX6ypifLmrfQ/XfiawN6hkjSBpCjhKxxZcWlUUmoXLaCKQU0bx4HF/tdDK2uzRuchf1txGvrWBzYREssoQ==",
 | 
				
			||||||
      "dev": true,
 | 
					      "dev": true,
 | 
				
			||||||
      "license": "MIT",
 | 
					      "license": "MIT",
 | 
				
			||||||
      "engines": {
 | 
					      "engines": {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -28,10 +28,9 @@ parameters:
 | 
				
			|||||||
		- '#Variable \$guild might not be defined#'
 | 
							- '#Variable \$guild might not be defined#'
 | 
				
			||||||
		- '#Variable \$[a-zA-Z0-9\\_]+ might not be defined#'
 | 
							- '#Variable \$[a-zA-Z0-9\\_]+ might not be defined#'
 | 
				
			||||||
		# Eloquent models
 | 
							# Eloquent models
 | 
				
			||||||
 | 
							- '#Call to an undefined method [a-zA-Z0-9\\_]+::[a-zA-Z0-9\\_]+\(\)#'
 | 
				
			||||||
		- '#Call to an undefined static method [a-zA-Z0-9\\_]+::[a-zA-Z0-9\\_]+\(\)#'
 | 
							- '#Call to an undefined static method [a-zA-Z0-9\\_]+::[a-zA-Z0-9\\_]+\(\)#'
 | 
				
			||||||
		- '#Call to an undefined method object::toArray\(\)#'
 | 
					 | 
				
			||||||
		# system/pages/highscores.php
 | 
							# system/pages/highscores.php
 | 
				
			||||||
		- '#Call to an undefined method Illuminate\\Database\\Query\\Builder::withOnlineStatus\(\)#'
 | 
					 | 
				
			||||||
		- '#Access to an undefined property Illuminate\\Database\\Eloquent\\Model::\$online_status#'
 | 
							- '#Access to an undefined property Illuminate\\Database\\Eloquent\\Model::\$online_status#'
 | 
				
			||||||
		- '#Access to an undefined property Illuminate\\Database\\Eloquent\\Model::\$vocation_name#'
 | 
							- '#Access to an undefined property Illuminate\\Database\\Eloquent\\Model::\$vocation_name#'
 | 
				
			||||||
		-
 | 
							-
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -51,5 +51,8 @@
 | 
				
			|||||||
		"themes": true,
 | 
							"themes": true,
 | 
				
			||||||
		"admin-pages": true,
 | 
							"admin-pages": true,
 | 
				
			||||||
		"admin-pages-sub-folders": true,
 | 
							"admin-pages-sub-folders": true,
 | 
				
			||||||
 | 
							"settings": true,
 | 
				
			||||||
 | 
							"install": true,
 | 
				
			||||||
 | 
							"init": false
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 }
 | 
					 }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -81,6 +81,7 @@ $deprecatedConfig = [
 | 
				
			|||||||
	'account_change_character_name_points' => 'account_change_character_name_price',
 | 
						'account_change_character_name_points' => 'account_change_character_name_price',
 | 
				
			||||||
	'account_change_character_sex',
 | 
						'account_change_character_sex',
 | 
				
			||||||
	'account_change_character_sex_points' => 'account_change_character_name_price',
 | 
						'account_change_character_sex_points' => 'account_change_character_name_price',
 | 
				
			||||||
 | 
						'email_lai_sec_interval' => 'mail_lost_account_interval',
 | 
				
			||||||
];
 | 
					];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
foreach ($deprecatedConfig as $key => $value) {
 | 
					foreach ($deprecatedConfig as $key => $value) {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -512,6 +512,13 @@ function template_place_holder($type): string
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
	elseif ($type === 'body_start') {
 | 
						elseif ($type === 'body_start') {
 | 
				
			||||||
		$ret .= $twig->render('browsehappy.html.twig');
 | 
							$ret .= $twig->render('browsehappy.html.twig');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (admin()) {
 | 
				
			||||||
 | 
								global $account_logged;
 | 
				
			||||||
 | 
								$ret .= $twig->render('admin-bar.html.twig', [
 | 
				
			||||||
 | 
									'username' => USE_ACCOUNT_NAME ? $account_logged->getName() : $account_logged->getId()
 | 
				
			||||||
 | 
								]);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	elseif($type === 'body_end') {
 | 
						elseif($type === 'body_end') {
 | 
				
			||||||
		$ret .= template_ga_code();
 | 
							$ret .= template_ga_code();
 | 
				
			||||||
@@ -767,6 +774,10 @@ function formatExperience($exp, $color = true)
 | 
				
			|||||||
	return $ret;
 | 
						return $ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function getExperienceForLevel($level): float|int {
 | 
				
			||||||
 | 
						return ( 50 / 3 ) * pow( $level, 3 ) - ( 100 * pow( $level, 2 ) ) + ( ( 850 / 3 ) * $level ) - 200;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function get_locales()
 | 
					function get_locales()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	$ret = array();
 | 
						$ret = array();
 | 
				
			||||||
@@ -982,11 +993,12 @@ function load_config_lua($filename)
 | 
				
			|||||||
		foreach($lines as $ln => $line)
 | 
							foreach($lines as $ln => $line)
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			$line = trim($line);
 | 
								$line = trim($line);
 | 
				
			||||||
			if(@$line[0] === '{' || @$line[0] === '}') {
 | 
								if(isset($line[0]) && ($line[0] === '{' || $line[0] === '}')) {
 | 
				
			||||||
				// arrays are not supported yet
 | 
									// arrays are not supported yet
 | 
				
			||||||
				// just ignore the error
 | 
									// just ignore the error
 | 
				
			||||||
				continue;
 | 
									continue;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			$tmp_exp = explode('=', $line, 2);
 | 
								$tmp_exp = explode('=', $line, 2);
 | 
				
			||||||
			if(str_contains($line, 'dofile')) {
 | 
								if(str_contains($line, 'dofile')) {
 | 
				
			||||||
				$delimiter = '"';
 | 
									$delimiter = '"';
 | 
				
			||||||
@@ -1130,10 +1142,18 @@ function getTopPlayers($limit = 5, $skill = 'level') {
 | 
				
			|||||||
			'looktype', 'lookhead', 'lookbody', 'looklegs', 'lookfeet'
 | 
								'looktype', 'lookhead', 'lookbody', 'looklegs', 'lookfeet'
 | 
				
			||||||
		];
 | 
							];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if ($db->hasColumn('players', 'promotion')) {
 | 
				
			||||||
 | 
								$columns[] = 'promotion';
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if ($db->hasColumn('players', 'lookaddons')) {
 | 
							if ($db->hasColumn('players', 'lookaddons')) {
 | 
				
			||||||
			$columns[] = 'lookaddons';
 | 
								$columns[] = 'lookaddons';
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if ($db->hasColumn('players', 'lookmount')) {
 | 
				
			||||||
 | 
								$columns[] = 'lookmount';
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		return Player::query()
 | 
							return Player::query()
 | 
				
			||||||
			->select($columns)
 | 
								->select($columns)
 | 
				
			||||||
			->withOnlineStatus()
 | 
								->withOnlineStatus()
 | 
				
			||||||
@@ -1216,7 +1236,8 @@ function setting($key)
 | 
				
			|||||||
		return $settings[$key[0]] = $key[1];
 | 
							return $settings[$key[0]] = $key[1];
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return $settings[$key]['value'];
 | 
						$ret = $settings[$key];
 | 
				
			||||||
 | 
						return isset($ret) ? $ret['value'] : null;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function clearCache()
 | 
					function clearCache()
 | 
				
			||||||
@@ -1265,14 +1286,15 @@ function clearCache()
 | 
				
			|||||||
		$db->setClearCacheAfter(true);
 | 
							$db->setClearCacheAfter(true);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (function_exists('apcu_clear_cache')) {
 | 
				
			||||||
 | 
							apcu_clear_cache();
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	deleteDirectory(CACHE . 'signatures', ['index.html'], true);
 | 
						deleteDirectory(CACHE . 'signatures', ['index.html'], true);
 | 
				
			||||||
	deleteDirectory(CACHE . 'twig', ['index.html'], true);
 | 
						deleteDirectory(CACHE . 'twig', ['index.html'], true);
 | 
				
			||||||
	deleteDirectory(CACHE . 'plugins', ['index.html'], true);
 | 
						deleteDirectory(CACHE . 'plugins', ['index.html'], true);
 | 
				
			||||||
	deleteDirectory(CACHE, ['signatures', 'twig', 'plugins', 'index.html', 'persistent'], true);
 | 
						deleteDirectory(CACHE, ['signatures', 'twig', 'plugins', 'index.html', 'persistent'], true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// routes cache
 | 
					 | 
				
			||||||
	clearRouteCache();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	global $hooks;
 | 
						global $hooks;
 | 
				
			||||||
	$hooks->trigger(HOOK_CACHE_CLEAR, ['cache' => Cache::getInstance()]);
 | 
						$hooks->trigger(HOOK_CACHE_CLEAR, ['cache' => Cache::getInstance()]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -1618,13 +1640,14 @@ function camelCaseToUnderscore($input)
 | 
				
			|||||||
	return ltrim(strtolower(preg_replace('/[A-Z]([A-Z](?![a-z]))*/', '_$0', $input)), '_');
 | 
						return ltrim(strtolower(preg_replace('/[A-Z]([A-Z](?![a-z]))*/', '_$0', $input)), '_');
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function removeIfFirstSlash(&$text) {
 | 
					function removeIfFirstSlash(&$text): void
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
	if(strpos($text, '/') === 0) {
 | 
						if(strpos($text, '/') === 0) {
 | 
				
			||||||
		$text = str_replace_first('/', '', $text);
 | 
							$text = str_replace_first('/', '', $text);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function escapeHtml($html) {
 | 
					function escapeHtml($html): string {
 | 
				
			||||||
	return htmlspecialchars($html);
 | 
						return htmlspecialchars($html);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -1638,7 +1661,7 @@ function getGuildNameById($id)
 | 
				
			|||||||
	return false;
 | 
						return false;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function getGuildLogoById($id)
 | 
					function getGuildLogoById($id): string
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	$logo = 'default.gif';
 | 
						$logo = 'default.gif';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -1654,7 +1677,8 @@ function getGuildLogoById($id)
 | 
				
			|||||||
	return BASE_URL . GUILD_IMAGES_DIR . $logo;
 | 
						return BASE_URL . GUILD_IMAGES_DIR . $logo;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function displayErrorBoxWithBackButton($errors, $action = null) {
 | 
					function displayErrorBoxWithBackButton($errors, $action = null): void
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
	global $twig;
 | 
						global $twig;
 | 
				
			||||||
	$twig->display('error_box.html.twig', ['errors' => $errors]);
 | 
						$twig->display('error_box.html.twig', ['errors' => $errors]);
 | 
				
			||||||
	$twig->display('account.back_button.html.twig', [
 | 
						$twig->display('account.back_button.html.twig', [
 | 
				
			||||||
@@ -1682,6 +1706,12 @@ function getAccountIdentityColumn(): string
 | 
				
			|||||||
	return 'id';
 | 
						return 'id';
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function isCanary(): bool
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						$vipSystemEnabled = configLua('vipSystemEnabled');
 | 
				
			||||||
 | 
						return isset($vipSystemEnabled);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// validator functions
 | 
					// validator functions
 | 
				
			||||||
require_once SYSTEM . 'compat/base.php';
 | 
					require_once SYSTEM . 'compat/base.php';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -144,6 +144,15 @@ $ots = POT::getInstance();
 | 
				
			|||||||
$eloquentConnection = null;
 | 
					$eloquentConnection = null;
 | 
				
			||||||
require_once SYSTEM . 'database.php';
 | 
					require_once SYSTEM . 'database.php';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					define('USE_ACCOUNT_NAME', $db->hasColumn('accounts', 'name'));
 | 
				
			||||||
 | 
					define('USE_ACCOUNT_NUMBER', $db->hasColumn('accounts', 'number'));
 | 
				
			||||||
 | 
					define('USE_ACCOUNT_SALT', $db->hasColumn('accounts', 'salt'));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					define('HAS_ACCOUNT_COINS', $db->hasColumn('accounts', 'coins'));
 | 
				
			||||||
 | 
					define('HAS_ACCOUNT_COINS_TRANSFERABLE', $db->hasColumn('accounts', 'coins_transferable'));
 | 
				
			||||||
 | 
					define('HAS_ACCOUNT_TRANSFERABLE_COINS', $db->hasColumn('accounts', 'transferable_coins'));
 | 
				
			||||||
 | 
					const ACCOUNT_COINS_TRANSFERABLE_COLUMN = (HAS_ACCOUNT_COINS_TRANSFERABLE ? 'coins_transferable' : 'transferable_coins');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
$twig->addGlobal('logged', false);
 | 
					$twig->addGlobal('logged', false);
 | 
				
			||||||
$twig->addGlobal('account_logged', new \OTS_Account());
 | 
					$twig->addGlobal('account_logged', new \OTS_Account());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -188,10 +197,6 @@ if($settingsItemImagesURL[strlen($settingsItemImagesURL) - 1] !== '/') {
 | 
				
			|||||||
	setting(['core.item_images_url', $settingsItemImagesURL . '/']);
 | 
						setting(['core.item_images_url', $settingsItemImagesURL . '/']);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
define('USE_ACCOUNT_NAME', $db->hasColumn('accounts', 'name'));
 | 
					 | 
				
			||||||
define('USE_ACCOUNT_NUMBER', $db->hasColumn('accounts', 'number'));
 | 
					 | 
				
			||||||
define('USE_ACCOUNT_SALT', $db->hasColumn('accounts', 'salt'));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
$towns = Cache::remember('towns', 10 * 60, function () use ($db) {
 | 
					$towns = Cache::remember('towns', 10 * 60, function () use ($db) {
 | 
				
			||||||
	if ($db->hasTable('towns') && Town::count() > 0) {
 | 
						if ($db->hasTable('towns') && Town::count() > 0) {
 | 
				
			||||||
		return Town::orderBy('id', 'ASC')->pluck('name', 'id')->toArray();
 | 
							return Town::orderBy('id', 'ASC')->pluck('name', 'id')->toArray();
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -443,8 +443,9 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable
 | 
				
			|||||||
			throw new E_OTS_NotLoaded();
 | 
								throw new E_OTS_NotLoaded();
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if(isset($this->data['premium_ends_at']) || isset($this->data['premend'])) {
 | 
							if(isset($this->data['premium_ends_at']) || isset($this->data['premend']) ||
 | 
				
			||||||
			$col = isset($this->data['premium_ends_at']) ? 'premium_ends_at' : 'premend';
 | 
								(isCanary() && isset($this->data['lastday']))) {
 | 
				
			||||||
 | 
									$col = (isset($this->data['premium_ends_at']) ? 'premium_ends_at' : (isset($this->data['lastday']) ? 'lastday' : 'premend'));
 | 
				
			||||||
				$ret = ceil(($this->data[$col] - time()) / (24 * 60 * 60));
 | 
									$ret = ceil(($this->data[$col] - time()) / (24 * 60 * 60));
 | 
				
			||||||
				return max($ret, 0);
 | 
									return max($ret, 0);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
@@ -471,17 +472,16 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable
 | 
				
			|||||||
		return $this->data['lastday'];
 | 
							return $this->data['lastday'];
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public function isPremium()
 | 
						public function isPremium(): bool
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		global $config;
 | 
							if(isset($this->data['premium_ends_at']) || isset($this->data['premend']) ||
 | 
				
			||||||
        if(isset($config['lua']['freePremium']) && getBoolean($config['lua']['freePremium'])) return true;
 | 
								(isCanary() && isset($this->data['lastday']))) {
 | 
				
			||||||
 | 
								$col = (isset($this->data['premium_ends_at']) ? 'premium_ends_at' : (isset($this->data['lastday']) ? 'lastday' : 'premend'));
 | 
				
			||||||
	    if(isset($this->data['premium_ends_at'])) {
 | 
								return $this->data[$col] > time();
 | 
				
			||||||
		    return $this->data['premium_ends_at'] > time();
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if(isset($this->data['premend'])) {
 | 
							if($this->data['premdays'] == self::GRATIS_PREMIUM_DAYS){
 | 
				
			||||||
			return $this->data['premend'] > time();
 | 
								return true;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		return ($this->data['premdays'] - (date("z", time()) + (365 * (date("Y", time()) - date("Y", $this->data['lastday']))) - date("z", $this->data['lastday'])) > 0);
 | 
							return ($this->data['premdays'] - (date("z", time()) + (365 * (date("Y", time()) - date("Y", $this->data['lastday']))) - date("z", $this->data['lastday'])) > 0);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -26,10 +26,11 @@ use MyAAC\Cache\Cache;
 | 
				
			|||||||
 */
 | 
					 */
 | 
				
			||||||
class OTS_DB_MySQL extends OTS_Base_DB
 | 
					class OTS_DB_MySQL extends OTS_Base_DB
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	private $has_table_cache = array();
 | 
						private array $has_table_cache = [];
 | 
				
			||||||
	private $has_column_cache = array();
 | 
						private array $has_column_cache = [];
 | 
				
			||||||
 | 
						private array $get_column_info_cache = [];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	private $clearCacheAfter = false;
 | 
						private bool $clearCacheAfter = false;
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Creates database connection.
 | 
					 * Creates database connection.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
@@ -119,6 +120,11 @@ class OTS_DB_MySQL extends OTS_Base_DB
 | 
				
			|||||||
				if($cache->fetch('database_columns', $tmp) && $tmp) {
 | 
									if($cache->fetch('database_columns', $tmp) && $tmp) {
 | 
				
			||||||
					$this->has_column_cache = unserialize($tmp);
 | 
										$this->has_column_cache = unserialize($tmp);
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									$tmp = null;
 | 
				
			||||||
 | 
									if($cache->fetch('database_columns_info', $tmp) && $tmp) {
 | 
				
			||||||
 | 
										$this->get_column_info_cache = unserialize($tmp);
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -155,11 +161,13 @@ class OTS_DB_MySQL extends OTS_Base_DB
 | 
				
			|||||||
			if ($this->clearCacheAfter) {
 | 
								if ($this->clearCacheAfter) {
 | 
				
			||||||
				$cache->delete('database_tables');
 | 
									$cache->delete('database_tables');
 | 
				
			||||||
				$cache->delete('database_columns');
 | 
									$cache->delete('database_columns');
 | 
				
			||||||
 | 
									$cache->delete('database_columns_info');
 | 
				
			||||||
				$cache->delete('database_checksum');
 | 
									$cache->delete('database_checksum');
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			else {
 | 
								else {
 | 
				
			||||||
				$cache->set('database_tables', serialize($this->has_table_cache), 3600);
 | 
									$cache->set('database_tables', serialize($this->has_table_cache), 3600);
 | 
				
			||||||
				$cache->set('database_columns', serialize($this->has_column_cache), 3600);
 | 
									$cache->set('database_columns', serialize($this->has_column_cache), 3600);
 | 
				
			||||||
 | 
									$cache->set('database_columns_info', serialize($this->get_column_info_cache), 3600);
 | 
				
			||||||
				$cache->set('database_checksum', serialize(sha1($config['database_host'] . '.' . $config['database_name'])), 3600);
 | 
									$cache->set('database_checksum', serialize(sha1($config['database_host'] . '.' . $config['database_name'])), 3600);
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
@@ -209,7 +217,8 @@ class OTS_DB_MySQL extends OTS_Base_DB
 | 
				
			|||||||
		return $sql;
 | 
							return $sql;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	public function hasTable($name) {
 | 
						public function hasTable($name): bool
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
		if(isset($this->has_table_cache[$name])) {
 | 
							if(isset($this->has_table_cache[$name])) {
 | 
				
			||||||
			return $this->has_table_cache[$name];
 | 
								return $this->has_table_cache[$name];
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
@@ -217,12 +226,13 @@ class OTS_DB_MySQL extends OTS_Base_DB
 | 
				
			|||||||
		return $this->hasTableInternal($name);
 | 
							return $this->hasTableInternal($name);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	private function hasTableInternal($name) {
 | 
						private function hasTableInternal($name): bool
 | 
				
			||||||
		global $config;
 | 
						{
 | 
				
			||||||
		return ($this->has_table_cache[$name] = $this->query('SELECT `TABLE_NAME` FROM `information_schema`.`tables` WHERE `TABLE_SCHEMA` = ' . $this->quote($config['database_name']) . ' AND `TABLE_NAME` = ' . $this->quote($name) . ' LIMIT 1;')->rowCount() > 0);
 | 
							return ($this->has_table_cache[$name] = $this->query('SELECT `TABLE_NAME` FROM `information_schema`.`tables` WHERE `TABLE_SCHEMA` = ' . $this->quote(config('database_name')) . ' AND `TABLE_NAME` = ' . $this->quote($name) . ' LIMIT 1;')->rowCount() > 0);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	public function hasColumn($table, $column) {
 | 
						public function hasColumn($table, $column): bool
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
		if(isset($this->has_column_cache[$table . '.' . $column])) {
 | 
							if(isset($this->has_column_cache[$table . '.' . $column])) {
 | 
				
			||||||
			return $this->has_column_cache[$table . '.' . $column];
 | 
								return $this->has_column_cache[$table . '.' . $column];
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
@@ -230,8 +240,8 @@ class OTS_DB_MySQL extends OTS_Base_DB
 | 
				
			|||||||
		return $this->hasColumnInternal($table, $column);
 | 
							return $this->hasColumnInternal($table, $column);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	private function hasColumnInternal($table, $column) {
 | 
						private function hasColumnInternal($table, $column): bool {
 | 
				
			||||||
		return $this->hasTable($table) && ($this->has_column_cache[$table . '.' . $column] = count($this->query('SHOW COLUMNS FROM `' . $table . "` LIKE '" . $column . "'")->fetchAll()) > 0);
 | 
							return $this->hasTable($table) && ($this->has_column_cache[$table . '.' . $column] = count($this->query('SHOW COLUMNS FROM `' . $table . "` LIKE " . $this->quote($column))->fetchAll()) > 0);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	public function hasTableAndColumns(string $table, array $columns = []): bool
 | 
						public function hasTableAndColumns(string $table, array $columns = []): bool
 | 
				
			||||||
@@ -247,7 +257,53 @@ class OTS_DB_MySQL extends OTS_Base_DB
 | 
				
			|||||||
		return true;
 | 
							return true;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	public function revalidateCache() {
 | 
						public function getColumnInfo(string $table, string $column): bool|array
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							if(isset($this->get_column_info_cache[$table . '.' . $column])) {
 | 
				
			||||||
 | 
								return $this->get_column_info_cache[$table . '.' . $column];
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							return $this->getColumnInfoInternal($table, $column);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						private function getColumnInfoInternal(string $table, string $column): bool|array
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							if (!$this->hasTable($table) || !$this->hasColumn($table, $column)) {
 | 
				
			||||||
 | 
								return false;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							$formatResult = function ($result) {
 | 
				
			||||||
 | 
								return [
 | 
				
			||||||
 | 
									'field' => $result['Field'],
 | 
				
			||||||
 | 
									'type' => $result['Type'],
 | 
				
			||||||
 | 
									'null' => strtolower($result['Null']),
 | 
				
			||||||
 | 
									'default' => $result['Default'],
 | 
				
			||||||
 | 
									'extra' => $result['Extra'],
 | 
				
			||||||
 | 
								];
 | 
				
			||||||
 | 
							};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							$query = $this->query('SHOW COLUMNS FROM `' . $table . "` LIKE " . $this->quote($column));
 | 
				
			||||||
 | 
							$rowCount = $query->rowCount();
 | 
				
			||||||
 | 
							if ($rowCount > 1) {
 | 
				
			||||||
 | 
								$tmp = [];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								$results = $query->fetchAll(PDO::FETCH_ASSOC);
 | 
				
			||||||
 | 
								foreach ($results as $result) {
 | 
				
			||||||
 | 
									$tmp[] = $formatResult($result);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								return ($this->get_column_info_cache[$table . '.' . $column] = $tmp);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							else if ($rowCount == 1) {
 | 
				
			||||||
 | 
								$result = $query->fetch(PDO::FETCH_ASSOC);
 | 
				
			||||||
 | 
								return ($this->get_column_info_cache[$table . '.' . $column] = $formatResult($result));
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							return [];
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						public function revalidateCache(): void
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
		foreach($this->has_table_cache as $key => $value) {
 | 
							foreach($this->has_table_cache as $key => $value) {
 | 
				
			||||||
			$this->hasTableInternal($key);
 | 
								$this->hasTableInternal($key);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
@@ -262,6 +318,21 @@ class OTS_DB_MySQL extends OTS_Base_DB
 | 
				
			|||||||
				$this->hasColumnInternal($explode[0], $explode[1]);
 | 
									$this->hasColumnInternal($explode[0], $explode[1]);
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							foreach($this->get_column_info_cache as $key => $value) {
 | 
				
			||||||
 | 
								$explode = explode('.', $key);
 | 
				
			||||||
 | 
								if(!isset($this->has_table_cache[$explode[0]])) { // first check if table exist
 | 
				
			||||||
 | 
									$this->hasTableInternal($explode[0]);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if($this->has_table_cache[$explode[0]]) {
 | 
				
			||||||
 | 
									$this->hasColumnInternal($explode[0], $explode[1]);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if($this->has_table_cache[$explode[0]]) {
 | 
				
			||||||
 | 
									$this->getColumnInfoInternal($explode[0], $explode[1]);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	public function setClearCacheAfter($clearCache)
 | 
						public function setClearCacheAfter($clearCache)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2919,6 +2919,32 @@ class OTS_Player extends OTS_Row_DAO
 | 
				
			|||||||
		$this->data['banned'] = $ban['active'];
 | 
							$this->data['banned'] = $ban['active'];
 | 
				
			||||||
		$this->data['banned_time'] = $ban['expires'];
 | 
							$this->data['banned_time'] = $ban['expires'];
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						public function isNameLocked(): bool
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							// nothing can't be banned
 | 
				
			||||||
 | 
							if( !$this->isLoaded() ) {
 | 
				
			||||||
 | 
								throw new E_OTS_NotLoaded();
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if($this->db->hasTable('player_namelocks')) {
 | 
				
			||||||
 | 
								$ban = $this->db->query('SELECT 1 FROM `player_namelocks` WHERE `player_id` = ' . $this->data['id'])->fetch(PDO::FETCH_ASSOC);
 | 
				
			||||||
 | 
								return (isset($ban['1']));
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							else if($this->db->hasTable('bans')) {
 | 
				
			||||||
 | 
								if($this->db->hasColumn('bans', 'active')) {
 | 
				
			||||||
 | 
									$ban = $this->db->query('SELECT `active`, `expires` FROM `bans` WHERE `type` = 2 AND `active` = 1 AND `value` = ' . $this->data['id'] . ' AND (`expires` > ' . time() .' OR `expires` = -1) ORDER BY `expires` DESC')->fetch();
 | 
				
			||||||
 | 
									return isset($ban['active']);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								else { // tfs 0.2
 | 
				
			||||||
 | 
									$ban = $this->db->query('SELECT `time` FROM `bans` WHERE `type` = 2 AND `account` = ' . $this->data['account_id'] . ' AND (`time` > ' . time() .' OR `time` = -1) ORDER BY `time` DESC')->fetch();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									return isset($ban['time']) && ($ban['time'] == -1 || $ban['time'] > 0);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Deletes player.
 | 
					 * Deletes player.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
@@ -2953,21 +2979,14 @@ class OTS_Player extends OTS_Row_DAO
 | 
				
			|||||||
 * @return string Player proffesion name.
 | 
					 * @return string Player proffesion name.
 | 
				
			||||||
 * @throws E_OTS_NotLoaded If player is not loaded or global vocations list is not loaded.
 | 
					 * @throws E_OTS_NotLoaded If player is not loaded or global vocations list is not loaded.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
	public function getVocationName()
 | 
						public function getVocationName(): string
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		if( !isset($this->data['vocation']) )
 | 
							if( !isset($this->data['vocation']) )
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			throw new E_OTS_NotLoaded();
 | 
								throw new E_OTS_NotLoaded();
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		global $config;
 | 
							return OTS_Toolbox::getVocationName($this->data['vocation'], $this->data['promotion'] ?? 0);
 | 
				
			||||||
		$voc = $this->getVocation();
 | 
					 | 
				
			||||||
		if(!isset($config['vocations'][$voc])) {
 | 
					 | 
				
			||||||
			return 'Unknown';
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		return $config['vocations'][$voc];
 | 
					 | 
				
			||||||
		//return POT::getInstance()->getVocationsList()->getVocationName($this->data['vocation']);
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -110,6 +110,15 @@ class OTS_Toolbox
 | 
				
			|||||||
		$list->setFilter($filter);
 | 
							$list->setFilter($filter);
 | 
				
			||||||
		return $list;
 | 
							return $list;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						public static function getVocationName($id, $promotion = 0): string
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							if($promotion > 0) {
 | 
				
			||||||
 | 
								$id = ($id + ($promotion * config('vocations_amount')));
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							return config('vocations')[$id] ?? 'Unknown';
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**#@-*/
 | 
					/**#@-*/
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -78,6 +78,7 @@ $locale['step_database_error_mysql_connect_3'] = 'MySQL ist nicht richtig konfig
 | 
				
			|||||||
$locale['step_database_error_mysql_connect_4'] = 'MySQL-Server läuft nicht.';
 | 
					$locale['step_database_error_mysql_connect_4'] = 'MySQL-Server läuft nicht.';
 | 
				
			||||||
$locale['step_database_error_schema'] = 'Fehler beim Importieren des Schemas:';
 | 
					$locale['step_database_error_schema'] = 'Fehler beim Importieren des Schemas:';
 | 
				
			||||||
$locale['step_database_success_schema'] = '$PREFIX$ Tabellen wurden erfolgreich installiert.';
 | 
					$locale['step_database_success_schema'] = '$PREFIX$ Tabellen wurden erfolgreich installiert.';
 | 
				
			||||||
 | 
					$locale['step_database_success_import_data'] = 'Import von Daten für Tabellen was erfolgreich.';
 | 
				
			||||||
$locale['step_database_error_file'] = '$FILE$ konnte nicht geöffnet werden. Bitte kopieren Sie diesen Inhalt und fügen Sie ihn dort ein:';
 | 
					$locale['step_database_error_file'] = '$FILE$ konnte nicht geöffnet werden. Bitte kopieren Sie diesen Inhalt und fügen Sie ihn dort ein:';
 | 
				
			||||||
$locale['step_database_adding_field'] = 'Folgendes Feld wurde hinzugefügt: ';
 | 
					$locale['step_database_adding_field'] = 'Folgendes Feld wurde hinzugefügt: ';
 | 
				
			||||||
$locale['step_database_modifying_field'] = 'Folgendes Feld wurde geändert: ';
 | 
					$locale['step_database_modifying_field'] = 'Folgendes Feld wurde geändert: ';
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -83,6 +83,7 @@ $locale['step_database_error_mysql_connect_3'] = 'MySQL is not configured proper
 | 
				
			|||||||
$locale['step_database_error_mysql_connect_4'] = 'MySQL server is not running.';
 | 
					$locale['step_database_error_mysql_connect_4'] = 'MySQL server is not running.';
 | 
				
			||||||
$locale['step_database_error_schema'] = 'Error while importing schema:';
 | 
					$locale['step_database_error_schema'] = 'Error while importing schema:';
 | 
				
			||||||
$locale['step_database_success_schema'] = 'Successfully installed $PREFIX$ tables.';
 | 
					$locale['step_database_success_schema'] = 'Successfully installed $PREFIX$ tables.';
 | 
				
			||||||
 | 
					$locale['step_database_success_import_data'] = 'Successfully imported base data for tables.';
 | 
				
			||||||
$locale['step_database_error_file'] = '$FILE$ couldn\'t be opened. Please copy this content and paste there:';
 | 
					$locale['step_database_error_file'] = '$FILE$ couldn\'t be opened. Please copy this content and paste there:';
 | 
				
			||||||
$locale['step_database_adding_field'] = 'Adding field';
 | 
					$locale['step_database_adding_field'] = 'Adding field';
 | 
				
			||||||
$locale['step_database_modifying_field'] = 'Modifying field';
 | 
					$locale['step_database_modifying_field'] = 'Modifying field';
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -81,7 +81,8 @@ $locale['step_database_error_mysql_connect_2'] = 'Możliwe przyczyny:';
 | 
				
			|||||||
$locale['step_database_error_mysql_connect_3'] = 'MySQL nie jest poprawnie skonfigurowane w <i>config.lua</i>.';
 | 
					$locale['step_database_error_mysql_connect_3'] = 'MySQL nie jest poprawnie skonfigurowane w <i>config.lua</i>.';
 | 
				
			||||||
$locale['step_database_error_mysql_connect_4'] = 'Serwer MySQL nie jest uruchomiony.';
 | 
					$locale['step_database_error_mysql_connect_4'] = 'Serwer MySQL nie jest uruchomiony.';
 | 
				
			||||||
$locale['step_database_error_schema'] = 'Błąd podczas importowania struktury bazy danych:';
 | 
					$locale['step_database_error_schema'] = 'Błąd podczas importowania struktury bazy danych:';
 | 
				
			||||||
$locale['step_database_success_schema'] = 'Pomyślnie zainstalowano tabele $PREFIX$.';
 | 
					$locale['step_database_success_schema'] = 'Pomyślnie zaimportowano tabele $PREFIX$.';
 | 
				
			||||||
 | 
					$locale['step_database_success_import_data'] = 'Pomyślnie załadowano bazowe dane dla tabel.';
 | 
				
			||||||
$locale['step_database_error_file'] = '$FILE$ nie mógł zostać otwarty. Proszę skopiować zawartość pola tekstowego i wkleić do tego pliku:';
 | 
					$locale['step_database_error_file'] = '$FILE$ nie mógł zostać otwarty. Proszę skopiować zawartość pola tekstowego i wkleić do tego pliku:';
 | 
				
			||||||
$locale['step_database_adding_field'] = 'Dodawanie pola';
 | 
					$locale['step_database_adding_field'] = 'Dodawanie pola';
 | 
				
			||||||
$locale['step_database_modifying_field'] = 'Modyfikacja pola';
 | 
					$locale['step_database_modifying_field'] = 'Modyfikacja pola';
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -34,8 +34,10 @@ if($logged) {
 | 
				
			|||||||
	$twig->addGlobal('account_logged', $account_logged);
 | 
						$twig->addGlobal('account_logged', $account_logged);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if (!defined('IGNORE_SET_LAST_VISIT') || !IGNORE_SET_LAST_VISIT) {
 | 
				
			||||||
	setSession('last_visit', time());
 | 
						setSession('last_visit', time());
 | 
				
			||||||
	if(defined('PAGE')) {
 | 
						if(defined('PAGE')) {
 | 
				
			||||||
		setSession('last_page', PAGE);
 | 
							setSession('last_page', PAGE);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	setSession('last_uri', $_SERVER['REQUEST_URI']);
 | 
						setSession('last_uri', $_SERVER['REQUEST_URI']);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -9,6 +9,8 @@
 | 
				
			|||||||
 */
 | 
					 */
 | 
				
			||||||
defined('MYAAC') or die('Direct access not allowed!');
 | 
					defined('MYAAC') or die('Direct access not allowed!');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					global $db;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// database migrations
 | 
					// database migrations
 | 
				
			||||||
$tmp = '';
 | 
					$tmp = '';
 | 
				
			||||||
if(fetchDatabaseConfig('database_version', $tmp)) { // we got version
 | 
					if(fetchDatabaseConfig('database_version', $tmp)) { // we got version
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										8
									
								
								system/migrations/46-account_emails_verify.sql
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								system/migrations/46-account_emails_verify.sql
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,8 @@
 | 
				
			|||||||
 | 
					CREATE TABLE `myaac_account_emails_verify`
 | 
				
			||||||
 | 
					(
 | 
				
			||||||
 | 
						`id` int NOT NULL AUTO_INCREMENT,
 | 
				
			||||||
 | 
						`account_id` int NOT NULL,
 | 
				
			||||||
 | 
						`hash` varchar(32) NOT NULL,
 | 
				
			||||||
 | 
						`sent_at` int NOT NULL DEFAULT 0,
 | 
				
			||||||
 | 
						PRIMARY KEY (`id`)
 | 
				
			||||||
 | 
					) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4;
 | 
				
			||||||
							
								
								
									
										24
									
								
								system/migrations/46.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								system/migrations/46.php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,24 @@
 | 
				
			|||||||
 | 
					<?php
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @var OTS_DB_MySQL $db
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					$up = function () use ($db) {
 | 
				
			||||||
 | 
						if ($db->hasColumn('accounts', 'email_hash')) {
 | 
				
			||||||
 | 
							$db->dropColumn('accounts', 'email_hash');
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!$db->hasTable(TABLE_PREFIX . 'account_emails_verify')) {
 | 
				
			||||||
 | 
							$db->query(file_get_contents(__DIR__ . '/46-account_emails_verify.sql'));
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					$down = function () use ($db) {
 | 
				
			||||||
 | 
						if (!$db->hasColumn('accounts', 'email_hash')) {
 | 
				
			||||||
 | 
							$db->addColumn('accounts', 'email_hash', "varchar(32) NOT NULL DEFAULT ''");
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if ($db->hasTable(TABLE_PREFIX . 'account_emails_verify')) {
 | 
				
			||||||
 | 
							$db->dropTable(TABLE_PREFIX . 'account_emails_verify');
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
@@ -8,7 +8,7 @@
 | 
				
			|||||||
 * @link      https://my-aac.org
 | 
					 * @link      https://my-aac.org
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
defined('MYAAC') or die('Direct access not allowed!');
 | 
					defined('MYAAC') or die('Direct access not allowed!');
 | 
				
			||||||
$title = '404 Not Found';
 | 
					$title = 'Not Found';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
header('HTTP/1.0 404 Not Found');
 | 
					header('HTTP/1.0 404 Not Found');
 | 
				
			||||||
?>
 | 
					?>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -8,7 +8,7 @@
 | 
				
			|||||||
 * @link      https://my-aac.org
 | 
					 * @link      https://my-aac.org
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
defined('MYAAC') or die('Direct access not allowed!');
 | 
					defined('MYAAC') or die('Direct access not allowed!');
 | 
				
			||||||
$title = '405 Method Not Allowed';
 | 
					$title = 'Method Not Allowed';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
header('HTTP/1.0 405 Method Not Allowed');
 | 
					header('HTTP/1.0 405 Method Not Allowed');
 | 
				
			||||||
?>
 | 
					?>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -166,7 +166,7 @@ if(isset($_POST['emailchangecancel']) && $_POST['emailchangecancel'] == 1) {
 | 
				
			|||||||
	$account_logged->setCustomField("email_new", "");
 | 
						$account_logged->setCustomField("email_new", "");
 | 
				
			||||||
	$account_logged->setCustomField("email_new_time", 0);
 | 
						$account_logged->setCustomField("email_new_time", 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	$custom_buttons = '<div style="text-align:center"><table border="0" cellspacing="0" cellpadding="0" ><form action="' . getLink('account/manage') . '" method="post" ><tr><td style="border:0px;" >' . $twig->render('buttons.back.html.twig') . '</td></tr></form></table></div>';
 | 
						$custom_buttons = '<div style="text-align:center"><table border="0" cellspacing="0" cellpadding="0" ><form action="' . getLink('account/manage') . '" method="post" >' . csrf(true) . '<tr><td style="border:0px;" >' . $twig->render('buttons.back.html.twig') . '</td></tr></form></table></div>';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	$twig->display('success.html.twig', array(
 | 
						$twig->display('success.html.twig', array(
 | 
				
			||||||
		'title' => 'Email Address Change Cancelled',
 | 
							'title' => 'Email Address Change Cancelled',
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -19,18 +19,17 @@ if(!$logged) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
csrfProtect();
 | 
					csrfProtect();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
$new_password = $_POST['newpassword'] ?? NULL;
 | 
					$new_password = $_POST['new_password'] ?? null;
 | 
				
			||||||
$new_password_confirm = $_POST['newpassword_confirm'] ?? NULL;
 | 
					$new_password_confirm = $_POST['new_password_confirm'] ?? null;
 | 
				
			||||||
$old_password = $_POST['oldpassword'] ?? NULL;
 | 
					$old_password = $_POST['old_password'] ?? null;
 | 
				
			||||||
if(empty($new_password) && empty($new_password_confirm) && empty($old_password)) {
 | 
					if(empty($new_password) && empty($new_password_confirm) && empty($old_password)) {
 | 
				
			||||||
	$twig->display('account.change-password.html.twig');
 | 
						$twig->display('account.change-password.html.twig');
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
else
 | 
					else {
 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	if(empty($new_password) || empty($new_password_confirm) || empty($old_password)){
 | 
						if(empty($new_password) || empty($new_password_confirm) || empty($old_password)){
 | 
				
			||||||
		$errors[] = 'Please fill in form.';
 | 
							$errors[] = 'Please fill in form.';
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	$password_strlen = strlen($new_password);
 | 
					
 | 
				
			||||||
	if($new_password != $new_password_confirm) {
 | 
						if($new_password != $new_password_confirm) {
 | 
				
			||||||
		$errors[] = 'The new passwords do not match!';
 | 
							$errors[] = 'The new passwords do not match!';
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -41,10 +40,13 @@ else
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		/** @var OTS_Account $account_logged */
 | 
							/** @var OTS_Account $account_logged */
 | 
				
			||||||
		$old_password = encrypt((USE_ACCOUNT_SALT ? $account_logged->getCustomField('salt') : '') . $old_password);
 | 
							$old_password_hashed = encrypt((USE_ACCOUNT_SALT ? $account_logged->getCustomField('salt') : '') . $old_password);
 | 
				
			||||||
		if($old_password != $account_logged->getPassword()) {
 | 
							if($old_password_hashed != $account_logged->getPassword()) {
 | 
				
			||||||
			$errors[] = 'Current password is incorrect!';
 | 
								$errors[] = 'Current password is incorrect!';
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
							else if ($old_password == $new_password) {
 | 
				
			||||||
 | 
								$errors[] = 'The old password is same as the new password!';
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		$hooks->trigger(HOOK_ACCOUNT_CHANGE_PASSWORD_POST);
 | 
							$hooks->trigger(HOOK_ACCOUNT_CHANGE_PASSWORD_POST);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -9,6 +9,7 @@
 | 
				
			|||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use MyAAC\Models\Account;
 | 
					use MyAAC\Models\Account;
 | 
				
			||||||
 | 
					use MyAAC\Models\AccountEmailVerify;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
defined('MYAAC') or die('Direct access not allowed!');
 | 
					defined('MYAAC') or die('Direct access not allowed!');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -20,16 +21,20 @@ if(empty($hash)) {
 | 
				
			|||||||
	return;
 | 
						return;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
if(!Account::where('email_hash', $hash)->exists()) {
 | 
					// by default link is valid for 30 days
 | 
				
			||||||
	note("Your email couldn't be verified. Please contact staff to do it manually.");
 | 
					$accountEmailVerify = AccountEmailVerify::where('hash', $hash)->where('sent_at', '>', time() - 30 * 24 * 60 * 60)->first();
 | 
				
			||||||
 | 
					if(!$accountEmailVerify) {
 | 
				
			||||||
 | 
						note("Wrong link or link has expired.");
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
else
 | 
					else
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	$accountModel = Account::where('email_hash', $hash)->where('email_verified', 0)->first();
 | 
						$accountModel = Account::where('id', $accountEmailVerify->account_id)->where('email_verified', 0)->first();
 | 
				
			||||||
	if ($accountModel) {
 | 
						if ($accountModel) {
 | 
				
			||||||
		$accountModel->email_verified = 1;
 | 
							$accountModel->email_verified = 1;
 | 
				
			||||||
		$accountModel->save();
 | 
							$accountModel->save();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							AccountEmailVerify::where('account_id', $accountModel->id)->delete();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		success('You have now verified your e-mail, this will increase the security of your account. Thank you for doing this. You can now <a href=' . getLink('account/manage') . '>log in</a>.');
 | 
							success('You have now verified your e-mail, this will increase the security of your account. Thank you for doing this. You can now <a href=' . getLink('account/manage') . '>log in</a>.');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		$account = new OTS_Account();
 | 
							$account = new OTS_Account();
 | 
				
			||||||
@@ -39,6 +44,6 @@ else
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	else {
 | 
						else {
 | 
				
			||||||
		error('Link has expired.');
 | 
							error('Your account is already verified.');
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -10,6 +10,7 @@
 | 
				
			|||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use MyAAC\CreateCharacter;
 | 
					use MyAAC\CreateCharacter;
 | 
				
			||||||
 | 
					use MyAAC\Models\AccountEmailVerify;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
defined('MYAAC') or die('Direct access not allowed!');
 | 
					defined('MYAAC') or die('Direct access not allowed!');
 | 
				
			||||||
$title = 'Create Account';
 | 
					$title = 'Create Account';
 | 
				
			||||||
@@ -227,10 +228,15 @@ if($save)
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		$accountDefaultCoins = setting('core.account_coins');
 | 
							$accountDefaultCoins = setting('core.account_coins');
 | 
				
			||||||
		if($db->hasColumn('accounts', 'coins') && $accountDefaultCoins > 0) {
 | 
							if(HAS_ACCOUNT_COINS && $accountDefaultCoins > 0) {
 | 
				
			||||||
			$new_account->setCustomField('coins', $accountDefaultCoins);
 | 
								$new_account->setCustomField('coins', $accountDefaultCoins);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							$accountDefaultCoinsTransferable = setting('core.account_coins_transferable');
 | 
				
			||||||
 | 
							if((HAS_ACCOUNT_COINS_TRANSFERABLE || HAS_ACCOUNT_TRANSFERABLE_COINS) && $accountDefaultCoinsTransferable > 0) {
 | 
				
			||||||
 | 
								$new_account->setCustomField(ACCOUNT_COINS_TRANSFERABLE_COLUMN, $accountDefaultCoinsTransferable);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		$tmp_account = $email;
 | 
							$tmp_account = $email;
 | 
				
			||||||
		if (!config('account_login_by_email')) {
 | 
							if (!config('account_login_by_email')) {
 | 
				
			||||||
			$tmp_account = (USE_ACCOUNT_NAME ? $account_name : $account_id);
 | 
								$tmp_account = (USE_ACCOUNT_NAME ? $account_name : $account_id);
 | 
				
			||||||
@@ -239,7 +245,12 @@ if($save)
 | 
				
			|||||||
		if(setting('core.mail_enabled') && setting('core.account_mail_verify'))
 | 
							if(setting('core.mail_enabled') && setting('core.account_mail_verify'))
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			$hash = md5(generateRandomString(16, true, true) . $email);
 | 
								$hash = md5(generateRandomString(16, true, true) . $email);
 | 
				
			||||||
			$new_account->setCustomField('email_hash', $hash);
 | 
					
 | 
				
			||||||
 | 
								AccountEmailVerify::create([
 | 
				
			||||||
 | 
									'account_id' => $new_account->getId(),
 | 
				
			||||||
 | 
									'hash' => $hash,
 | 
				
			||||||
 | 
									'sent_at' => time(),
 | 
				
			||||||
 | 
								]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			$verify_url = getLink('account/confirm-email/' . $hash);
 | 
								$verify_url = getLink('account/confirm-email/' . $hash);
 | 
				
			||||||
			$body_html = $twig->render('mail.account.verify.html.twig', array(
 | 
								$body_html = $twig->render('mail.account.verify.html.twig', array(
 | 
				
			||||||
@@ -263,8 +274,10 @@ if($save)
 | 
				
			|||||||
			}
 | 
								}
 | 
				
			||||||
			else
 | 
								else
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
				error('An error occorred while sending email! Account not created. Try again. For Admin: More info can be found in system/logs/mailer-error.log');
 | 
									error('An error occurred while sending email! Account not created. Try again. For Admin: More info can be found in system/logs/mailer-error.log');
 | 
				
			||||||
				$new_account->delete();
 | 
									$new_account->delete();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									return;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		else
 | 
							else
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -48,7 +48,9 @@ if(!empty($login_account) && !empty($login_password))
 | 
				
			|||||||
	)
 | 
						)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		if (setting('core.account_mail_verify') && (int)$account_logged->getCustomField('email_verified') !== 1) {
 | 
							if (setting('core.account_mail_verify') && (int)$account_logged->getCustomField('email_verified') !== 1) {
 | 
				
			||||||
			$errors[] = 'Your account is not verified. Please verify your email address. If the message is not coming check the SPAM folder in your E-Mail client.';
 | 
								$link = getLink('account/resend-email-verify');
 | 
				
			||||||
 | 
								$errors[] = 'Your account is not verified. Please verify your email address. If the message is not coming check the SPAM folder in your E-Mail client.<br/>' .
 | 
				
			||||||
 | 
									'You can resend the Email here: <a href="' . $link . '">' . $link . '</a>';
 | 
				
			||||||
		} else {
 | 
							} else {
 | 
				
			||||||
			session_regenerate_id();
 | 
								session_regenerate_id();
 | 
				
			||||||
			setSession('account', $account_logged->getId());
 | 
								setSession('account', $account_logged->getId());
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -9,540 +9,11 @@
 | 
				
			|||||||
 * @link      https://my-aac.org
 | 
					 * @link      https://my-aac.org
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
defined('MYAAC') or die('Direct access not allowed!');
 | 
					defined('MYAAC') or die('Direct access not allowed!');
 | 
				
			||||||
$title = 'Lost Account Interface';
 | 
					$title = 'Lost Account';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
if(!setting('core.mail_enabled'))
 | 
					if(!setting('core.mail_enabled')) {
 | 
				
			||||||
{
 | 
						echo "<b>Account maker is not configured to send e-mails, you can't use Lost Account Interface. Contact with admin to get help.</b>";
 | 
				
			||||||
	echo '<b>Account maker is not configured to send e-mails, you can\'t use Lost Account Interface. Contact with admin to get help.</b>';
 | 
					 | 
				
			||||||
	return;
 | 
						return;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
$action_type = isset($_REQUEST['action_type']) ? $_REQUEST['action_type'] : '';
 | 
					$twig->display('account/lost/form.html.twig');
 | 
				
			||||||
if($action == '')
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	$twig->display('account.lost.form.html.twig');
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
else if($action == 'step1' && $action_type == '') {
 | 
					 | 
				
			||||||
	$twig->display('account.lost.noaction.html.twig');
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
elseif($action == 'step1' && $action_type == 'email')
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	$nick = stripslashes($_REQUEST['nick']);
 | 
					 | 
				
			||||||
	if(Validator::characterName($nick))
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		$player = new OTS_Player();
 | 
					 | 
				
			||||||
		$account = new OTS_Account();
 | 
					 | 
				
			||||||
		$player->find($nick);
 | 
					 | 
				
			||||||
		if($player->isLoaded())
 | 
					 | 
				
			||||||
			$account = $player->getAccount();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		if($account->isLoaded())
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			if($account->getCustomField('email_next') < time())
 | 
					 | 
				
			||||||
				echo 'Please enter e-mail to account with this character.<BR>
 | 
					 | 
				
			||||||
				<form action="' . getLink('account/lost') . '?action=sendcode" method=post>
 | 
					 | 
				
			||||||
				<input type=hidden name="character">
 | 
					 | 
				
			||||||
				<table cellspacing=1 cellpadding=4 border=0 width=100%>
 | 
					 | 
				
			||||||
				<TR><TD BGCOLOR="'.$config['vdarkborder'].'" class="white"><B>Please enter e-mail to account</B></TD></TR>
 | 
					 | 
				
			||||||
				<TR><TD BGCOLOR="'.$config['darkborder'].'">
 | 
					 | 
				
			||||||
				Character: <INPUT TYPE=text NAME="nick" VALUE="'.$nick.'" SIZE="40" readonly="readonly"><BR>
 | 
					 | 
				
			||||||
				E-mail to account:<INPUT TYPE=text NAME="email" VALUE="" SIZE="40"><BR>
 | 
					 | 
				
			||||||
				</TD></TR>
 | 
					 | 
				
			||||||
				</TABLE>
 | 
					 | 
				
			||||||
				<BR>
 | 
					 | 
				
			||||||
				<TABLE CELLSPACING=0 CELLPADDING=0 BORDER=0 WIDTH=100%><TR><TD><div style="text-align:center">
 | 
					 | 
				
			||||||
				' . $twig->render('buttons.submit.html.twig') . '</div>
 | 
					 | 
				
			||||||
				</TD></TR></FORM></TABLE></TABLE>';
 | 
					 | 
				
			||||||
			else
 | 
					 | 
				
			||||||
			{
 | 
					 | 
				
			||||||
				$insec = (int)$account->getCustomField('email_next') - time();
 | 
					 | 
				
			||||||
				$minutesleft = floor($insec / 60);
 | 
					 | 
				
			||||||
				$secondsleft = $insec - ($minutesleft * 60);
 | 
					 | 
				
			||||||
				$timeleft = $minutesleft.' minutes '.$secondsleft.' seconds';
 | 
					 | 
				
			||||||
				echo 'Account of selected character (<b>'.$nick.'</b>) received e-mail in last '.ceil(setting('core.mail_lost_account_interval') / 60).' minutes. You must wait '.$timeleft.' before you can use Lost Account Interface again.';
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		else
 | 
					 | 
				
			||||||
			echo 'Player or account of player <b>' . $nick . '</b> doesn\'t exist.';
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	else
 | 
					 | 
				
			||||||
		echo 'Invalid player name format. If you have other characters on account try with other name.';
 | 
					 | 
				
			||||||
	echo '<BR /><TABLE CELLSPACING=0 CELLPADDING=0 BORDER=0 WIDTH=100%><TR><TD><div style="text-align:center">
 | 
					 | 
				
			||||||
				<a href="' . getLink('account/lost') . '" border="0"><IMG SRC="'.$template_path.'/images/global/buttons/sbutton_back.gif" NAME="Back" ALT="Back" BORDER=0 WIDTH=120 HEIGHT=18></a></div>
 | 
					 | 
				
			||||||
				</TD></TR></FORM></TABLE></TABLE>';
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
elseif($action == 'sendcode')
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	$email = $_REQUEST['email'];
 | 
					 | 
				
			||||||
	$nick = stripslashes($_REQUEST['nick']);
 | 
					 | 
				
			||||||
	if(Validator::characterName($nick))
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		$player = new OTS_Player();
 | 
					 | 
				
			||||||
		$account = new OTS_Account();
 | 
					 | 
				
			||||||
		$player->find($nick);
 | 
					 | 
				
			||||||
		if($player->isLoaded())
 | 
					 | 
				
			||||||
			$account = $player->getAccount();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		if($account->isLoaded())
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			if($account->getCustomField('email_next') < time())
 | 
					 | 
				
			||||||
			{
 | 
					 | 
				
			||||||
				if($account->getEMail() == $email)
 | 
					 | 
				
			||||||
				{
 | 
					 | 
				
			||||||
					$newcode = generateRandomString(30, true, false, true);
 | 
					 | 
				
			||||||
					$mailBody = '
 | 
					 | 
				
			||||||
					You asked to reset your ' . $config['lua']['serverName'] . ' password.<br/>
 | 
					 | 
				
			||||||
					<p>Account name: '.$account->getName().'</p>
 | 
					 | 
				
			||||||
					<br />
 | 
					 | 
				
			||||||
					To do so, please click this link:
 | 
					 | 
				
			||||||
					<p><a href="' . getLink('account/lost') . '?action=checkcode&code='.$newcode.'&character='.urlencode($nick).'">' . getLink('account/lost') . '?action=checkcode&code='.$newcode.'&character='.urlencode($nick).'</a></p>
 | 
					 | 
				
			||||||
					<p>or open page: <i>' . getLink('account/lost') . '?action=checkcode</i> and in field "code" write <b>'.$newcode.'</b></p>
 | 
					 | 
				
			||||||
					<br/>
 | 
					 | 
				
			||||||
						<p>If you did not request a password change, you may ignore this message and your password will remain unchanged.';
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
					$account_mail = $account->getCustomField('email');
 | 
					 | 
				
			||||||
					if(_mail($account_mail, $config['lua']['serverName'].' - Recover your account', $mailBody))
 | 
					 | 
				
			||||||
					{
 | 
					 | 
				
			||||||
						$account->setCustomField('email_code', $newcode);
 | 
					 | 
				
			||||||
						$account->setCustomField('email_next', (time() + setting('core.mail_lost_account_interval')));
 | 
					 | 
				
			||||||
						echo '<br />Details about steps required to recover your account has been sent to <b>' . $account_mail . '</b>. You should receive this email within 15 minutes. Please check your inbox/spam directory.';
 | 
					 | 
				
			||||||
					}
 | 
					 | 
				
			||||||
					else
 | 
					 | 
				
			||||||
					{
 | 
					 | 
				
			||||||
						$account->setCustomField('email_next', (time() + 60));
 | 
					 | 
				
			||||||
						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
 | 
					 | 
				
			||||||
					echo 'Invalid e-mail to account of character <b>'.$nick.'</b>. Try again.';
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			else
 | 
					 | 
				
			||||||
			{
 | 
					 | 
				
			||||||
				$insec = (int)$account->getCustomField('email_next') - time();
 | 
					 | 
				
			||||||
				$minutesleft = floor($insec / 60);
 | 
					 | 
				
			||||||
				$secondsleft = $insec - ($minutesleft * 60);
 | 
					 | 
				
			||||||
				$timeleft = $minutesleft.' minutes '.$secondsleft.' seconds';
 | 
					 | 
				
			||||||
				echo 'Account of selected character (<b>'.$nick.'</b>) received e-mail in last '.ceil(setting('core.mail_lost_account_interval') / 60).' minutes. You must wait '.$timeleft.' before you can use Lost Account Interface again.';
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		else
 | 
					 | 
				
			||||||
			echo 'Player or account of player <b>'.$nick.'</b> doesn\'t exist.';
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	else
 | 
					 | 
				
			||||||
		echo 'Invalid player name format. If you have other characters on account try with other name.';
 | 
					 | 
				
			||||||
	echo '<BR /><TABLE CELLSPACING=0 CELLPADDING=0 BORDER=0 WIDTH=100%><TR><TD><div style="text-align:center">
 | 
					 | 
				
			||||||
				<a href="' . getLink('account/lost') . '?action=step1&action_type=email&nick='.urlencode($nick).'" border="0"><IMG SRC="'.$template_path.'/images/global/buttons/sbutton_back.gif" NAME="Back" ALT="Back" BORDER=0 WIDTH=120 HEIGHT=18></a></div>
 | 
					 | 
				
			||||||
				</TD></TR></FORM></TABLE></TABLE>';
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
elseif($action == 'step1' && $action_type == 'reckey')
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	$nick = stripslashes($_REQUEST['nick']);
 | 
					 | 
				
			||||||
	if(Validator::characterName($nick))
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		$player = new OTS_Player();
 | 
					 | 
				
			||||||
		$account = new OTS_Account();
 | 
					 | 
				
			||||||
		$player->find($nick);
 | 
					 | 
				
			||||||
		if($player->isLoaded())
 | 
					 | 
				
			||||||
			$account = $player->getAccount();
 | 
					 | 
				
			||||||
		if($account->isLoaded())
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			$account_key = $account->getCustomField('key');
 | 
					 | 
				
			||||||
			if(!empty($account_key))
 | 
					 | 
				
			||||||
			{
 | 
					 | 
				
			||||||
						echo 'If you enter right recovery key you will see form to set new e-mail and password to account. To this e-mail will be send your new password and account name.<BR>
 | 
					 | 
				
			||||||
						<FORM ACTION="' . getLink('account/lost') . '?action=step2" METHOD=post>
 | 
					 | 
				
			||||||
						<TABLE CELLSPACING=1 CELLPADDING=4 BORDER=0 WIDTH=100%>
 | 
					 | 
				
			||||||
						<TR><TD BGCOLOR="'.$config['vdarkborder'].'" class="white"><B>Please enter your recovery key</B></TD></TR>
 | 
					 | 
				
			||||||
						<TR><TD BGCOLOR="'.$config['darkborder'].'">
 | 
					 | 
				
			||||||
						Character name: <INPUT TYPE=text NAME="nick" VALUE="'.$nick.'" SIZE="40" readonly="readonly"><BR />
 | 
					 | 
				
			||||||
						Recovery key:    <INPUT TYPE=text NAME="key" VALUE="" SIZE="40"><BR>
 | 
					 | 
				
			||||||
						</TD></TR>
 | 
					 | 
				
			||||||
						</TABLE>
 | 
					 | 
				
			||||||
						<BR>
 | 
					 | 
				
			||||||
						<TABLE CELLSPACING=0 CELLPADDING=0 BORDER=0 WIDTH=100%><TR><TD><div style="text-align:center">
 | 
					 | 
				
			||||||
						' . $twig->render('buttons.submit.html.twig') . '</div>
 | 
					 | 
				
			||||||
						</TD></TR></FORM></TABLE></TABLE>';
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			else
 | 
					 | 
				
			||||||
				echo 'Account of this character has no recovery key!';
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		else
 | 
					 | 
				
			||||||
			echo 'Player or account of player <b>'.$nick.'</b> doesn\'t exist.';
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	else
 | 
					 | 
				
			||||||
		echo 'Invalid player name format. If you have other characters on account try with other name.';
 | 
					 | 
				
			||||||
	echo '<BR /><TABLE CELLSPACING=0 CELLPADDING=0 BORDER=0 WIDTH=100%><TR><TD><div style="text-align:center">
 | 
					 | 
				
			||||||
				<a href="' . getLink('account/lost') . '" border="0"><IMG SRC="'.$template_path.'/images/global/buttons/sbutton_back.gif" NAME="Back" ALT="Back" BORDER=0 WIDTH=120 HEIGHT=18></a></div>
 | 
					 | 
				
			||||||
				</TD></TR></FORM></TABLE></TABLE>';
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
elseif($action == 'step2')
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	$rec_key = trim($_REQUEST['key']);
 | 
					 | 
				
			||||||
	$nick = stripslashes($_REQUEST['nick']);
 | 
					 | 
				
			||||||
	if(Validator::characterName($nick))
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		$player = new OTS_Player();
 | 
					 | 
				
			||||||
		$account = new OTS_Account();
 | 
					 | 
				
			||||||
		$player->find($nick);
 | 
					 | 
				
			||||||
		if($player->isLoaded())
 | 
					 | 
				
			||||||
			$account = $player->getAccount();
 | 
					 | 
				
			||||||
		if($account->isLoaded())
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			$account_key = $account->getCustomField('key');
 | 
					 | 
				
			||||||
			if(!empty($account_key))
 | 
					 | 
				
			||||||
			{
 | 
					 | 
				
			||||||
				if($account_key == $rec_key)
 | 
					 | 
				
			||||||
				{
 | 
					 | 
				
			||||||
					echo '<script type="text/javascript">
 | 
					 | 
				
			||||||
					function validate_required(field,alerttxt)
 | 
					 | 
				
			||||||
					{
 | 
					 | 
				
			||||||
					with (field)
 | 
					 | 
				
			||||||
					{
 | 
					 | 
				
			||||||
					if (value==null||value==""||value==" ")
 | 
					 | 
				
			||||||
					  {alert(alerttxt);return false;}
 | 
					 | 
				
			||||||
					else {return true}
 | 
					 | 
				
			||||||
					}
 | 
					 | 
				
			||||||
					}
 | 
					 | 
				
			||||||
					function validate_email(field,alerttxt)
 | 
					 | 
				
			||||||
					{
 | 
					 | 
				
			||||||
					with (field)
 | 
					 | 
				
			||||||
					{
 | 
					 | 
				
			||||||
					apos=value.indexOf("@");
 | 
					 | 
				
			||||||
					dotpos=value.lastIndexOf(".");
 | 
					 | 
				
			||||||
					if (apos<1||dotpos-apos<2)
 | 
					 | 
				
			||||||
					  {alert(alerttxt);return false;}
 | 
					 | 
				
			||||||
					else {return true;}
 | 
					 | 
				
			||||||
					}
 | 
					 | 
				
			||||||
					}
 | 
					 | 
				
			||||||
					function validate_form(thisform)
 | 
					 | 
				
			||||||
					{
 | 
					 | 
				
			||||||
					with (thisform)
 | 
					 | 
				
			||||||
					{
 | 
					 | 
				
			||||||
					if (validate_required(email,"Please enter your e-mail!")==false)
 | 
					 | 
				
			||||||
					  {email.focus();return false;}
 | 
					 | 
				
			||||||
					if (validate_email(email,"Invalid e-mail format!")==false)
 | 
					 | 
				
			||||||
					  {email.focus();return false;}
 | 
					 | 
				
			||||||
					if (validate_required(passor,"Please enter password!")==false)
 | 
					 | 
				
			||||||
					  {passor.focus();return false;}
 | 
					 | 
				
			||||||
					if (validate_required(passor2,"Please repeat password!")==false)
 | 
					 | 
				
			||||||
					  {passor2.focus();return false;}
 | 
					 | 
				
			||||||
					if (passor2.value!=passor.value)
 | 
					 | 
				
			||||||
					  {alert(\'Repeated password is not equal to password!\');return false;}
 | 
					 | 
				
			||||||
					}
 | 
					 | 
				
			||||||
					}
 | 
					 | 
				
			||||||
					</script>';
 | 
					 | 
				
			||||||
					echo 'Set new password and e-mail to your account.<BR>
 | 
					 | 
				
			||||||
					<FORM ACTION="' . getLink('account/lost') . '?action=step3" onsubmit="return validate_form(this)" METHOD=post>
 | 
					 | 
				
			||||||
					<INPUT TYPE=hidden NAME="character" VALUE="">
 | 
					 | 
				
			||||||
					<TABLE CELLSPACING=1 CELLPADDING=4 BORDER=0 WIDTH=100%>
 | 
					 | 
				
			||||||
					<TR><TD BGCOLOR="'.$config['vdarkborder'].'" class="white"><B>Please enter new password and e-mail</B></TD></TR>
 | 
					 | 
				
			||||||
					<TR><TD BGCOLOR="'.$config['darkborder'].'">
 | 
					 | 
				
			||||||
					Account of character:  <INPUT TYPE=text NAME="nick" VALUE="'.$nick.'" SIZE="40" readonly="readonly"><BR />
 | 
					 | 
				
			||||||
					New password:            <INPUT id="passor" TYPE=password NAME="passor" VALUE="" SIZE="40"><BR>
 | 
					 | 
				
			||||||
					Repeat new password:  <INPUT id="passor2" TYPE=password NAME="passor" VALUE="" SIZE="40"><BR>
 | 
					 | 
				
			||||||
					New e-mail address:     <INPUT id="email" TYPE=text NAME="email" VALUE="" SIZE="40"><BR>
 | 
					 | 
				
			||||||
					<INPUT TYPE=hidden NAME="key" VALUE="'.$rec_key.'">
 | 
					 | 
				
			||||||
					</TD></TR>
 | 
					 | 
				
			||||||
					</TABLE>
 | 
					 | 
				
			||||||
					<BR>
 | 
					 | 
				
			||||||
					<TABLE CELLSPACING=0 CELLPADDING=0 BORDER=0 WIDTH=100%><TR><TD><div style="text-align:center">
 | 
					 | 
				
			||||||
					' . $twig->render('buttons.submit.html.twig') . '</div>
 | 
					 | 
				
			||||||
					</TD></TR></FORM></TABLE></TABLE>';
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				else
 | 
					 | 
				
			||||||
					echo 'Wrong recovery key!';
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			else
 | 
					 | 
				
			||||||
				echo 'Account of this character has no recovery key!';
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		else
 | 
					 | 
				
			||||||
			echo 'Player or account of player <b>'.$nick.'</b> doesn\'t exist.';
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	else
 | 
					 | 
				
			||||||
		echo 'Invalid player name format. If you have other characters on account try with other name.';
 | 
					 | 
				
			||||||
	echo '<BR /><TABLE CELLSPACING=0 CELLPADDING=0 BORDER=0 WIDTH=100%><TR><TD><div style="text-align:center">
 | 
					 | 
				
			||||||
				<a href="' . getLink('account/lost') . '?action=step1&action_type=reckey&nick='.urlencode($nick).'" border="0"><IMG SRC="'.$template_path.'/images/global/buttons/sbutton_back.gif" NAME="Back" ALT="Back" BORDER=0 WIDTH=120 HEIGHT=18></a></div>
 | 
					 | 
				
			||||||
				</TD></TR></FORM></TABLE></TABLE>';
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
elseif($action == 'step3')
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	$rec_key = trim($_REQUEST['key']);
 | 
					 | 
				
			||||||
	$nick = stripslashes($_REQUEST['nick']);
 | 
					 | 
				
			||||||
	$new_pass = trim($_REQUEST['passor']);
 | 
					 | 
				
			||||||
	$new_email = trim($_REQUEST['email']);
 | 
					 | 
				
			||||||
	if(Validator::characterName($nick))
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		$player = new OTS_Player();
 | 
					 | 
				
			||||||
		$account = new OTS_Account();
 | 
					 | 
				
			||||||
		$player->find($nick);
 | 
					 | 
				
			||||||
		if($player->isLoaded())
 | 
					 | 
				
			||||||
			$account = $player->getAccount();
 | 
					 | 
				
			||||||
		if($account->isLoaded())
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			$account_key = $account->getCustomField('key');
 | 
					 | 
				
			||||||
			if(!empty($account_key))
 | 
					 | 
				
			||||||
			{
 | 
					 | 
				
			||||||
				if($account_key == $rec_key)
 | 
					 | 
				
			||||||
				{
 | 
					 | 
				
			||||||
					if(Validator::password($new_pass))
 | 
					 | 
				
			||||||
					{
 | 
					 | 
				
			||||||
						if(Validator::email($new_email))
 | 
					 | 
				
			||||||
						{
 | 
					 | 
				
			||||||
							$account->setEMail($new_email);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
							$tmp_new_pass = $new_pass;
 | 
					 | 
				
			||||||
							if(USE_ACCOUNT_SALT)
 | 
					 | 
				
			||||||
							{
 | 
					 | 
				
			||||||
								$salt = generateRandomString(10, false, true, true);
 | 
					 | 
				
			||||||
								$tmp_new_pass = $salt . $new_pass;
 | 
					 | 
				
			||||||
							}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
							$account->setPassword(encrypt($tmp_new_pass));
 | 
					 | 
				
			||||||
							$account->save();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
							if(USE_ACCOUNT_SALT)
 | 
					 | 
				
			||||||
								$account->setCustomField('salt', $salt);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
							echo 'Your account name, new password and new e-mail.<BR>
 | 
					 | 
				
			||||||
							<FORM ACTION="' . getLink('account/manage') . '" onsubmit="return validate_form(this)" METHOD=post>
 | 
					 | 
				
			||||||
							<INPUT TYPE=hidden NAME="character" VALUE="">
 | 
					 | 
				
			||||||
							<TABLE CELLSPACING=1 CELLPADDING=4 BORDER=0 WIDTH=100%>
 | 
					 | 
				
			||||||
							<TR><TD BGCOLOR="'.$config['vdarkborder'].'" class="white"><B>Your account name, new password and new e-mail</B></TD></TR>
 | 
					 | 
				
			||||||
							<TR><TD BGCOLOR="'.$config['darkborder'].'">
 | 
					 | 
				
			||||||
							Account name:     <b>'.$account->getName().'</b><BR>
 | 
					 | 
				
			||||||
							New password:        <b>'.$new_pass.'</b><BR>
 | 
					 | 
				
			||||||
							New e-mail address: <b>'.$new_email.'</b><BR>';
 | 
					 | 
				
			||||||
							if($account->getCustomField('email_next') < time())
 | 
					 | 
				
			||||||
							{
 | 
					 | 
				
			||||||
								$mailBody = '
 | 
					 | 
				
			||||||
								<h3>Your account name and new password!</h3>
 | 
					 | 
				
			||||||
								<p>Changed password and e-mail to your account in Lost Account Interface on server <a href="'.BASE_URL.'"><b>'.$config['lua']['serverName'].'</b></a></p>
 | 
					 | 
				
			||||||
								<p>Account name: <b>'.$account->getName().'</b></p>
 | 
					 | 
				
			||||||
								<p>New password: <b>'.$new_pass.'</b></p>
 | 
					 | 
				
			||||||
								<p>E-mail: <b>'.$new_email.'</b> (this e-mail)</p>
 | 
					 | 
				
			||||||
								<br />
 | 
					 | 
				
			||||||
								<p><u>It\'s automatic e-mail from OTS Lost Account System. Do not reply!</u></p>';
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
								if(_mail($account->getCustomField('email'), $config['lua']['serverName']." - New password to your account", $mailBody))
 | 
					 | 
				
			||||||
								{
 | 
					 | 
				
			||||||
									echo '<br /><small>Sent e-mail with your account name and password to new e-mail. You should receive this e-mail in 15 minutes. You can login now with new password!</small>';
 | 
					 | 
				
			||||||
								}
 | 
					 | 
				
			||||||
								else
 | 
					 | 
				
			||||||
								{
 | 
					 | 
				
			||||||
									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
 | 
					 | 
				
			||||||
							{
 | 
					 | 
				
			||||||
								echo '<br /><small>You will not receive e-mail with this informations.</small>';
 | 
					 | 
				
			||||||
							}
 | 
					 | 
				
			||||||
							echo '<INPUT TYPE=hidden NAME="account_login" VALUE="'.$account->getId().'">
 | 
					 | 
				
			||||||
							<INPUT TYPE=hidden NAME="password_login" VALUE="'.$new_pass.'">
 | 
					 | 
				
			||||||
							</TD></TR></TABLE><BR>
 | 
					 | 
				
			||||||
							<TABLE CELLSPACING=0 CELLPADDING=0 BORDER=0 WIDTH=100%><TR><TD><div style="text-align:center">
 | 
					 | 
				
			||||||
							<INPUT TYPE=image NAME="Login" ALT="Login" SRC="'.$template_path.'/images/global/buttons/sbutton_login.gif" BORDER=0 WIDTH=120 HEIGHT=18></div>
 | 
					 | 
				
			||||||
							</TD></TR></FORM></TABLE></TABLE>';
 | 
					 | 
				
			||||||
						}
 | 
					 | 
				
			||||||
						else
 | 
					 | 
				
			||||||
							echo Validator::getLastError();
 | 
					 | 
				
			||||||
					}
 | 
					 | 
				
			||||||
					else
 | 
					 | 
				
			||||||
						echo Validator::getLastError();
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				else
 | 
					 | 
				
			||||||
					echo 'Wrong recovery key!';
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			else
 | 
					 | 
				
			||||||
				echo 'Account of this character has no recovery key!';
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		else
 | 
					 | 
				
			||||||
			echo 'Player or account of player <b>'.$nick.'</b> doesn\'t exist.';
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	else
 | 
					 | 
				
			||||||
		echo 'Invalid player name format. If you have other characters on account try with other name.';
 | 
					 | 
				
			||||||
	echo '<BR /><TABLE CELLSPACING=0 CELLPADDING=0 BORDER=0 WIDTH=100%><TR><TD><div style="text-align:center">
 | 
					 | 
				
			||||||
				<a href="' . getLink('account/lost') . '?action=step1&action_type=reckey&nick='.urlencode($nick).'" border="0"><IMG SRC="'.$template_path.'/images/global/buttons/sbutton_back.gif" NAME="Back" ALT="Back" BORDER=0 WIDTH=120 HEIGHT=18></a></div>
 | 
					 | 
				
			||||||
				</TD></TR></FORM></TABLE></TABLE>';
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
elseif($action == 'checkcode')
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	$code = trim($_REQUEST['code']);
 | 
					 | 
				
			||||||
	$character = stripslashes(trim($_REQUEST['character']));
 | 
					 | 
				
			||||||
	if(empty($code) || empty($character))
 | 
					 | 
				
			||||||
		echo 'Please enter code from e-mail and name of one character from account. Then press Submit.<BR>
 | 
					 | 
				
			||||||
				<FORM ACTION="' . getLink('account/lost') . '?action=checkcode" METHOD=post>
 | 
					 | 
				
			||||||
				<TABLE CELLSPACING=1 CELLPADDING=4 BORDER=0 WIDTH=100%>
 | 
					 | 
				
			||||||
				<TR><TD BGCOLOR="'.$config['vdarkborder'].'" class="white"><B>Code & character name</B></TD></TR>
 | 
					 | 
				
			||||||
				<TR><TD BGCOLOR="'.$config['darkborder'].'">
 | 
					 | 
				
			||||||
				Your code: <INPUT TYPE=text NAME="code" VALUE="" SIZE="40")><BR />
 | 
					 | 
				
			||||||
				Character: <INPUT TYPE=text NAME="character" VALUE="" SIZE="40")><BR />
 | 
					 | 
				
			||||||
				</TD></TR>
 | 
					 | 
				
			||||||
				</TABLE>
 | 
					 | 
				
			||||||
				<BR>
 | 
					 | 
				
			||||||
				<TABLE CELLSPACING=0 CELLPADDING=0 BORDER=0 WIDTH=100%><TR><TD><div style="text-align:center">
 | 
					 | 
				
			||||||
				' . $twig->render('buttons.submit.html.twig') . '</div>
 | 
					 | 
				
			||||||
				</TD></TR></FORM></TABLE></TABLE>';
 | 
					 | 
				
			||||||
	else
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		$player = new OTS_Player();
 | 
					 | 
				
			||||||
		$account = new OTS_Account();
 | 
					 | 
				
			||||||
		$player->find($character);
 | 
					 | 
				
			||||||
		if($player->isLoaded())
 | 
					 | 
				
			||||||
			$account = $player->getAccount();
 | 
					 | 
				
			||||||
		if($account->isLoaded())
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			if($account->getCustomField('email_code') == $code)
 | 
					 | 
				
			||||||
			{
 | 
					 | 
				
			||||||
				echo '<script type="text/javascript">
 | 
					 | 
				
			||||||
				function validate_required(field,alerttxt)
 | 
					 | 
				
			||||||
				{
 | 
					 | 
				
			||||||
				with (field)
 | 
					 | 
				
			||||||
				{
 | 
					 | 
				
			||||||
				if (value==null||value==""||value==" ")
 | 
					 | 
				
			||||||
				  {alert(alerttxt);return false;}
 | 
					 | 
				
			||||||
				else {return true}
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				function validate_form(thisform)
 | 
					 | 
				
			||||||
				{
 | 
					 | 
				
			||||||
				with (thisform)
 | 
					 | 
				
			||||||
				{
 | 
					 | 
				
			||||||
				if (validate_required(passor,"Please enter password!")==false)
 | 
					 | 
				
			||||||
				  {passor.focus();return false;}
 | 
					 | 
				
			||||||
				if (validate_required(passor2,"Please repeat password!")==false)
 | 
					 | 
				
			||||||
				  {passor2.focus();return false;}
 | 
					 | 
				
			||||||
				if (passor2.value!=passor.value)
 | 
					 | 
				
			||||||
				  {alert(\'Repeated password is not equal to password!\');return false;}
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				</script>
 | 
					 | 
				
			||||||
				Please enter new password to your account and repeat to make sure you remember password.<BR>
 | 
					 | 
				
			||||||
				<FORM ACTION="' . getLink('account/lost') . '?action=setnewpassword" onsubmit="return validate_form(this)" METHOD=post>
 | 
					 | 
				
			||||||
				<INPUT TYPE=hidden NAME="character" VALUE="'.$character.'">
 | 
					 | 
				
			||||||
				<INPUT TYPE=hidden NAME="code" VALUE="'.$code.'">
 | 
					 | 
				
			||||||
				<TABLE CELLSPACING=1 CELLPADDING=4 BORDER=0 WIDTH=100%>
 | 
					 | 
				
			||||||
				<TR><TD BGCOLOR="'.$config['vdarkborder'].'" class="white"><B>Code & account name</B></TD></TR>
 | 
					 | 
				
			||||||
				<TR><TD BGCOLOR="'.$config['darkborder'].'">
 | 
					 | 
				
			||||||
				New password:      <INPUT TYPE=password ID="passor" NAME="passor" VALUE="" SIZE="40")><BR />
 | 
					 | 
				
			||||||
				Repeat new password: <INPUT TYPE=password ID="passor2" NAME="passor2" VALUE="" SIZE="40")><BR />
 | 
					 | 
				
			||||||
				</TD></TR>
 | 
					 | 
				
			||||||
				</TABLE>
 | 
					 | 
				
			||||||
				<BR>
 | 
					 | 
				
			||||||
				<TABLE CELLSPACING=0 CELLPADDING=0 BORDER=0 WIDTH=100%><TR><TD><div style="text-align:center">
 | 
					 | 
				
			||||||
				' . $twig->render('buttons.submit.html.twig') . '</div>
 | 
					 | 
				
			||||||
				</TD></TR></FORM></TABLE></TABLE>';
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			else
 | 
					 | 
				
			||||||
				$error= 'Wrong code to change password.';
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		else
 | 
					 | 
				
			||||||
			$error = 'Account of this character or this character doesn\'t exist.';
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if(!empty($error))
 | 
					 | 
				
			||||||
				echo '<span style="color: red"><b>'.$error.'</b></span><br />Please enter code from e-mail and name of one character from account. Then press Submit.<BR>
 | 
					 | 
				
			||||||
				<FORM ACTION="' . getLink('account/lost') . '?action=checkcode" METHOD=post>
 | 
					 | 
				
			||||||
				<TABLE CELLSPACING=1 CELLPADDING=4 BORDER=0 WIDTH=100%>
 | 
					 | 
				
			||||||
				<TR><TD BGCOLOR="'.$config['vdarkborder'].'" class="white"><B>Code & character name</B></TD></TR>
 | 
					 | 
				
			||||||
				<TR><TD BGCOLOR="'.$config['darkborder'].'">
 | 
					 | 
				
			||||||
				Your code: <INPUT TYPE=text NAME="code" VALUE="" SIZE="40")><BR />
 | 
					 | 
				
			||||||
				Character: <INPUT TYPE=text NAME="character" VALUE="" SIZE="40")><BR />
 | 
					 | 
				
			||||||
				</TD></TR>
 | 
					 | 
				
			||||||
				</TABLE>
 | 
					 | 
				
			||||||
				<BR>
 | 
					 | 
				
			||||||
				<TABLE CELLSPACING=0 CELLPADDING=0 BORDER=0 WIDTH=100%><TR><TD><div style="text-align:center">
 | 
					 | 
				
			||||||
				' . $twig->render('buttons.submit.html.twig') . '</div>
 | 
					 | 
				
			||||||
				</TD></TR></FORM></TABLE></TABLE>';
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
elseif($action == 'setnewpassword')
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	$newpassword = $_REQUEST['passor'];
 | 
					 | 
				
			||||||
	$code = $_REQUEST['code'];
 | 
					 | 
				
			||||||
	$character = stripslashes($_REQUEST['character']);
 | 
					 | 
				
			||||||
	echo '';
 | 
					 | 
				
			||||||
	if(empty($code) || empty($character) || empty($newpassword))
 | 
					 | 
				
			||||||
		echo '<span style="color: red"><b>Error. Try again.</b></span><br />Please enter code from e-mail and name of one character from account. Then press Submit.<BR>
 | 
					 | 
				
			||||||
				<BR><FORM ACTION="' . getLink('account/lost') . '?action=checkcode" METHOD=post>
 | 
					 | 
				
			||||||
				<TABLE CELLSPACING=0 CELLPADDING=0 BORDER=0 WIDTH=100%><TR><TD><div style="text-align:center">
 | 
					 | 
				
			||||||
				<INPUT TYPE=image NAME="Back" ALT="Back" SRC="'.$template_path.'/images/global/buttons/sbutton_back.gif" BORDER=0 WIDTH=120 HEIGHT=18></div>
 | 
					 | 
				
			||||||
				</TD></TR></FORM></TABLE></TABLE>';
 | 
					 | 
				
			||||||
	else
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		$player = new OTS_Player();
 | 
					 | 
				
			||||||
		$account = new OTS_Account();
 | 
					 | 
				
			||||||
		$player->find($character);
 | 
					 | 
				
			||||||
		if($player->isLoaded())
 | 
					 | 
				
			||||||
			$account = $player->getAccount();
 | 
					 | 
				
			||||||
		if($account->isLoaded())
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			if($account->getCustomField('email_code') == $code)
 | 
					 | 
				
			||||||
			{
 | 
					 | 
				
			||||||
				if(Validator::password($newpassword))
 | 
					 | 
				
			||||||
				{
 | 
					 | 
				
			||||||
					$tmp_new_pass = $newpassword;
 | 
					 | 
				
			||||||
					if(USE_ACCOUNT_SALT)
 | 
					 | 
				
			||||||
					{
 | 
					 | 
				
			||||||
						$salt = generateRandomString(10, false, true, true);
 | 
					 | 
				
			||||||
						$tmp_new_pass  = $salt . $newpassword;
 | 
					 | 
				
			||||||
						$account->setCustomField('salt', $salt);
 | 
					 | 
				
			||||||
					}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
					$account->setPassword(encrypt($tmp_new_pass ));
 | 
					 | 
				
			||||||
					$account->save();
 | 
					 | 
				
			||||||
					$account->setCustomField('email_code', '');
 | 
					 | 
				
			||||||
					echo 'New password to your account is below. Now you can login.<BR>
 | 
					 | 
				
			||||||
					<INPUT TYPE=hidden NAME="character" VALUE="'.$character.'">
 | 
					 | 
				
			||||||
					<TABLE CELLSPACING=1 CELLPADDING=4 BORDER=0 WIDTH=100%>
 | 
					 | 
				
			||||||
					<TR><TD BGCOLOR="'.$config['vdarkborder'].'" class="white"><B>Changed password</B></TD></TR>
 | 
					 | 
				
			||||||
					<TR><TD BGCOLOR="'.$config['darkborder'].'">
 | 
					 | 
				
			||||||
					New password: <b>'.$newpassword.'</b><BR />
 | 
					 | 
				
			||||||
					Account name:   <i>(Already on your e-mail)</i><BR />';
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
					$mailBody = '
 | 
					 | 
				
			||||||
					<h3>Your account name and password!</h3>
 | 
					 | 
				
			||||||
					<p>Changed password to your account in Lost Account Interface on server <a href="'.BASE_URL.'"><b>'.$config['lua']['serverName'].'</b></a></p>
 | 
					 | 
				
			||||||
					<p>Account name: <b>'.$account->getName().'</b></p>
 | 
					 | 
				
			||||||
					<p>New password: <b>'.$newpassword.'</b></p>
 | 
					 | 
				
			||||||
					<br />
 | 
					 | 
				
			||||||
					<p><u>It\'s automatic e-mail from OTS Lost Account System. Do not reply!</u></p>';
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
					if(_mail($account->getCustomField('email'), $config['lua']['serverName']." - Your new password", $mailBody))
 | 
					 | 
				
			||||||
					{
 | 
					 | 
				
			||||||
						echo '<br /><small>New password work! Sent e-mail with your password and account name. You should receive this e-mail in 15 minutes. You can login now with new password!';
 | 
					 | 
				
			||||||
					}
 | 
					 | 
				
			||||||
					else
 | 
					 | 
				
			||||||
					{
 | 
					 | 
				
			||||||
						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>
 | 
					 | 
				
			||||||
				<BR>
 | 
					 | 
				
			||||||
				<TABLE CELLSPACING=0 CELLPADDING=0 BORDER=0 WIDTH=100%><TR><TD><div style="text-align:center">
 | 
					 | 
				
			||||||
				<FORM ACTION="' . getLink('account/manage') . '" METHOD=post>
 | 
					 | 
				
			||||||
				<INPUT TYPE=image NAME="Login" ALT="Login" SRC="'.$template_path.'/images/global/buttons/sbutton_login.gif" BORDER=0 WIDTH=120 HEIGHT=18></div>
 | 
					 | 
				
			||||||
				</TD></TR></FORM></TABLE></TABLE>';
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				else
 | 
					 | 
				
			||||||
					$error= Validator::getLastError();
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			else
 | 
					 | 
				
			||||||
				$error= 'Wrong code to change password.';
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		else
 | 
					 | 
				
			||||||
			$error = 'Account of this character or this character doesn\'t exist.';
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if(!empty($error))
 | 
					 | 
				
			||||||
				echo '<span style="color: red"><b>'.$error.'</b></span><br />Please enter code from e-mail and name of one character from account. Then press Submit.<BR>
 | 
					 | 
				
			||||||
				<FORM ACTION="' . getLink('account/lost') . '?action=checkcode" METHOD=post>
 | 
					 | 
				
			||||||
				<TABLE CELLSPACING=1 CELLPADDING=4 BORDER=0 WIDTH=100%>
 | 
					 | 
				
			||||||
				<TR><TD BGCOLOR="'.$config['vdarkborder'].'" class="white"><B>Code & character name</B></TD></TR>
 | 
					 | 
				
			||||||
				<TR><TD BGCOLOR="'.$config['darkborder'].'">
 | 
					 | 
				
			||||||
				Your code: <INPUT TYPE=text NAME="code" VALUE="" SIZE="40")><BR />
 | 
					 | 
				
			||||||
				Character: <INPUT TYPE=text NAME="character" VALUE="" SIZE="40")><BR />
 | 
					 | 
				
			||||||
				</TD></TR>
 | 
					 | 
				
			||||||
				</TABLE>
 | 
					 | 
				
			||||||
				<BR>
 | 
					 | 
				
			||||||
				<TABLE CELLSPACING=0 CELLPADDING=0 BORDER=0 WIDTH=100%><TR><TD><div style="text-align:center">
 | 
					 | 
				
			||||||
				' . $twig->render('buttons.submit.html.twig') . '</div>
 | 
					 | 
				
			||||||
				</TD></TR></FORM></TABLE></TABLE>';
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										18
									
								
								system/pages/account/lost/base.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								system/pages/account/lost/base.php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,18 @@
 | 
				
			|||||||
 | 
					<?php
 | 
				
			||||||
 | 
					defined('MYAAC') or die('Direct access not allowed!');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function lostAccountWriteCooldown(string $nick, int $time): void
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						global $twig;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						$inSec = $time - time();
 | 
				
			||||||
 | 
						$minutesLeft = floor($inSec / 60);
 | 
				
			||||||
 | 
						$secondsLeft = $inSec - ($minutesLeft * 60);
 | 
				
			||||||
 | 
						$timeLeft = "$minutesLeft minutes $secondsLeft seconds";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						$timeRounded = ceil(setting('core.mail_lost_account_interval') / 60);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						$twig->display('error_box.html.twig', [
 | 
				
			||||||
 | 
							'errors' => ["Account of selected character (<b>" . escapeHtml($nick) . "</b>) received e-mail in last $timeRounded minutes. You must wait $timeLeft before you can use Lost Account Interface again."]
 | 
				
			||||||
 | 
						]);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										51
									
								
								system/pages/account/lost/check-code.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								system/pages/account/lost/check-code.php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,51 @@
 | 
				
			|||||||
 | 
					<?php
 | 
				
			||||||
 | 
					defined('MYAAC') or die('Direct access not allowed!');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					csrfProtect();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					$title = 'Lost Account';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					$code = $_POST['code'] ?? '';
 | 
				
			||||||
 | 
					$character = $_POST['character'] ?? '';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if(empty($code) || empty($character)) {
 | 
				
			||||||
 | 
						$twig->display('account/lost/check-code.html.twig', [
 | 
				
			||||||
 | 
							'code' => $code,
 | 
				
			||||||
 | 
							'characters' => $character,
 | 
				
			||||||
 | 
						]);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					else {
 | 
				
			||||||
 | 
						$player = new OTS_Player();
 | 
				
			||||||
 | 
						$account = new OTS_Account();
 | 
				
			||||||
 | 
						$player->find($character);
 | 
				
			||||||
 | 
						if($player->isLoaded()) {
 | 
				
			||||||
 | 
							$account = $player->getAccount();
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if($account->isLoaded()) {
 | 
				
			||||||
 | 
							if($account->getCustomField('email_code') == $code) {
 | 
				
			||||||
 | 
								$twig->display('account/lost/check-code.finish.html.twig', [
 | 
				
			||||||
 | 
									'character' => $character,
 | 
				
			||||||
 | 
									'code' => $code,
 | 
				
			||||||
 | 
								]);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							else {
 | 
				
			||||||
 | 
								$error = 'Wrong code to change password.';
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						else {
 | 
				
			||||||
 | 
							$error = "Account of this character or this character doesn't exist.";
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if(!empty($error)) {
 | 
				
			||||||
 | 
						$twig->display('error_box.html.twig', [
 | 
				
			||||||
 | 
							'errors' => [$error],
 | 
				
			||||||
 | 
						]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						echo '<br/>';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						$twig->display('account/lost/check-code.html.twig', [
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						]);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										68
									
								
								system/pages/account/lost/email/send-code.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										68
									
								
								system/pages/account/lost/email/send-code.php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,68 @@
 | 
				
			|||||||
 | 
					<?php
 | 
				
			||||||
 | 
					defined('MYAAC') or die('Direct access not allowed!');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					csrfProtect();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					require __DIR__ . '/../base.php';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					$title = 'Lost Account';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					$email = $_POST['email'] ?? '';
 | 
				
			||||||
 | 
					$nick = $_POST['nick'] ?? '';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					$player = new OTS_Player();
 | 
				
			||||||
 | 
					$account = new OTS_Account();
 | 
				
			||||||
 | 
					$player->find($nick);
 | 
				
			||||||
 | 
					if($player->isLoaded()) {
 | 
				
			||||||
 | 
						$account = $player->getAccount();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if($account->isLoaded()) {
 | 
				
			||||||
 | 
						if($account->getCustomField('email_next') < time()) {
 | 
				
			||||||
 | 
							if($account->getEMail() == $email) {
 | 
				
			||||||
 | 
								$newCode = generateRandomString(30, true, false, true);
 | 
				
			||||||
 | 
								$mailBody = $twig->render('mail.account.lost.code.html.twig', [
 | 
				
			||||||
 | 
									'newCode' => $newCode,
 | 
				
			||||||
 | 
									'account' => $account,
 | 
				
			||||||
 | 
									'nick' => $nick,
 | 
				
			||||||
 | 
								]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								$accountEMail = $account->getCustomField('email');
 | 
				
			||||||
 | 
								if(_mail($accountEMail, configLua('serverName') . ' - Recover your account', $mailBody)) {
 | 
				
			||||||
 | 
									$account->setCustomField('email_code', $newCode);
 | 
				
			||||||
 | 
									$account->setCustomField('email_next', (time() + setting('core.mail_lost_account_interval')));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									$twig->display('success.html.twig', [
 | 
				
			||||||
 | 
										'title' => 'Email has been sent',
 | 
				
			||||||
 | 
										'description' => 'Details about steps required to recover your account has been sent to <b>' . $accountEMail . '</b>. You should receive this email within 15 minutes. Please check your inbox/spam directory.',
 | 
				
			||||||
 | 
										'custom_buttons' => '',
 | 
				
			||||||
 | 
									]);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								else {
 | 
				
			||||||
 | 
									$account->setCustomField('email_next', (time() + 60));
 | 
				
			||||||
 | 
									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 {
 | 
				
			||||||
 | 
								$errors[] = 'Invalid e-mail to account of character <b>' . escapeHtml($nick) . '</b>. Try again.';
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						else {
 | 
				
			||||||
 | 
							lostAccountWriteCooldown($nick, (int)$account->getCustomField('email_next'));
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					else {
 | 
				
			||||||
 | 
						$errors[] =  "Player or account of player <b>" . escapeHtml($nick) . "</b> doesn't exist.";
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if (!empty($errors)) {
 | 
				
			||||||
 | 
						$twig->display('error_box.html.twig', [
 | 
				
			||||||
 | 
							'errors' => $errors,
 | 
				
			||||||
 | 
						]);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					$twig->display('account.back_button.html.twig', [
 | 
				
			||||||
 | 
						'new_line' => true,
 | 
				
			||||||
 | 
						'center' => true,
 | 
				
			||||||
 | 
						'action' => getLink('account/lost/step-1') . '?action=email&nick=' . urlencode($nick),
 | 
				
			||||||
 | 
					]);
 | 
				
			||||||
							
								
								
									
										94
									
								
								system/pages/account/lost/email/set-new-password.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										94
									
								
								system/pages/account/lost/email/set-new-password.php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,94 @@
 | 
				
			|||||||
 | 
					<?php
 | 
				
			||||||
 | 
					defined('MYAAC') or die('Direct access not allowed!');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					csrfProtect();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					$title = 'Lost Account';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					$newPassword = $_POST['password'] ?? '';
 | 
				
			||||||
 | 
					$passwordRepeat = $_POST['password_repeat'] ?? '';
 | 
				
			||||||
 | 
					$code = $_POST['code'] ?? '';
 | 
				
			||||||
 | 
					$character = $_POST['character'] ?? '';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if(empty($code) || empty($character) || empty($newPassword) || empty($passwordRepeat)) {
 | 
				
			||||||
 | 
						$errors[] = 'Please enter code from e-mail and name of one character from account. Then press Submit.';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						$twig->display('error_box.html.twig', [
 | 
				
			||||||
 | 
							'errors' => $errors,
 | 
				
			||||||
 | 
						]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						$twig->display('account.back_button.html.twig', [
 | 
				
			||||||
 | 
							'new_line' => true,
 | 
				
			||||||
 | 
							'center' => true,
 | 
				
			||||||
 | 
							'action' => getLink('account/lost/check-code')
 | 
				
			||||||
 | 
						]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					$player = new OTS_Player();
 | 
				
			||||||
 | 
					$account = new OTS_Account();
 | 
				
			||||||
 | 
					$player->find($character);
 | 
				
			||||||
 | 
					if($player->isLoaded()) {
 | 
				
			||||||
 | 
						$account = $player->getAccount();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if($account->isLoaded()) {
 | 
				
			||||||
 | 
						if($account->getCustomField('email_code') == $code) {
 | 
				
			||||||
 | 
							if ($newPassword == $passwordRepeat) {
 | 
				
			||||||
 | 
								if (Validator::password($newPassword)) {
 | 
				
			||||||
 | 
									$tmp_new_pass = $newPassword;
 | 
				
			||||||
 | 
									if (USE_ACCOUNT_SALT) {
 | 
				
			||||||
 | 
										$salt = generateRandomString(10, false, true, true);
 | 
				
			||||||
 | 
										$tmp_new_pass = $salt . $newPassword;
 | 
				
			||||||
 | 
										$account->setCustomField('salt', $salt);
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									$account->setPassword(encrypt($tmp_new_pass));
 | 
				
			||||||
 | 
									$account->save();
 | 
				
			||||||
 | 
									$account->setCustomField('email_code', '');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									$mailBody = $twig->render('mail.account.lost.new-password.html.twig', [
 | 
				
			||||||
 | 
										'account' => $account,
 | 
				
			||||||
 | 
										'newPassword' => $newPassword,
 | 
				
			||||||
 | 
									]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									$statusMsg = '';
 | 
				
			||||||
 | 
									if (_mail($account->getCustomField('email'), configLua('serverName') . ' - Your new password', $mailBody)) {
 | 
				
			||||||
 | 
										$statusMsg = '<br /><small>New password work! Sent e-mail with your password and account name. You should receive this e-mail in 15 minutes. You can login now with new password!';
 | 
				
			||||||
 | 
									} else {
 | 
				
			||||||
 | 
										$statusMsg = '<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';
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									$twig->display('account/lost/finish.new-password.html.twig', [
 | 
				
			||||||
 | 
										'statusMsg' => $statusMsg,
 | 
				
			||||||
 | 
										'newPassword' => $newPassword,
 | 
				
			||||||
 | 
									]);
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									$error = Validator::getLastError();
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							else {
 | 
				
			||||||
 | 
								$error = 'Passwords are not the same!';
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						else {
 | 
				
			||||||
 | 
							$error = 'Wrong code to change password.';
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					else {
 | 
				
			||||||
 | 
						$error = "Account of this character or this character doesn't exist.";
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if(!empty($error)) {
 | 
				
			||||||
 | 
						$twig->display('error_box.html.twig', [
 | 
				
			||||||
 | 
							'errors' => [$error],
 | 
				
			||||||
 | 
						]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						echo '<br/>';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						$twig->display('account/lost/check-code.html.twig', [
 | 
				
			||||||
 | 
							'code' => $code,
 | 
				
			||||||
 | 
							'character' => $character,
 | 
				
			||||||
 | 
						]);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										36
									
								
								system/pages/account/lost/email/step-1.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								system/pages/account/lost/email/step-1.php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,36 @@
 | 
				
			|||||||
 | 
					<?php
 | 
				
			||||||
 | 
					defined('MYAAC') or die('Direct access not allowed!');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					require __DIR__ . '/../base.php';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					csrfProtect();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					$title = 'Lost Account';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					$nick = $_POST['nick'] ?? '';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if($account->isLoaded()) {
 | 
				
			||||||
 | 
						if($account->getCustomField('email_next') < time()) {
 | 
				
			||||||
 | 
							$twig->display('account/lost/email.html.twig', [
 | 
				
			||||||
 | 
								'nick' => $nick,
 | 
				
			||||||
 | 
							]);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						else {
 | 
				
			||||||
 | 
							lostAccountWriteCooldown($nick, (int)$account->getCustomField('email_next'));
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					else {
 | 
				
			||||||
 | 
						$errors[] = "Player or account of player <b>" . escapeHtml($nick) . "</b> doesn't exist.";
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if (!empty($errors)) {
 | 
				
			||||||
 | 
						$twig->display('error_box.html.twig', [
 | 
				
			||||||
 | 
							'errors' => $errors,
 | 
				
			||||||
 | 
						]);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					$twig->display('account.back_button.html.twig', [
 | 
				
			||||||
 | 
						'new_line' => true,
 | 
				
			||||||
 | 
						'center' => true,
 | 
				
			||||||
 | 
						'action' => getLink('account/lost'),
 | 
				
			||||||
 | 
					]);
 | 
				
			||||||
							
								
								
									
										36
									
								
								system/pages/account/lost/recovery-key/step-1.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								system/pages/account/lost/recovery-key/step-1.php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,36 @@
 | 
				
			|||||||
 | 
					<?php
 | 
				
			||||||
 | 
					defined('MYAAC') or die('Direct access not allowed!');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					csrfProtect();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					$title = 'Lost Account';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					$nick = $_POST['nick'] ?? '';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if($account->isLoaded()) {
 | 
				
			||||||
 | 
						$account_key = $account->getCustomField('key');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if(!empty($account_key)) {
 | 
				
			||||||
 | 
							$twig->display('account/lost/recovery-key.step-1.html.twig', [
 | 
				
			||||||
 | 
								'nick' => $nick,
 | 
				
			||||||
 | 
							]);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						else {
 | 
				
			||||||
 | 
							$errors[] = 'Account of this character has no recovery key!';
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					else {
 | 
				
			||||||
 | 
						$errors[] = "Player or account of player <b>" . escapeHtml($nick) . "</b> doesn't exist.";
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if (!empty($errors)) {
 | 
				
			||||||
 | 
						$twig->display('error_box.html.twig', [
 | 
				
			||||||
 | 
							'errors' => $errors,
 | 
				
			||||||
 | 
						]);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					$twig->display('account.back_button.html.twig', [
 | 
				
			||||||
 | 
						'new_line' => true,
 | 
				
			||||||
 | 
						'center' => true,
 | 
				
			||||||
 | 
						'action' => getLink('account/lost'),
 | 
				
			||||||
 | 
					]);
 | 
				
			||||||
							
								
								
									
										49
									
								
								system/pages/account/lost/recovery-key/step-2.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								system/pages/account/lost/recovery-key/step-2.php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,49 @@
 | 
				
			|||||||
 | 
					<?php
 | 
				
			||||||
 | 
					defined('MYAAC') or die('Direct access not allowed!');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					csrfProtect();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					$title = 'Lost Account';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					$key = $_REQUEST['key'] ?? '';
 | 
				
			||||||
 | 
					$nick = $_POST['nick'] ?? '';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					$player = new OTS_Player();
 | 
				
			||||||
 | 
					$account = new OTS_Account();
 | 
				
			||||||
 | 
					$player->find($nick);
 | 
				
			||||||
 | 
					if($player->isLoaded()) {
 | 
				
			||||||
 | 
						$account = $player->getAccount();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if($account->isLoaded()) {
 | 
				
			||||||
 | 
						$accountKey = $account->getCustomField('key');
 | 
				
			||||||
 | 
						if(!empty($accountKey)) {
 | 
				
			||||||
 | 
							if($accountKey == $key) {
 | 
				
			||||||
 | 
								$twig->display('account/lost/recovery-key.step-2.html.twig', [
 | 
				
			||||||
 | 
									'nick' => $nick,
 | 
				
			||||||
 | 
									'key' => $key,
 | 
				
			||||||
 | 
								]);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							else {
 | 
				
			||||||
 | 
								$errors[] = 'Wrong recovery key!';
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						else {
 | 
				
			||||||
 | 
							$errors[] = 'Account of this character has no recovery key!';
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					else {
 | 
				
			||||||
 | 
						$errors[] = "Player or account of player <b>" . escapeHtml($nick) . "</b> doesn't exist.";
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if (!empty($errors)) {
 | 
				
			||||||
 | 
						$twig->display('error_box.html.twig', [
 | 
				
			||||||
 | 
							'errors' => $errors,
 | 
				
			||||||
 | 
						]);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					$twig->display('account.back_button.html.twig', [
 | 
				
			||||||
 | 
						'new_line' => true,
 | 
				
			||||||
 | 
						'center' => true,
 | 
				
			||||||
 | 
						'action' => getLink('account/lost/step-1') . '?action=recovery-key&nick=' . urlencode($nick),
 | 
				
			||||||
 | 
					]);
 | 
				
			||||||
							
								
								
									
										101
									
								
								system/pages/account/lost/recovery-key/step-3.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										101
									
								
								system/pages/account/lost/recovery-key/step-3.php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,101 @@
 | 
				
			|||||||
 | 
					<?php
 | 
				
			||||||
 | 
					defined('MYAAC') or die('Direct access not allowed!');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					csrfProtect();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					$title = 'Lost Account';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					$key = $_POST['key'];
 | 
				
			||||||
 | 
					$nick = $_POST['nick'] ?? '';
 | 
				
			||||||
 | 
					$newPassword = $_POST['password'] ?? '';
 | 
				
			||||||
 | 
					$passwordRepeat = $_POST['password_repeat'] ?? '';
 | 
				
			||||||
 | 
					$newEmail = $_POST['email'] ?? '';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					$player = new OTS_Player();
 | 
				
			||||||
 | 
					$account = new OTS_Account();
 | 
				
			||||||
 | 
					$player->find($nick);
 | 
				
			||||||
 | 
					if($player->isLoaded()) {
 | 
				
			||||||
 | 
						$account = $player->getAccount();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if($account->isLoaded()) {
 | 
				
			||||||
 | 
						$accountKey = $account->getCustomField('key');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if(!empty($accountKey)) {
 | 
				
			||||||
 | 
							if($accountKey == $key) {
 | 
				
			||||||
 | 
								if(Validator::password($newPassword)) {
 | 
				
			||||||
 | 
									if ($newPassword == $passwordRepeat) {
 | 
				
			||||||
 | 
										if (Validator::email($newEmail)) {
 | 
				
			||||||
 | 
											$account->setEMail($newEmail);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
											$tmp_new_pass = $newPassword;
 | 
				
			||||||
 | 
											if (USE_ACCOUNT_SALT) {
 | 
				
			||||||
 | 
												$salt = generateRandomString(10, false, true, true);
 | 
				
			||||||
 | 
												$tmp_new_pass = $salt . $newPassword;
 | 
				
			||||||
 | 
											}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
											$account->setPassword(encrypt($tmp_new_pass));
 | 
				
			||||||
 | 
											$account->save();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
											if (USE_ACCOUNT_SALT) {
 | 
				
			||||||
 | 
												$account->setCustomField('salt', $salt);
 | 
				
			||||||
 | 
											}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
											$statusMsg = '';
 | 
				
			||||||
 | 
											if ($account->getCustomField('email_next') < time()) {
 | 
				
			||||||
 | 
												$mailBody = $twig->render('mail.account.lost.new-email.html.twig', [
 | 
				
			||||||
 | 
													'account' => $account,
 | 
				
			||||||
 | 
													'newPassword' => $newPassword,
 | 
				
			||||||
 | 
													'newEmail' => $newEmail,
 | 
				
			||||||
 | 
												]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
												if (_mail($account->getCustomField('email'), configLua('serverName') . ' - New password to your account', $mailBody)) {
 | 
				
			||||||
 | 
													$statusMsg = '<br /><small>Sent e-mail with your account name and password to new e-mail. You should receive this e-mail in 15 minutes. You can login now with new password!</small>';
 | 
				
			||||||
 | 
												} else {
 | 
				
			||||||
 | 
													$statusMsg = '<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 {
 | 
				
			||||||
 | 
												$statusMsg = '<br /><small>You will not receive e-mail with this informations.</small>';
 | 
				
			||||||
 | 
											}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
											$twig->display('account/lost/finish.new-email.html.twig', [
 | 
				
			||||||
 | 
												'statusMsg' => $statusMsg,
 | 
				
			||||||
 | 
												'account' => $account,
 | 
				
			||||||
 | 
												'newPassword' => $newPassword,
 | 
				
			||||||
 | 
												'newEmail' => $newEmail,
 | 
				
			||||||
 | 
											]);
 | 
				
			||||||
 | 
										} else {
 | 
				
			||||||
 | 
											$errors[] = Validator::getLastError();
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									else {
 | 
				
			||||||
 | 
										$errors[] = 'Passwords are not the same!';
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								else {
 | 
				
			||||||
 | 
									$errors[] = Validator::getLastError();
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							else {
 | 
				
			||||||
 | 
								$errors[] = 'Wrong recovery key!';
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						else {
 | 
				
			||||||
 | 
							$errors[] = 'Account of this character has no recovery key!';
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					else {
 | 
				
			||||||
 | 
						$errors[] = "Player or account of player <b>" . escapeHtml($nick) . "</b> doesn't exist.";
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if (!empty($errors)) {
 | 
				
			||||||
 | 
						$twig->display('error_box.html.twig', [
 | 
				
			||||||
 | 
							'errors' => $errors,
 | 
				
			||||||
 | 
						]);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					$twig->display('account.back_button.html.twig', [
 | 
				
			||||||
 | 
						'new_line' => true,
 | 
				
			||||||
 | 
						'center' => true,
 | 
				
			||||||
 | 
						'action' => getLink('account/lost/step-1') . '?action=recovery-key&nick=' . urlencode($nick),
 | 
				
			||||||
 | 
					]);
 | 
				
			||||||
							
								
								
									
										26
									
								
								system/pages/account/lost/step-1.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								system/pages/account/lost/step-1.php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,26 @@
 | 
				
			|||||||
 | 
					<?php
 | 
				
			||||||
 | 
					defined('MYAAC') or die('Direct access not allowed!');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					csrfProtect();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					$title = 'Lost Account';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					$nick = $_REQUEST['nick'] ?? '';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					$player = new OTS_Player();
 | 
				
			||||||
 | 
					$account = new OTS_Account();
 | 
				
			||||||
 | 
					$player->find($nick);
 | 
				
			||||||
 | 
					if($player->isLoaded()) {
 | 
				
			||||||
 | 
						$account = $player->getAccount();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if (ACTION == 'email') {
 | 
				
			||||||
 | 
						require __DIR__ . '/email/step-1.php';
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					else if (ACTION == 'recovery-key') {
 | 
				
			||||||
 | 
						require __DIR__ . '/recovery-key/step-1.php';
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					else {
 | 
				
			||||||
 | 
						$twig->display('account/lost/no-action.html.twig');
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -38,15 +38,24 @@ csrfProtect();
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
$groups = new OTS_Groups_List();
 | 
					$groups = new OTS_Groups_List();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
$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
 | 
					 * @var OTS_Account $account_logged
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
if(!$account_logged->isPremium())
 | 
					$premDays = $account_logged->getPremDays();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					$freePremium = isset($config['lua']['freePremium']) && getBoolean($config['lua']['freePremium']) || $premDays == OTS_Account::GRATIS_PREMIUM_DAYS;
 | 
				
			||||||
 | 
					$dayOrDays = ($premDays == 1 ? 'day' : 'days');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					$vipSystemEnabled = isset($config['lua']['vipSystemEnabled']) && getBoolean($config['lua']['vipSystemEnabled']);
 | 
				
			||||||
 | 
					$premiumLabel = $vipSystemEnabled ? 'VIP' : 'Premium Account';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if ($freePremium && !$vipSystemEnabled) {
 | 
				
			||||||
 | 
						$account_status = '<b><span style="color: green">Gratis Premium Account</span></b>';
 | 
				
			||||||
 | 
					} else if(!$account_logged->isPremium()) {
 | 
				
			||||||
	$account_status = '<b><span style="color: red">Free Account</span></b>';
 | 
						$account_status = '<b><span style="color: red">Free Account</span></b>';
 | 
				
			||||||
else
 | 
					} else {
 | 
				
			||||||
	$account_status = '<b><span style="color: green">' . ($freePremium ? 'Gratis Premium Account' : 'Premium Account, ' . $account_logged->getPremDays() . ' '.$dayOrDays.' left') . '</span></b>';
 | 
						$account_status = '<b><span style="color: green">' . $premiumLabel . ', ' . $premDays . ' '.$dayOrDays.' left</span></b>';
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
$recovery_key = $account_logged->getCustomField('key');
 | 
					$recovery_key = $account_logged->getCustomField('key');
 | 
				
			||||||
if(empty($recovery_key))
 | 
					if(empty($recovery_key))
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,23 +0,0 @@
 | 
				
			|||||||
<?php
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * Change comment
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * @package   MyAAC
 | 
					 | 
				
			||||||
 * @author    Gesior <jerzyskalski@wp.pl>
 | 
					 | 
				
			||||||
 * @author    Slawkens <slawkens@gmail.com>
 | 
					 | 
				
			||||||
 * @copyright 2019 MyAAC
 | 
					 | 
				
			||||||
 * @link      https://my-aac.org
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
defined('MYAAC') or die('Direct access not allowed!');
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
$redirect = urldecode($_REQUEST['redirect']);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// should never happen, unless hacker modify the URL
 | 
					 | 
				
			||||||
if (!str_contains($redirect, BASE_URL)) {
 | 
					 | 
				
			||||||
	error('Fatal error: Cannot redirect outside the website.');
 | 
					 | 
				
			||||||
	return;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
$twig->display('account.redirect.html.twig', array(
 | 
					 | 
				
			||||||
	'redirect' => $redirect
 | 
					 | 
				
			||||||
));
 | 
					 | 
				
			||||||
							
								
								
									
										94
									
								
								system/pages/account/resend-email-verify.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										94
									
								
								system/pages/account/resend-email-verify.php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,94 @@
 | 
				
			|||||||
 | 
					<?php
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use MyAAC\Models\AccountEmailVerify;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					defined('MYAAC') or die('Direct access not allowed!');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					$title = 'Resend Email';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					$errorWithBackButton = function ($msg) use ($twig) {
 | 
				
			||||||
 | 
						$errors = [$msg];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						$twig->display('error_box.html.twig', ['errors' => $errors]);
 | 
				
			||||||
 | 
						$twig->display('account.back_button.html.twig', [
 | 
				
			||||||
 | 
							'action' => getLink('account/resend-email-verify'),
 | 
				
			||||||
 | 
						]);
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if (!setting('core.mail_enabled') || !setting('core.account_mail_verify')) {
 | 
				
			||||||
 | 
						$errorWithBackButton('Resending email is not possible on this server.');
 | 
				
			||||||
 | 
						return;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					$showForm = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if (isset($_POST['submit']) && $_POST['submit'] == '1') {
 | 
				
			||||||
 | 
						$email = $_REQUEST['email'];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (empty($email) || !filter_var($email, FILTER_VALIDATE_EMAIL)) {
 | 
				
			||||||
 | 
							$errorWithBackButton('Please enter valid Email.');
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						$account = new OTS_Account();
 | 
				
			||||||
 | 
						$account->findByEMail($email);
 | 
				
			||||||
 | 
						if ($account->isLoaded()) {
 | 
				
			||||||
 | 
							if ($account->getCustomField('email_verified') == '1') {
 | 
				
			||||||
 | 
								$errorWithBackButton('This account is already verified! You can <a href=' . getLink('account/manage') . '>log in</a> on the website.');
 | 
				
			||||||
 | 
								return;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							$accountEmailVerify = AccountEmailVerify::where('account_id', $account->getId())->orderBy('sent_at', 'DESC')->first();
 | 
				
			||||||
 | 
							if ($accountEmailVerify && time() - $accountEmailVerify->sent_at < 60) {
 | 
				
			||||||
 | 
								$errorWithBackButton('Only one Email per minute is allowed. Please try again later.');
 | 
				
			||||||
 | 
								return;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							$tmp_account = $email;
 | 
				
			||||||
 | 
							if (!config('account_login_by_email')) {
 | 
				
			||||||
 | 
								$tmp_account = (USE_ACCOUNT_NAME ? $account->getName() : $account->getId());
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							$hash = md5(generateRandomString(16, true, true) . $email);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							AccountEmailVerify::create([
 | 
				
			||||||
 | 
								'account_id' => $account->getId(),
 | 
				
			||||||
 | 
								'hash' => $hash,
 | 
				
			||||||
 | 
								'sent_at' => time(),
 | 
				
			||||||
 | 
							]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							$verify_url = getLink('account/confirm-email/' . $hash);
 | 
				
			||||||
 | 
							$body_html = $twig->render('mail.account.resend-email-verify.html.twig', array(
 | 
				
			||||||
 | 
								'account' => $tmp_account,
 | 
				
			||||||
 | 
								'verify_url' => generateLink($verify_url, $verify_url, true)
 | 
				
			||||||
 | 
							));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (_mail($account->getEMail(), configLua('serverName') . ' - Verify Account', $body_html)) {
 | 
				
			||||||
 | 
								$message = "If account with this email exists - you will become an email with verification link.";
 | 
				
			||||||
 | 
								$showForm = false;
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								$message = "<p class='error'>An error occurred while sending email (<b>{$email}</b> )! Try again later. For Admin: More info can be found in system/logs/mailer-error.log</p>";
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						else {
 | 
				
			||||||
 | 
							$message = "<br />If account with this email exists - you will become an email with verification link.";
 | 
				
			||||||
 | 
							$showForm = false;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						$twig->display('success.html.twig', array(
 | 
				
			||||||
 | 
							'title' => 'Verify Email Sent',
 | 
				
			||||||
 | 
							'description' => $message,
 | 
				
			||||||
 | 
						));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//show errors if not empty
 | 
				
			||||||
 | 
					if (!empty($errors)) {
 | 
				
			||||||
 | 
						$twig->display('error_box.html.twig', ['errors' => $errors]);
 | 
				
			||||||
 | 
						$twig->display('account.back_button.html.twig', [
 | 
				
			||||||
 | 
							'action' => getLink('account/resend-email-verify'),
 | 
				
			||||||
 | 
						]);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if ($showForm) {
 | 
				
			||||||
 | 
						$twig->display('account.resend-email-verify.html.twig');
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -21,6 +21,9 @@ if(!$logged) {
 | 
				
			|||||||
	$errors[] = 'You are not logged in. You can\'t create guild.';
 | 
						$errors[] = 'You are not logged in. You can\'t create guild.';
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					$configLuaFreePremium = configLua('freePremium');
 | 
				
			||||||
 | 
					$freePremium = (isset($configLuaFreePremium) && getBoolean($configLuaFreePremium)) || ($logged && $account_logged->getPremDays() == OTS_Account::GRATIS_PREMIUM_DAYS);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
$array_of_player_nig = array();
 | 
					$array_of_player_nig = array();
 | 
				
			||||||
if(empty($errors))
 | 
					if(empty($errors))
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
@@ -31,7 +34,7 @@ if(empty($errors))
 | 
				
			|||||||
		if(!$player_rank->isLoaded())
 | 
							if(!$player_rank->isLoaded())
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			if($player->getLevel() >= setting('core.guild_need_level')) {
 | 
								if($player->getLevel() >= setting('core.guild_need_level')) {
 | 
				
			||||||
				if(!setting('core.guild_need_premium') || $account_logged->isPremium()) {
 | 
									if(!setting('core.guild_need_premium') || $account_logged->isPremium() || $freePremium) {
 | 
				
			||||||
					$array_of_player_nig[] = $player->getName();
 | 
										$array_of_player_nig[] = $player->getName();
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
@@ -95,7 +98,7 @@ if($todo == 'save')
 | 
				
			|||||||
		if($player->getLevel() < setting('core.guild_need_level')) {
 | 
							if($player->getLevel() < setting('core.guild_need_level')) {
 | 
				
			||||||
			$errors[] = 'Character <b>'.$name.'</b> has too low level. To create guild you need character with level <b>' . setting('core.guild_need_level') . '</b>.';
 | 
								$errors[] = 'Character <b>'.$name.'</b> has too low level. To create guild you need character with level <b>' . setting('core.guild_need_level') . '</b>.';
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		if(setting('core.guild_need_premium') && !$account_logged->isPremium()) {
 | 
							if(setting('core.guild_need_premium') && !$account_logged->isPremium() && !$freePremium) {
 | 
				
			||||||
			$errors[] = 'Character <b>'.$name.'</b> is on FREE account. To create guild you need PREMIUM account.';
 | 
								$errors[] = 'Character <b>'.$name.'</b> is on FREE account. To create guild you need PREMIUM account.';
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -23,6 +23,12 @@ if(!Validator::guildName($guild_name)) {
 | 
				
			|||||||
	$errors[] = Validator::getLastError();
 | 
						$errors[] = Validator::getLastError();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if (!$db->hasTableAndColumns('guild_invites', ['player_id'])) {
 | 
				
			||||||
 | 
						$errors[] = "Guild invite is not possible on this website.";
 | 
				
			||||||
 | 
						$twig->display('error_box.html.twig', ['errors' => $errors]);
 | 
				
			||||||
 | 
						return;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
if(empty($errors)) {
 | 
					if(empty($errors)) {
 | 
				
			||||||
	$guild = new OTS_Guild();
 | 
						$guild = new OTS_Guild();
 | 
				
			||||||
	$guild->find($guild_name);
 | 
						$guild->find($guild_name);
 | 
				
			||||||
@@ -58,7 +64,7 @@ if(empty($errors)) {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
if(!$guild_vice) {
 | 
					if(empty($errors) && !$guild_vice) {
 | 
				
			||||||
	$errors[] = 'You are not a leader or vice leader of guild <b>'.$guild_name.'</b>.'.$level_in_guild;
 | 
						$errors[] = 'You are not a leader or vice leader of guild <b>'.$guild_name.'</b>.'.$level_in_guild;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -84,6 +90,7 @@ if(isset($_POST['todo']) && $_POST['todo'] == 'save') {
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
if(empty($errors)) {
 | 
					if(empty($errors)) {
 | 
				
			||||||
	include(SYSTEM . 'libs/pot/InvitesDriver.php');
 | 
						include(SYSTEM . 'libs/pot/InvitesDriver.php');
 | 
				
			||||||
	new InvitesDriver($guild);
 | 
						new InvitesDriver($guild);
 | 
				
			||||||
@@ -104,6 +111,7 @@ if(!empty($errors)) {
 | 
				
			|||||||
else {
 | 
					else {
 | 
				
			||||||
	if(isset($_POST['todo']) && $_POST['todo'] == 'save') {
 | 
						if(isset($_POST['todo']) && $_POST['todo'] == 'save') {
 | 
				
			||||||
		$guild->invite($player);
 | 
							$guild->invite($player);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		$twig->display('success.html.twig', array(
 | 
							$twig->display('success.html.twig', array(
 | 
				
			||||||
			'title' => 'Invite player',
 | 
								'title' => 'Invite player',
 | 
				
			||||||
			'description' => 'Player with name <b>' . $player->getName() . '</b> has been invited to your guild.',
 | 
								'description' => 'Player with name <b>' . $player->getName() . '</b> has been invited to your guild.',
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -36,10 +36,9 @@ if(count($guilds_list) > 0) {
 | 
				
			|||||||
		$guildName = $guild->getName();
 | 
							$guildName = $guild->getName();
 | 
				
			||||||
		$guilds[] = array('name' => $guildName, 'logo' => $guild_logo, 'link' => getGuildLink($guildName, false), 'description' => $description);
 | 
							$guilds[] = array('name' => $guildName, 'logo' => $guild_logo, 'link' => getGuildLink($guildName, false), 'description' => $description);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
};
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
$twig->display('guilds.list.html.twig', array(
 | 
					$twig->display('guilds.list.html.twig', array(
 | 
				
			||||||
	'guilds' => $guilds,
 | 
						'guilds' => $guilds,
 | 
				
			||||||
	'logged' => $logged ?? false,
 | 
					 | 
				
			||||||
	'isAdmin' => admin(),
 | 
						'isAdmin' => admin(),
 | 
				
			||||||
));
 | 
					));
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -121,24 +121,27 @@ foreach($rank_list as $rank)
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					$invited_list = [];
 | 
				
			||||||
 | 
					$show_accept_invite = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if ($db->hasTableAndColumns('guild_invites', ['player_id'])) {
 | 
				
			||||||
	include(SYSTEM . 'libs/pot/InvitesDriver.php');
 | 
						include(SYSTEM . 'libs/pot/InvitesDriver.php');
 | 
				
			||||||
	new InvitesDriver($guild);
 | 
						new InvitesDriver($guild);
 | 
				
			||||||
	$invited_list = $guild->listInvites();
 | 
						$invited_list = $guild->listInvites();
 | 
				
			||||||
$show_accept_invite = 0;
 | 
					
 | 
				
			||||||
if($logged && count($invited_list) > 0)
 | 
						if($logged && count($invited_list) > 0) {
 | 
				
			||||||
{
 | 
							foreach($invited_list as $invited_player) {
 | 
				
			||||||
	foreach($invited_list as $invited_player)
 | 
								if(count($account_players) > 0) {
 | 
				
			||||||
	{
 | 
									foreach($account_players as $player_from_acc) {
 | 
				
			||||||
		if(count($account_players) > 0)
 | 
										if($player_from_acc->isLoaded() && $invited_player->isLoaded() && $player_from_acc->getName() == $invited_player->getName()) {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			foreach($account_players as $player_from_acc)
 | 
					 | 
				
			||||||
			{
 | 
					 | 
				
			||||||
				if($player_from_acc->isLoaded() && $invited_player->isLoaded() && $player_from_acc->getName() == $invited_player->getName())
 | 
					 | 
				
			||||||
						$show_accept_invite++;
 | 
											$show_accept_invite++;
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
$useGuildNick = $db->hasTable('guild_members') || $db->hasTable('guild_membership') || $db->hasColumn('players', 'guildnick');
 | 
					$useGuildNick = $db->hasTable('guild_members') || $db->hasTable('guild_membership') || $db->hasColumn('players', 'guildnick');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -123,17 +123,11 @@ if($db->hasColumn('players', 'promotion'))
 | 
				
			|||||||
	$promotion = ',players.promotion';
 | 
						$promotion = ',players.promotion';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
$outfit_addons = false;
 | 
					$outfit_addons = false;
 | 
				
			||||||
$outfit = '';
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
$settingHighscoresOutfit = setting('core.highscores_outfit');
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
if($settingHighscoresOutfit) {
 | 
					 | 
				
			||||||
$outfit = ', lookbody, lookfeet, lookhead, looklegs, looktype';
 | 
					$outfit = ', lookbody, lookfeet, lookhead, looklegs, looktype';
 | 
				
			||||||
if($db->hasColumn('players', 'lookaddons')) {
 | 
					if($db->hasColumn('players', 'lookaddons')) {
 | 
				
			||||||
	$outfit .= ', lookaddons';
 | 
						$outfit .= ', lookaddons';
 | 
				
			||||||
	$outfit_addons = true;
 | 
						$outfit_addons = true;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
$configHighscoresPerPage = setting('core.highscores_per_page');
 | 
					$configHighscoresPerPage = setting('core.highscores_per_page');
 | 
				
			||||||
$limit = $configHighscoresPerPage + 1;
 | 
					$limit = $configHighscoresPerPage + 1;
 | 
				
			||||||
@@ -146,17 +140,24 @@ $cache = Cache::getInstance();
 | 
				
			|||||||
if ($cache->enabled() && $highscoresTTL > 0) {
 | 
					if ($cache->enabled() && $highscoresTTL > 0) {
 | 
				
			||||||
	$tmp = '';
 | 
						$tmp = '';
 | 
				
			||||||
	if ($cache->fetch($cacheKey, $tmp)) {
 | 
						if ($cache->fetch($cacheKey, $tmp)) {
 | 
				
			||||||
		$highscores = unserialize($tmp);
 | 
							$data = unserialize($tmp);
 | 
				
			||||||
 | 
							$totalResults = $data['totalResults'];
 | 
				
			||||||
 | 
							$highscores = $data['highscores'];
 | 
				
			||||||
 | 
							$updatedAt = $data['updatedAt'];
 | 
				
			||||||
		$needReCache = false;
 | 
							$needReCache = false;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
$offset = ($page - 1) * $configHighscoresPerPage;
 | 
					$offset = ($page - 1) * $configHighscoresPerPage;
 | 
				
			||||||
$query->join('accounts', 'accounts.id', '=', 'players.account_id')
 | 
					$query->withOnlineStatus()
 | 
				
			||||||
	->withOnlineStatus()
 | 
					 | 
				
			||||||
	->whereNotIn('players.id', setting('core.highscores_ids_hidden'))
 | 
						->whereNotIn('players.id', setting('core.highscores_ids_hidden'))
 | 
				
			||||||
	->notDeleted()
 | 
						->notDeleted()
 | 
				
			||||||
	->where('players.group_id', '<', setting('core.highscores_groups_hidden'))
 | 
						->where('players.group_id', '<', setting('core.highscores_groups_hidden'));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					$totalResultsQuery = clone $query;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					$query
 | 
				
			||||||
 | 
						->join('accounts', 'accounts.id', '=', 'players.account_id')
 | 
				
			||||||
	->limit($limit)
 | 
						->limit($limit)
 | 
				
			||||||
	->offset($offset)
 | 
						->offset($offset)
 | 
				
			||||||
	->selectRaw('accounts.country, players.id, players.name, players.account_id, players.level, players.vocation' . $outfit . $promotion)
 | 
						->selectRaw('accounts.country, players.id, players.name, players.account_id, players.level, players.vocation' . $outfit . $promotion)
 | 
				
			||||||
@@ -215,17 +216,24 @@ if (empty($highscores)) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
		return $tmp;
 | 
							return $tmp;
 | 
				
			||||||
	})->toArray();
 | 
						})->toArray();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						$updatedAt = time();
 | 
				
			||||||
 | 
						$totalResults = $totalResultsQuery->count();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
if ($highscoresTTL > 0 && $cache->enabled() && $needReCache) {
 | 
					if ($highscoresTTL > 0 && $cache->enabled() && $needReCache) {
 | 
				
			||||||
	$cache->set($cacheKey, serialize($highscores), $highscoresTTL * 60);
 | 
						$cache->set($cacheKey, serialize(
 | 
				
			||||||
 | 
							[
 | 
				
			||||||
 | 
								'totalResults' => $totalResults,
 | 
				
			||||||
 | 
								'highscores' => $highscores,
 | 
				
			||||||
 | 
								'updatedAt' => $updatedAt,
 | 
				
			||||||
 | 
							]
 | 
				
			||||||
 | 
						), $highscoresTTL * 60);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
$show_link_to_next_page = false;
 | 
					$show_link_to_next_page = false;
 | 
				
			||||||
$i = 0;
 | 
					$i = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
$settingHighscoresVocation = setting('core.highscores_vocation');
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
foreach($highscores as $id => &$player)
 | 
					foreach($highscores as $id => &$player)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	if(++$i <= $configHighscoresPerPage)
 | 
						if(++$i <= $configHighscoresPerPage)
 | 
				
			||||||
@@ -239,11 +247,23 @@ foreach($highscores as $id => &$player)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
		$player['link'] = getPlayerLink($player['name'], false);
 | 
							$player['link'] = getPlayerLink($player['name'], false);
 | 
				
			||||||
		$player['flag'] = getFlagImage($player['country']);
 | 
							$player['flag'] = getFlagImage($player['country']);
 | 
				
			||||||
		if($settingHighscoresOutfit) {
 | 
					 | 
				
			||||||
		$player['outfit'] = '<img style="position:absolute;margin-top:' . (in_array($player['looktype'], setting('core.outfit_images_wrong_looktypes')) ? '-15px;margin-left:5px' : '-45px;margin-left:-25px') . ';" src="' . $player['outfit_url'] . '" alt="" />';
 | 
							$player['outfit'] = '<img style="position:absolute;margin-top:' . (in_array($player['looktype'], setting('core.outfit_images_wrong_looktypes')) ? '-15px;margin-left:5px' : '-45px;margin-left:-25px') . ';" src="' . $player['outfit_url'] . '" alt="" />';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if ($skill != POT::SKILL__LEVEL) {
 | 
				
			||||||
 | 
								if (isset($lastValue) && $lastValue == $player['value']) {
 | 
				
			||||||
 | 
									$player['rank'] = $lastRank;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
								else {
 | 
				
			||||||
				$player['rank'] = $offset + $i;
 | 
									$player['rank'] = $offset + $i;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								$lastRank = $player['rank'] ;
 | 
				
			||||||
 | 
								$lastValue = $player['value'];
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							else {
 | 
				
			||||||
 | 
								$player['rank'] = $offset + $i;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	else {
 | 
						else {
 | 
				
			||||||
		unset($highscores[$id]);
 | 
							unset($highscores[$id]);
 | 
				
			||||||
		$show_link_to_next_page = true;
 | 
							$show_link_to_next_page = true;
 | 
				
			||||||
@@ -263,6 +283,8 @@ if($show_link_to_next_page) {
 | 
				
			|||||||
	$linkNextPage = getLink('highscores') . '/' . $list . ($vocation !== 'all' ? '/' . $vocation : '') . '/' . ($page + 1);
 | 
						$linkNextPage = getLink('highscores') . '/' . $list . ($vocation !== 'all' ? '/' . $vocation : '') . '/' . ($page + 1);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					$baseLink = getLink('highscores') . '/' . $list . ($vocation !== 'all' ? '/' . $vocation : '') . '/';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
$types = array(
 | 
					$types = array(
 | 
				
			||||||
	'experience' => 'Experience',
 | 
						'experience' => 'Experience',
 | 
				
			||||||
	'magic' => 'Magic',
 | 
						'magic' => 'Magic',
 | 
				
			||||||
@@ -297,4 +319,8 @@ $twig->display('highscores.html.twig', [
 | 
				
			|||||||
	'types' => $types,
 | 
						'types' => $types,
 | 
				
			||||||
	'linkPreviousPage' => $linkPreviousPage,
 | 
						'linkPreviousPage' => $linkPreviousPage,
 | 
				
			||||||
	'linkNextPage' => $linkNextPage,
 | 
						'linkNextPage' => $linkNextPage,
 | 
				
			||||||
 | 
						'totalResults' => $totalResults,
 | 
				
			||||||
 | 
						'page' => $page,
 | 
				
			||||||
 | 
						'baseLink' => $baseLink,
 | 
				
			||||||
 | 
						'updatedAt' => $updatedAt,
 | 
				
			||||||
]);
 | 
					]);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -9,26 +9,33 @@
 | 
				
			|||||||
 * @link      https://my-aac.org
 | 
					 * @link      https://my-aac.org
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use MyAAC\Cache\Cache;
 | 
				
			||||||
use MyAAC\Models\ServerConfig;
 | 
					use MyAAC\Models\ServerConfig;
 | 
				
			||||||
use MyAAC\Models\ServerRecord;
 | 
					use MyAAC\Models\ServerRecord;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
defined('MYAAC') or die('Direct access not allowed!');
 | 
					defined('MYAAC') or die('Direct access not allowed!');
 | 
				
			||||||
$title = 'Who is online?';
 | 
					$title = 'Who is online?';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
if (setting('core.account_country'))
 | 
					if (setting('core.account_country')) {
 | 
				
			||||||
	require SYSTEM . 'countries.conf.php';
 | 
						require SYSTEM . 'countries.conf.php';
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
$promotion = '';
 | 
					$promotion = '';
 | 
				
			||||||
if($db->hasColumn('players', 'promotion'))
 | 
					if($db->hasColumn('players', 'promotion')) {
 | 
				
			||||||
	$promotion = '`promotion`,';
 | 
						$promotion = '`promotion`,';
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
$order = $_GET['order'] ?? 'name';
 | 
					$order = $_GET['order'] ?? 'name_asc';
 | 
				
			||||||
if(!in_array($order, array('country', 'name', 'level', 'vocation')))
 | 
					if(!in_array($order, ['country_asc', 'country_desc', 'name_asc', 'name_desc', 'level_asc', 'level_desc', 'vocation_asc', 'vocation_desc'])) {
 | 
				
			||||||
	$order = $db->fieldName('name');
 | 
						$order = 'name_asc';
 | 
				
			||||||
else if($order == 'country')
 | 
					}
 | 
				
			||||||
	$order = $db->tableName('accounts') . '.' . $db->fieldName('country');
 | 
					else if($order == 'vocation_asc' || $order == 'vocation_desc') {
 | 
				
			||||||
else if($order == 'vocation')
 | 
						$order = $promotion . 'vocation_' . (str_contains($order, 'asc') ? 'asc' : 'desc');
 | 
				
			||||||
	$order = $promotion . 'vocation ASC';
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					$cached = Cache::remember("online_$order", setting('core.online_cache_ttl') * 60, function() use($db, $promotion, $order) {
 | 
				
			||||||
 | 
						$orderExplode = explode('_', $order);
 | 
				
			||||||
 | 
						$orderSql = $orderExplode[0] . ' ' . $orderExplode[1];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	$skull_type = 'skull';
 | 
						$skull_type = 'skull';
 | 
				
			||||||
	if($db->hasColumn('players', 'skull_type')) {
 | 
						if($db->hasColumn('players', 'skull_type')) {
 | 
				
			||||||
@@ -41,72 +48,74 @@ if($db->hasColumn('players', 'skull_time')) {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	$outfit_addons = false;
 | 
						$outfit_addons = false;
 | 
				
			||||||
$outfit = '';
 | 
					 | 
				
			||||||
if (setting('core.online_outfit')) {
 | 
					 | 
				
			||||||
	$outfit = ', lookbody, lookfeet, lookhead, looklegs, looktype';
 | 
						$outfit = ', lookbody, lookfeet, lookhead, looklegs, looktype';
 | 
				
			||||||
	if($db->hasColumn('players', 'lookaddons')) {
 | 
						if($db->hasColumn('players', 'lookaddons')) {
 | 
				
			||||||
		$outfit .= ', lookaddons';
 | 
							$outfit .= ', lookaddons';
 | 
				
			||||||
		$outfit_addons = true;
 | 
							$outfit_addons = true;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
$vocs = [];
 | 
						$vocations = array_map(function ($name) {
 | 
				
			||||||
if (setting('core.online_vocations')) {
 | 
							return 0;
 | 
				
			||||||
	foreach($config['vocations'] as $id => $name) {
 | 
						}, setting('core.vocations'));
 | 
				
			||||||
		$vocs[$id] = 0;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if($db->hasTable('players_online')) // tfs 1.0
 | 
						if($db->hasTable('players_online')) // tfs 1.0
 | 
				
			||||||
	$playersOnline = $db->query('SELECT `accounts`.`country`, `players`.`name`, `players`.`level`, `players`.`vocation`' . $outfit . ', `' . $skull_time . '` as `skulltime`, `' . $skull_type . '` as `skull` FROM `accounts`, `players`, `players_online` WHERE `players`.`id` = `players_online`.`player_id` AND `accounts`.`id` = `players`.`account_id`  ORDER BY ' . $order);
 | 
							$playersOnline = $db->query('SELECT `accounts`.`country`, `players`.`name`, `players`.`level`, `players`.`vocation`' . $outfit . ', `' . $skull_time . '` as `skulltime`, `' . $skull_type . '` as `skull` FROM `accounts`, `players`, `players_online` WHERE `players`.`id` = `players_online`.`player_id` AND `accounts`.`id` = `players`.`account_id`  ORDER BY ' . $orderSql);
 | 
				
			||||||
	else
 | 
						else
 | 
				
			||||||
	$playersOnline = $db->query('SELECT `accounts`.`country`, `players`.`name`, `players`.`level`, `players`.`vocation`' . $outfit . ', ' . $promotion . ' `' . $skull_time . '` as `skulltime`, `' . $skull_type . '` as `skull` FROM `accounts`, `players` WHERE `players`.`online` > 0 AND `accounts`.`id` = `players`.`account_id`  ORDER BY ' . $order);
 | 
							$playersOnline = $db->query('SELECT `accounts`.`country`, `players`.`name`, `players`.`level`, `players`.`vocation`' . $outfit . ', ' . $promotion . ' `' . $skull_time . '` as `skulltime`, `' . $skull_type . '` as `skull` FROM `accounts`, `players` WHERE `players`.`online` > 0 AND `accounts`.`id` = `players`.`account_id`  ORDER BY ' . $orderSql);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
$players_data = array();
 | 
						$settingVocations = setting('core.vocations');
 | 
				
			||||||
$players = 0;
 | 
						$settingVocationsAmount = setting('core.vocations_amount');
 | 
				
			||||||
$data = '';
 | 
					
 | 
				
			||||||
 | 
						$players = [];
 | 
				
			||||||
	foreach($playersOnline as $player) {
 | 
						foreach($playersOnline as $player) {
 | 
				
			||||||
		$skull = '';
 | 
							$skull = '';
 | 
				
			||||||
	if (setting('core.online_skulls'))
 | 
							if($player['skulltime'] > 0) {
 | 
				
			||||||
	{
 | 
								if($player['skull'] == 3) {
 | 
				
			||||||
		if($player['skulltime'] > 0)
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			if($player['skull'] == 3)
 | 
					 | 
				
			||||||
				$skull = ' <img style="border: 0;" src="images/white_skull.gif"/>';
 | 
									$skull = ' <img style="border: 0;" src="images/white_skull.gif"/>';
 | 
				
			||||||
			elseif($player['skull'] == 4)
 | 
								}
 | 
				
			||||||
 | 
								elseif($player['skull'] == 4) {
 | 
				
			||||||
				$skull = ' <img style="border: 0;" src="images/red_skull.gif"/>';
 | 
									$skull = ' <img style="border: 0;" src="images/red_skull.gif"/>';
 | 
				
			||||||
			elseif($player['skull'] == 5)
 | 
								}
 | 
				
			||||||
 | 
								elseif($player['skull'] == 5) {
 | 
				
			||||||
				$skull = ' <img style="border: 0;" src="images/black_skull.gif"/>';
 | 
									$skull = ' <img style="border: 0;" src="images/black_skull.gif"/>';
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if(isset($player['promotion'])) {
 | 
							if(isset($player['promotion'])) {
 | 
				
			||||||
			if((int)$player['promotion'] > 0)
 | 
								if((int)$player['promotion'] > 0)
 | 
				
			||||||
			$player['vocation'] += ($player['promotion'] * $config['vocations_amount']);
 | 
									$player['vocation'] += ($player['promotion'] * $settingVocationsAmount);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	$players_data[] = array(
 | 
							$players[] = array(
 | 
				
			||||||
			'name' => getPlayerLink($player['name']),
 | 
								'name' => getPlayerLink($player['name']),
 | 
				
			||||||
			'player' => $player,
 | 
								'player' => $player,
 | 
				
			||||||
			'level' => $player['level'],
 | 
								'level' => $player['level'],
 | 
				
			||||||
		'vocation' => $config['vocations'][$player['vocation']],
 | 
								'vocation' => $settingVocations[$player['vocation']],
 | 
				
			||||||
		'country_image' => setting('core.account_country') ? getFlagImage($player['country']) : null,
 | 
								'skull' => $skull,
 | 
				
			||||||
		'outfit' => setting('core.online_outfit') ? setting('core.outfit_images_url') . '?id=' . $player['looktype'] . ($outfit_addons ? '&addons=' . $player['lookaddons'] : '') . '&head=' . $player['lookhead'] . '&body=' . $player['lookbody'] . '&legs=' . $player['looklegs'] . '&feet=' . $player['lookfeet'] : null
 | 
								'country_image' => getFlagImage($player['country']),
 | 
				
			||||||
 | 
								'outfit' => setting('core.outfit_images_url') . '?id=' . $player['looktype'] . ($outfit_addons ? '&addons=' . $player['lookaddons'] : '') . '&head=' . $player['lookhead'] . '&body=' . $player['lookbody'] . '&legs=' . $player['looklegs'] . '&feet=' . $player['lookfeet'],
 | 
				
			||||||
		);
 | 
							);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (setting('core.online_vocations')) {
 | 
							$vocations[($player['vocation'] > $settingVocationsAmount ? $player['vocation'] - $settingVocationsAmount : $player['vocation'])]++;
 | 
				
			||||||
		$vocs[($player['vocation'] > $config['vocations_amount'] ? $player['vocation'] - $config['vocations_amount'] : $player['vocation'])]++;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	$record = '';
 | 
						$record = '';
 | 
				
			||||||
if(count($players_data) > 0) {
 | 
						if(count($players) > 0) {
 | 
				
			||||||
		if( setting('core.online_record')) {
 | 
							if( setting('core.online_record')) {
 | 
				
			||||||
			$result = null;
 | 
								$result = null;
 | 
				
			||||||
			$timestamp = false;
 | 
								$timestamp = false;
 | 
				
			||||||
			if($db->hasTable('server_record')) {
 | 
								if($db->hasTable('server_record')) {
 | 
				
			||||||
			$timestamp = true;
 | 
									$timestamp = $db->hasColumn('server_record', 'timestamp');
 | 
				
			||||||
			$result = ServerRecord::where('world_id', $config['lua']['worldId'])->orderByDesc('record')->first()->toArray();
 | 
									$serverRecordQuery = ServerRecord::query();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									if ($db->hasColumn('server_record', 'world_id')) {
 | 
				
			||||||
 | 
										$serverRecordQuery->where('world_id', configLua('worldId'));
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									$result = $serverRecordQuery->orderByDesc('record')->first();
 | 
				
			||||||
 | 
									if ($result) {
 | 
				
			||||||
 | 
										$result = $result->toArray();
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
			} else if($db->hasTable('server_config')) { // tfs 1.0
 | 
								} else if($db->hasTable('server_config')) { // tfs 1.0
 | 
				
			||||||
				$row = ServerConfig::where('config', 'players_record')->first();
 | 
									$row = ServerConfig::where('config', 'players_record')->first();
 | 
				
			||||||
				if ($row) {
 | 
									if ($row) {
 | 
				
			||||||
@@ -115,17 +124,25 @@ if(count($players_data) > 0) {
 | 
				
			|||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if($result) {
 | 
								if($result) {
 | 
				
			||||||
			$record = 'The maximum on this game world was ' . $result['record'] . ' players' . ($timestamp ? ' on ' . date("M d Y, H:i:s", $result['timestamp']) . '.' : '.');
 | 
									$record = $result['record'] . ' player' . ($result['record'] > 1 ? 's' : '') . ($timestamp ? ' (on ' . date("M d Y, H:i:s", $result['timestamp']) . ')' : '');
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
$twig->display('online.html.twig', array(
 | 
						return [
 | 
				
			||||||
	'players' => $players_data,
 | 
							'players' => $players,
 | 
				
			||||||
		'record' => $record,
 | 
							'record' => $record,
 | 
				
			||||||
	'vocs' => $vocs,
 | 
							'vocations' => $vocations,
 | 
				
			||||||
 | 
						];
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					$twig->display('online.html.twig', array(
 | 
				
			||||||
 | 
						'players' => $cached['players'],
 | 
				
			||||||
 | 
						'record' => $cached['record'],
 | 
				
			||||||
 | 
						'vocations' => $cached['vocations'],
 | 
				
			||||||
 | 
						'vocs' => $cached['vocations'], // deprecated, to be removed
 | 
				
			||||||
 | 
						'order' => $order,
 | 
				
			||||||
));
 | 
					));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// search bar
 | 
					// search bar
 | 
				
			||||||
$twig->display('online.form.html.twig');
 | 
					$twig->display('characters.form.html.twig');
 | 
				
			||||||
?>
 | 
					 | 
				
			||||||
 
 | 
				
			|||||||
@@ -88,25 +88,38 @@ if($logged && $account_logged && $account_logged->isLoaded()) {
 | 
				
			|||||||
/**
 | 
					/**
 | 
				
			||||||
 * Routes loading
 | 
					 * Routes loading
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
$dispatcher = FastRoute\cachedDispatcher(function (FastRoute\RouteCollector $r) {
 | 
					 | 
				
			||||||
$routesFinal = [];
 | 
					$routesFinal = [];
 | 
				
			||||||
 | 
					$dispatcher = FastRoute\cachedDispatcher(function (FastRoute\RouteCollector $r) {
 | 
				
			||||||
 | 
						global $cache, $routesFinal;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	foreach(getDatabasePages() as $page) {
 | 
						foreach(getDatabasePages() as $page) {
 | 
				
			||||||
		$routesFinal[] = ['*', $page, '__database__/' . $page, 100];
 | 
							$routesFinal[] = ['*', $page, '__database__/' . $page, 100];
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						$routes = require SYSTEM . 'routes.php';
 | 
				
			||||||
	Plugins::clearWarnings();
 | 
						Plugins::clearWarnings();
 | 
				
			||||||
	foreach (Plugins::getRoutes() as $route) {
 | 
					
 | 
				
			||||||
		$routesFinal[] = [$route[0], $route[1], $route[2], $route[3] ?? 1000];
 | 
						foreach (Plugins::getRoutes() as $pluginRoute) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							$routesFinal[] = [$pluginRoute[0], $pluginRoute[1], $pluginRoute[2], $pluginRoute[3] ?? 1000];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// Possibility to override routes with plugins pages, like characters.php
 | 
				
			||||||
 | 
							foreach ($routes as &$route) {
 | 
				
			||||||
 | 
								if (str_contains($pluginRoute[2], 'pages/' . $route[2])) {
 | 
				
			||||||
 | 
									$route[2] = $pluginRoute[2];
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
		echo '<pre>';
 | 
							echo '<pre>';
 | 
				
			||||||
		var_dump($route[1], $route[3], $route[2]);
 | 
							var_dump($pluginRoute[1], $pluginRoute[3], $pluginRoute[2]);
 | 
				
			||||||
		echo '/<pre>';
 | 
							echo '/<pre>';
 | 
				
			||||||
*/
 | 
					*/
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	$routes = require SYSTEM . 'routes.php';
 | 
					 | 
				
			||||||
	foreach ($routes as $route) {
 | 
						foreach ($routes as $route) {
 | 
				
			||||||
		if (!str_contains($route[2], '__redirect__') && !str_contains($route[2], '__database__')) {
 | 
							if (!str_contains($route[2], '__redirect__') && !str_contains($route[2], '__database__')
 | 
				
			||||||
 | 
								&& !str_contains($route[2], 'plugins/')
 | 
				
			||||||
 | 
							) {
 | 
				
			||||||
			if (!is_file(BASE . 'system/pages/' . $route[2])) {
 | 
								if (!is_file(BASE . 'system/pages/' . $route[2])) {
 | 
				
			||||||
				continue;
 | 
									continue;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
@@ -154,7 +167,7 @@ $dispatcher = FastRoute\cachedDispatcher(function (FastRoute\RouteCollector $r)
 | 
				
			|||||||
	echo '</pre>';
 | 
						echo '</pre>';
 | 
				
			||||||
	die;
 | 
						die;
 | 
				
			||||||
*/
 | 
					*/
 | 
				
			||||||
	foreach ($routesFinal as $route) {
 | 
						foreach ($routesFinal as &$route) {
 | 
				
			||||||
		if ($route[0] === '*') {
 | 
							if ($route[0] === '*') {
 | 
				
			||||||
			$route[0] = ['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'HEAD'];
 | 
								$route[0] = ['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'HEAD'];
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
@@ -174,14 +187,23 @@ $dispatcher = FastRoute\cachedDispatcher(function (FastRoute\RouteCollector $r)
 | 
				
			|||||||
		// apply aliases
 | 
							// apply aliases
 | 
				
			||||||
		$route[1] = str_replace($aliases[0], $aliases[1], $route[1]);
 | 
							$route[1] = str_replace($aliases[0], $aliases[1], $route[1]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							try {
 | 
				
			||||||
			$r->addRoute($route[0], $route[1], $route[2]);
 | 
								$r->addRoute($route[0], $route[1], $route[2]);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
							catch (\Exception $e) {
 | 
				
			||||||
 | 
								// duplicated route, just ignore
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (config('env') === 'dev') {
 | 
						if (config('env') === 'dev') {
 | 
				
			||||||
		foreach(Plugins::getWarnings() as $warning) {
 | 
							foreach(Plugins::getWarnings() as $warning) {
 | 
				
			||||||
			log_append('router.log', $warning);
 | 
								log_append('router.log', $warning);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if ($cache->enabled()) {
 | 
				
			||||||
 | 
							$cache->set('routes_final', serialize($routesFinal), 10 * 365 * 24 * 60 * 60); // 10 years / infinite
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
},
 | 
					},
 | 
				
			||||||
	[
 | 
						[
 | 
				
			||||||
		'cacheFile' => CACHE . 'route.cache',
 | 
							'cacheFile' => CACHE . 'route.cache',
 | 
				
			||||||
@@ -196,7 +218,7 @@ $found = true;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
// old support for pages like /?subtopic=accountmanagement
 | 
					// old support for pages like /?subtopic=accountmanagement
 | 
				
			||||||
$page = $_REQUEST['p'] ?? ($_REQUEST['subtopic'] ?? '');
 | 
					$page = $_REQUEST['p'] ?? ($_REQUEST['subtopic'] ?? '');
 | 
				
			||||||
if(!empty($page) && preg_match('/^[A-z0-9\-]+$/', $page)) {
 | 
					if(!empty($page) && preg_match('/^[A-z0-9\/\-]+$/', $page)) {
 | 
				
			||||||
	if (isset($_REQUEST['p'])) { // some plugins may require this
 | 
						if (isset($_REQUEST['p'])) { // some plugins may require this
 | 
				
			||||||
		$_REQUEST['subtopic'] = $_REQUEST['p'];
 | 
							$_REQUEST['subtopic'] = $_REQUEST['p'];
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -205,11 +227,28 @@ if(!empty($page) && preg_match('/^[A-z0-9\-]+$/', $page)) {
 | 
				
			|||||||
		require SYSTEM . 'compat/pages.php';
 | 
							require SYSTEM . 'compat/pages.php';
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						$foundRoute = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						$tmp = null;
 | 
				
			||||||
 | 
						if ($cache->enabled() && $cache->fetch('routes_final', $tmp)) {
 | 
				
			||||||
 | 
							$routesFinal = unserialize($tmp);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						foreach ($routesFinal as $route) {
 | 
				
			||||||
 | 
							if ($page === $route[1]) {
 | 
				
			||||||
 | 
								$file = $route[2];
 | 
				
			||||||
 | 
								$foundRoute = true;
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!$foundRoute) {
 | 
				
			||||||
		$file = loadPageFromFileSystem($page, $found);
 | 
							$file = loadPageFromFileSystem($page, $found);
 | 
				
			||||||
		if(!$found) {
 | 
							if(!$found) {
 | 
				
			||||||
			$file = false;
 | 
								$file = false;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
else {
 | 
					else {
 | 
				
			||||||
	$routeInfo = $dispatcher->dispatch($httpMethod, $uri);
 | 
						$routeInfo = $dispatcher->dispatch($httpMethod, $uri);
 | 
				
			||||||
	switch ($routeInfo[0]) {
 | 
						switch ($routeInfo[0]) {
 | 
				
			||||||
@@ -321,7 +360,9 @@ if (isset($_REQUEST['_page_only'])) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
if(!isset($title)) {
 | 
					if(!isset($title)) {
 | 
				
			||||||
	$title = str_replace('index.php/', '', $page);
 | 
						$title = str_replace('index.php/', '', $page);
 | 
				
			||||||
	$title = ucfirst($title);
 | 
						$title = str_replace(['_', '-', '/'], ' ', $page);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						$title = ucwords($title);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
if(setting('core.backward_support')) {
 | 
					if(setting('core.backward_support')) {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -22,11 +22,11 @@ return [
 | 
				
			|||||||
	['GET', 'account/confirm-email/{hash:alphanum}', 'account/confirm-email.php'],
 | 
						['GET', 'account/confirm-email/{hash:alphanum}', 'account/confirm-email.php'],
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	['GET', 'bans/{page:int}', 'bans.php'],
 | 
						['GET', 'bans/{page:int}', 'bans.php'],
 | 
				
			||||||
	[['GET', 'POST'], 'characters[/{name:[A-Za-z0-9-_%+\' \[\]]+}]', 'characters.php'],
 | 
						[['GET', 'POST'], 'characters/{name:[A-Za-z0-9-_%+\' \[\]]+}', 'characters.php'],
 | 
				
			||||||
	['GET', 'changelog[/{page:int}]', 'changelog.php'],
 | 
						['GET', 'changelog/{page:int}', 'changelog.php'],
 | 
				
			||||||
	[['GET', 'POST'], 'monsters[/{name:string}]', 'monsters.php'],
 | 
						[['GET', 'POST'], 'monsters/{name:string}', 'monsters.php'],
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	[['GET', 'POST'], 'faq[/{action:string}]', 'faq.php'],
 | 
						[['GET', 'POST'], 'faq/{action:string}', 'faq.php'],
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	[['GET', 'POST'], 'forum/{action:string}', 'forum.php'],
 | 
						[['GET', 'POST'], 'forum/{action:string}', 'forum.php'],
 | 
				
			||||||
	['GET', 'forum/board/{id:int}', 'forum/show_board.php'],
 | 
						['GET', 'forum/board/{id:int}', 'forum/show_board.php'],
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -28,6 +28,15 @@ if (!IS_CLI) {
 | 
				
			|||||||
	$siteURL = $serverUrl . $baseDir;
 | 
						$siteURL = $serverUrl . $baseDir;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					$donateColumnOptions = [
 | 
				
			||||||
 | 
						'premium_points' => 'Premium Points',
 | 
				
			||||||
 | 
						'coins' => 'Coins',
 | 
				
			||||||
 | 
					];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if (defined('HAS_ACCOUNT_COINS_TRANSFERABLE') && (HAS_ACCOUNT_COINS_TRANSFERABLE || HAS_ACCOUNT_TRANSFERABLE_COINS)) {
 | 
				
			||||||
 | 
						$donateColumnOptions[ACCOUNT_COINS_TRANSFERABLE_COLUMN] = 'Coins Transferable';
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
return [
 | 
					return [
 | 
				
			||||||
	'name' => 'MyAAC',
 | 
						'name' => 'MyAAC',
 | 
				
			||||||
	'settings' => [
 | 
						'settings' => [
 | 
				
			||||||
@@ -694,7 +703,14 @@ Sent by MyAAC,<br/>
 | 
				
			|||||||
			'name' => 'Default Account Coins',
 | 
								'name' => 'Default Account Coins',
 | 
				
			||||||
			'type' => 'number',
 | 
								'type' => 'number',
 | 
				
			||||||
			'desc' => 'Default coins on new account',
 | 
								'desc' => 'Default coins on new account',
 | 
				
			||||||
			'hidden' => ($db && !$db->hasColumn('accounts', 'coins')),
 | 
								'hidden' => ($db && !HAS_ACCOUNT_COINS),
 | 
				
			||||||
 | 
								'default' => 0,
 | 
				
			||||||
 | 
							],
 | 
				
			||||||
 | 
							'account_coins_transferable' => [
 | 
				
			||||||
 | 
								'name' => 'Default Account Transferable Coins',
 | 
				
			||||||
 | 
								'type' => 'number',
 | 
				
			||||||
 | 
								'desc' => 'Default transferable coins on new account',
 | 
				
			||||||
 | 
								'hidden' => ($db && !HAS_ACCOUNT_COINS_TRANSFERABLE && !HAS_ACCOUNT_TRANSFERABLE_COINS),
 | 
				
			||||||
			'default' => 0,
 | 
								'default' => 0,
 | 
				
			||||||
		],
 | 
							],
 | 
				
			||||||
		'account_mail_change' => [
 | 
							'account_mail_change' => [
 | 
				
			||||||
@@ -1062,6 +1078,12 @@ Sent by MyAAC,<br/>
 | 
				
			|||||||
			'desc' => 'How often to update highscores from database in minutes. Too low may slow down your website.<br/>0 to disable.',
 | 
								'desc' => 'How often to update highscores from database in minutes. Too low may slow down your website.<br/>0 to disable.',
 | 
				
			||||||
			'default' => 15,
 | 
								'default' => 15,
 | 
				
			||||||
		],
 | 
							],
 | 
				
			||||||
 | 
							'highscores_skills_box' => [
 | 
				
			||||||
 | 
								'name' => 'Display Skills Box',
 | 
				
			||||||
 | 
								'type' => 'boolean',
 | 
				
			||||||
 | 
								'desc' => 'show "Choose a skill" box on the highscores (allowing peoples to sort highscores by skill)?',
 | 
				
			||||||
 | 
								'default' => true,
 | 
				
			||||||
 | 
							],
 | 
				
			||||||
		'highscores_vocation_box' => [
 | 
							'highscores_vocation_box' => [
 | 
				
			||||||
			'name' => 'Display Vocation Box',
 | 
								'name' => 'Display Vocation Box',
 | 
				
			||||||
			'type' => 'boolean',
 | 
								'type' => 'boolean',
 | 
				
			||||||
@@ -1074,6 +1096,12 @@ Sent by MyAAC,<br/>
 | 
				
			|||||||
			'desc' => 'Show player vocation under his nickname?',
 | 
								'desc' => 'Show player vocation under his nickname?',
 | 
				
			||||||
			'default' => true,
 | 
								'default' => true,
 | 
				
			||||||
		],
 | 
							],
 | 
				
			||||||
 | 
							'highscores_online_status' => [
 | 
				
			||||||
 | 
								'name' => 'Display Online Status',
 | 
				
			||||||
 | 
								'type' => 'boolean',
 | 
				
			||||||
 | 
								'desc' => 'Show player status as red (offline) or green (online)',
 | 
				
			||||||
 | 
								'default' => false,
 | 
				
			||||||
 | 
							],
 | 
				
			||||||
		'highscores_frags' => [
 | 
							'highscores_frags' => [
 | 
				
			||||||
			'name' => 'Display Top Frags',
 | 
								'name' => 'Display Top Frags',
 | 
				
			||||||
			'type' => 'boolean',
 | 
								'type' => 'boolean',
 | 
				
			||||||
@@ -1228,6 +1256,14 @@ Sent by MyAAC,<br/>
 | 
				
			|||||||
			'type' => 'section',
 | 
								'type' => 'section',
 | 
				
			||||||
			'title' => 'Online Page'
 | 
								'title' => 'Online Page'
 | 
				
			||||||
		],
 | 
							],
 | 
				
			||||||
 | 
							'online_cache_ttl' => [
 | 
				
			||||||
 | 
								'name' => 'Online Cache TTL (in minutes)',
 | 
				
			||||||
 | 
								'type' => 'number',
 | 
				
			||||||
 | 
								'min' => 0,
 | 
				
			||||||
 | 
								'desc' => 'How often to update online list from database in minutes. Too low may slow down your website.' . PHP_EOL .
 | 
				
			||||||
 | 
									'0 to disable.',
 | 
				
			||||||
 | 
								'default' => 15,
 | 
				
			||||||
 | 
							],
 | 
				
			||||||
		'online_record' => [
 | 
							'online_record' => [
 | 
				
			||||||
			'name' => 'Display Players Record',
 | 
								'name' => 'Display Players Record',
 | 
				
			||||||
			'type' => 'boolean',
 | 
								'type' => 'boolean',
 | 
				
			||||||
@@ -1264,6 +1300,12 @@ Sent by MyAAC,<br/>
 | 
				
			|||||||
			'desc' => '',
 | 
								'desc' => '',
 | 
				
			||||||
			'default' => false,
 | 
								'default' => false,
 | 
				
			||||||
		],
 | 
							],
 | 
				
			||||||
 | 
							'online_datacenter' => [
 | 
				
			||||||
 | 
								'name' => 'Data Center',
 | 
				
			||||||
 | 
								'type' => 'text',
 | 
				
			||||||
 | 
								'desc' => 'Server Location, will be shown on online page',
 | 
				
			||||||
 | 
								'default' => 'Poland - Warsaw',
 | 
				
			||||||
 | 
							],
 | 
				
			||||||
		[
 | 
							[
 | 
				
			||||||
			'type' => 'section',
 | 
								'type' => 'section',
 | 
				
			||||||
			'title' => 'Team Page'
 | 
								'title' => 'Team Page'
 | 
				
			||||||
@@ -1565,13 +1607,14 @@ Sent by MyAAC,<br/>
 | 
				
			|||||||
			'name' => 'Donate Column',
 | 
								'name' => 'Donate Column',
 | 
				
			||||||
			'type' => 'options',
 | 
								'type' => 'options',
 | 
				
			||||||
			'desc' => 'What to give to player after donation - what column in accounts table to use.',
 | 
								'desc' => 'What to give to player after donation - what column in accounts table to use.',
 | 
				
			||||||
			'options' => ['premium_points' => 'Premium Points', 'coins' => 'Coins'],
 | 
								'options' => $donateColumnOptions,
 | 
				
			||||||
			'default' => 'premium_points',
 | 
								'default' => 'premium_points',
 | 
				
			||||||
			'callbacks' => [
 | 
								'callbacks' => [
 | 
				
			||||||
				'beforeSave' => function($key, $value, &$errorMessage) {
 | 
									'beforeSave' => function($key, $value, &$errorMessage) {
 | 
				
			||||||
					global $db;
 | 
										global $db;
 | 
				
			||||||
					if ($value == 'coins' && !$db->hasColumn('accounts', 'coins')) {
 | 
					
 | 
				
			||||||
						$errorMessage = "Shop: Donate Column: Cannot set column to coins, because it doesn't exist in database.";
 | 
										if (!$db->hasColumn('accounts', $value)) {
 | 
				
			||||||
 | 
											$errorMessage = "Shop: Donate Column: Cannot set column to $value, because it doesn't exist in database.";
 | 
				
			||||||
						return false;
 | 
											return false;
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
					return true;
 | 
										return true;
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										49
									
								
								system/src/Admin/Plugins.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								system/src/Admin/Plugins.php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,49 @@
 | 
				
			|||||||
 | 
					<?php
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace MyAAC\Admin;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use GuzzleHttp\Client;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class Plugins
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						private string $api_base_uri = 'https://plugins.my-aac.org/api/';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						public function getLatestVersions(): array
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							$client = new Client([
 | 
				
			||||||
 | 
								// Base URI is used with relative requests
 | 
				
			||||||
 | 
								'base_uri' => $this->api_base_uri,
 | 
				
			||||||
 | 
								// You can set any number of default request options.
 | 
				
			||||||
 | 
								'timeout'  => 3.0,
 | 
				
			||||||
 | 
							]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							$plugins = get_plugins(true);
 | 
				
			||||||
 | 
							foreach ($plugins as &$plugin) {
 | 
				
			||||||
 | 
								if (str_contains($plugin, 'disabled.')) {
 | 
				
			||||||
 | 
									$plugin = str_replace('disabled.', '', $plugin);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							try {
 | 
				
			||||||
 | 
								$response = $client->get('get-latest-versions', [
 | 
				
			||||||
 | 
									'json' => ['plugins' => $plugins],
 | 
				
			||||||
 | 
								]);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							catch (\Exception $e) {
 | 
				
			||||||
 | 
								error('API Error. Please try again later.');
 | 
				
			||||||
 | 
								return [];
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							$statusCode = $response->getStatusCode();
 | 
				
			||||||
 | 
							if ($statusCode != 200) {
 | 
				
			||||||
 | 
								throw new \Exception('Error getting info from plugins repository. Please try again later.');
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							$data = $response->getBody();
 | 
				
			||||||
 | 
							return json_decode($data, true);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						public function setApiBaseUri(string $uri): void {
 | 
				
			||||||
 | 
							$this->api_base_uri = $uri;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -106,7 +106,7 @@ class Cache
 | 
				
			|||||||
	public static function remember($key, $ttl, $callback)
 | 
						public static function remember($key, $ttl, $callback)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		$cache = self::getInstance();
 | 
							$cache = self::getInstance();
 | 
				
			||||||
		if (!$cache->enabled()) {
 | 
							if (!$cache->enabled() || $ttl == 0) {
 | 
				
			||||||
			return $callback();
 | 
								return $callback();
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -115,6 +115,11 @@ class Cache
 | 
				
			|||||||
			return unserialize($value);
 | 
								return unserialize($value);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// -1 for infinite cache
 | 
				
			||||||
 | 
							if ($ttl == -1) {
 | 
				
			||||||
 | 
								$ttl = 10 * 365 * 24 * 60 * 60; // 10 years should be enough
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		$value = $callback();
 | 
							$value = $callback();
 | 
				
			||||||
		$cache->set($key, serialize($value), $ttl);
 | 
							$cache->set($key, serialize($value), $ttl);
 | 
				
			||||||
		return $value;
 | 
							return $value;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,6 +2,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
namespace MyAAC\Commands;
 | 
					namespace MyAAC\Commands;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use MyAAC\Cache\Cache;
 | 
				
			||||||
use MyAAC\Hooks;
 | 
					use MyAAC\Hooks;
 | 
				
			||||||
use Symfony\Component\Console\Input\InputInterface;
 | 
					use Symfony\Component\Console\Input\InputInterface;
 | 
				
			||||||
use Symfony\Component\Console\Output\OutputInterface;
 | 
					use Symfony\Component\Console\Output\OutputInterface;
 | 
				
			||||||
@@ -17,10 +18,7 @@ class CacheClearCommand extends Command
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	protected function execute(InputInterface $input, OutputInterface $output): int
 | 
						protected function execute(InputInterface $input, OutputInterface $output): int
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		global $hooks;
 | 
							require SYSTEM . 'init.php';
 | 
				
			||||||
		$hooks = new Hooks();
 | 
					 | 
				
			||||||
		$hooks->load();
 | 
					 | 
				
			||||||
		$hooks->trigger(HOOK_INIT);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		$io = new SymfonyStyle($input, $output);
 | 
							$io = new SymfonyStyle($input, $output);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -29,6 +27,13 @@ class CacheClearCommand extends Command
 | 
				
			|||||||
			return Command::FAILURE;
 | 
								return Command::FAILURE;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							$cacheEngine = config('cache_engine') == 'auto' ?
 | 
				
			||||||
 | 
								Cache::detect() : config('cache_engine');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (config('env') !== 'dev' && $cacheEngine == 'apcu') {
 | 
				
			||||||
 | 
								$io->warning('APCu cache cannot be cleared in CLI. Please visit the Admin Panel and clear there.');
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		$io->success('Cache cleared');
 | 
							$io->success('Cache cleared');
 | 
				
			||||||
		return Command::SUCCESS;
 | 
							return Command::SUCCESS;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										33
									
								
								system/src/Commands/Env.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								system/src/Commands/Env.php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,33 @@
 | 
				
			|||||||
 | 
					<?php
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace MyAAC\Commands;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use POT;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					trait Env
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						protected function init(): void
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							global $config;
 | 
				
			||||||
 | 
							if (!isset($config['installed']) || !$config['installed']) {
 | 
				
			||||||
 | 
								throw new \RuntimeException('MyAAC has not been installed yet or there was error during installation. Please install again.');
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if(empty($config['server_path'])) {
 | 
				
			||||||
 | 
								throw new \RuntimeException('Server Path has been not set. Go to config.php and set it.');
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// take care of trailing slash at the end
 | 
				
			||||||
 | 
							if($config['server_path'][strlen($config['server_path']) - 1] !== '/')
 | 
				
			||||||
 | 
								$config['server_path'] .= '/';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							$config['lua'] = load_config_lua($config['server_path'] . 'config.lua');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// POT
 | 
				
			||||||
 | 
							require_once SYSTEM . 'libs/pot/OTS.php';
 | 
				
			||||||
 | 
							$ots = POT::getInstance();
 | 
				
			||||||
 | 
							$eloquentConnection = null;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							require_once SYSTEM . 'database.php';
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -12,9 +12,10 @@ class MailSendCommand extends Command
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
	protected function configure(): void
 | 
						protected function configure(): void
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		$this->setName('mail:send')
 | 
							$this->setName('email:send')
 | 
				
			||||||
 | 
								->setAliases(['mail:send'])
 | 
				
			||||||
			->setDescription('This command sends E-Mail to single user. Message can be provided as follows: ' . PHP_EOL
 | 
								->setDescription('This command sends E-Mail to single user. Message can be provided as follows: ' . PHP_EOL
 | 
				
			||||||
				. '  echo "Hello World" | php sa email:send --subject="This is the subject" test@test.com')
 | 
									. '  echo "Hello World" | php aac email:send --subject="This is the subject" test@test.com')
 | 
				
			||||||
			->addArgument('recipient', InputArgument::REQUIRED, 'Email, Account Name, Account id or Player Name')
 | 
								->addArgument('recipient', InputArgument::REQUIRED, 'Email, Account Name, Account id or Player Name')
 | 
				
			||||||
			->addOption('subject', 's', InputOption::VALUE_REQUIRED, 'Subject');
 | 
								->addOption('subject', 's', InputOption::VALUE_REQUIRED, 'Subject');
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -9,6 +9,8 @@ use Symfony\Component\Console\Style\SymfonyStyle;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
class MigrateCommand extends Command
 | 
					class MigrateCommand extends Command
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
						use Env;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	protected function configure(): void
 | 
						protected function configure(): void
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		$this->setName('migrate')
 | 
							$this->setName('migrate')
 | 
				
			||||||
@@ -17,9 +19,19 @@ class MigrateCommand extends Command
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	protected function execute(InputInterface $input, OutputInterface $output): int
 | 
						protected function execute(InputInterface $input, OutputInterface $output): int
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		require SYSTEM . 'init.php';
 | 
							$this->init();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		$io = new SymfonyStyle($input, $output);
 | 
							$io = new SymfonyStyle($input, $output);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							$tmp = '';
 | 
				
			||||||
 | 
							if(fetchDatabaseConfig('database_version', $tmp)) { // we got version
 | 
				
			||||||
 | 
								$tmp = (int)$tmp;
 | 
				
			||||||
 | 
								if ($tmp >= DATABASE_VERSION) {
 | 
				
			||||||
 | 
									$io->success('Already on latest version.');
 | 
				
			||||||
 | 
									return Command::SUCCESS;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		require SYSTEM . 'migrate.php';
 | 
							require SYSTEM . 'migrate.php';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		$io->success('Migrated to latest version (' . DATABASE_VERSION . ')');
 | 
							$io->success('Migrated to latest version (' . DATABASE_VERSION . ')');
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -10,6 +10,8 @@ use Symfony\Component\Console\Style\SymfonyStyle;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
class MigrateRunCommand extends Command
 | 
					class MigrateRunCommand extends Command
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
						use Env;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	protected function configure(): void
 | 
						protected function configure(): void
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		$this->setName('migrate:run')
 | 
							$this->setName('migrate:run')
 | 
				
			||||||
@@ -23,12 +25,12 @@ class MigrateRunCommand extends Command
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	protected function execute(InputInterface $input, OutputInterface $output): int
 | 
						protected function execute(InputInterface $input, OutputInterface $output): int
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		require SYSTEM . 'init.php';
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		$io = new SymfonyStyle($input, $output);
 | 
							$io = new SymfonyStyle($input, $output);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		$ids = $input->getArgument('id');
 | 
							$ids = $input->getArgument('id');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							$this->init();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// pre-check
 | 
							// pre-check
 | 
				
			||||||
		// in case one of the migrations doesn't exist - we won't execute any of them
 | 
							// in case one of the migrations doesn't exist - we won't execute any of them
 | 
				
			||||||
		foreach ($ids as $id) {
 | 
							foreach ($ids as $id) {
 | 
				
			||||||
@@ -45,6 +47,22 @@ class MigrateRunCommand extends Command
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
		$down = $input->getOption('down') ?? false;
 | 
							$down = $input->getOption('down') ?? false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/**
 | 
				
			||||||
 | 
							 * Sort according to $down option.
 | 
				
			||||||
 | 
							 * Do we really want it?
 | 
				
			||||||
 | 
							 * Or should we use order provided by user,
 | 
				
			||||||
 | 
							 *      even when it's not sorted correctly?
 | 
				
			||||||
 | 
							 * Leaving it for consideration.
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
 | 
							/*
 | 
				
			||||||
 | 
							if ($down) {
 | 
				
			||||||
 | 
								rsort($ids);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							else {
 | 
				
			||||||
 | 
								sort($ids);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		foreach ($ids as $id) {
 | 
							foreach ($ids as $id) {
 | 
				
			||||||
			$this->executeMigration($id, $io, !$down);
 | 
								$this->executeMigration($id, $io, !$down);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -11,6 +11,8 @@ use Symfony\Component\Console\Style\SymfonyStyle;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
class MigrateToCommand extends Command
 | 
					class MigrateToCommand extends Command
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
						use Env;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	protected function configure(): void
 | 
						protected function configure(): void
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		$this->setName('migrate:to')
 | 
							$this->setName('migrate:to')
 | 
				
			||||||
@@ -32,7 +34,7 @@ class MigrateToCommand extends Command
 | 
				
			|||||||
			return Command::FAILURE;
 | 
								return Command::FAILURE;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		$this->initEnv();
 | 
							$this->init();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		$currentVersion = Config::where('name', 'database_version')->first()->value;
 | 
							$currentVersion = Config::where('name', 'database_version')->first()->value;
 | 
				
			||||||
		if ($currentVersion > $versionDest) {
 | 
							if ($currentVersion > $versionDest) {
 | 
				
			||||||
@@ -80,29 +82,4 @@ class MigrateToCommand extends Command
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
		updateDatabaseConfig('database_version', ($_up ? $id : $id - 1));
 | 
							updateDatabaseConfig('database_version', ($_up ? $id : $id - 1));
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					 | 
				
			||||||
	private function initEnv()
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		global $config;
 | 
					 | 
				
			||||||
		if (!isset($config['installed']) || !$config['installed']) {
 | 
					 | 
				
			||||||
			throw new \RuntimeException('MyAAC has not been installed yet or there was error during installation. Please install again.');
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		if(empty($config['server_path'])) {
 | 
					 | 
				
			||||||
			throw new \RuntimeException('Server Path has been not set. Go to config.php and set it.');
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		// take care of trailing slash at the end
 | 
					 | 
				
			||||||
		if($config['server_path'][strlen($config['server_path']) - 1] !== '/')
 | 
					 | 
				
			||||||
			$config['server_path'] .= '/';
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		$config['lua'] = load_config_lua($config['server_path'] . 'config.lua');
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		// POT
 | 
					 | 
				
			||||||
		require_once SYSTEM . 'libs/pot/OTS.php';
 | 
					 | 
				
			||||||
		$ots = POT::getInstance();
 | 
					 | 
				
			||||||
		$eloquentConnection = null;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		require_once SYSTEM . 'database.php';
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										36
									
								
								system/src/Commands/PluginDisableCommand.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								system/src/Commands/PluginDisableCommand.php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,36 @@
 | 
				
			|||||||
 | 
					<?php
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace MyAAC\Commands;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use MyAAC\Plugins;
 | 
				
			||||||
 | 
					use Symfony\Component\Console\Input\InputArgument;
 | 
				
			||||||
 | 
					use Symfony\Component\Console\Input\InputInterface;
 | 
				
			||||||
 | 
					use Symfony\Component\Console\Output\OutputInterface;
 | 
				
			||||||
 | 
					use Symfony\Component\Console\Style\SymfonyStyle;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class PluginDisableCommand extends Command
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						protected function configure(): void
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							$this->setName('plugin:disable')
 | 
				
			||||||
 | 
								->setDescription('This command disables plugin')
 | 
				
			||||||
 | 
								->addArgument('plugin-name', InputArgument::REQUIRED, 'Plugin that you want to disable');
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						protected function execute(InputInterface $input, OutputInterface $output): int
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							require SYSTEM . 'init.php';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							$io = new SymfonyStyle($input, $output);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							$pluginName = $input->getArgument('plugin-name');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (!Plugins::disable($pluginName)) {
 | 
				
			||||||
 | 
								$io->error('Error while disabling plugin ' . $pluginName . ': ' . Plugins::getError());
 | 
				
			||||||
 | 
								return 2;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							$io->success('Successfully disabled plugin ' . $pluginName);
 | 
				
			||||||
 | 
							return Command::SUCCESS;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										36
									
								
								system/src/Commands/PluginEnableCommand.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								system/src/Commands/PluginEnableCommand.php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,36 @@
 | 
				
			|||||||
 | 
					<?php
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace MyAAC\Commands;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use MyAAC\Plugins;
 | 
				
			||||||
 | 
					use Symfony\Component\Console\Input\InputArgument;
 | 
				
			||||||
 | 
					use Symfony\Component\Console\Input\InputInterface;
 | 
				
			||||||
 | 
					use Symfony\Component\Console\Output\OutputInterface;
 | 
				
			||||||
 | 
					use Symfony\Component\Console\Style\SymfonyStyle;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class PluginEnableCommand extends Command
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						protected function configure(): void
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							$this->setName('plugin:enable')
 | 
				
			||||||
 | 
								->setDescription('This command enables plugin')
 | 
				
			||||||
 | 
								->addArgument('plugin-name', InputArgument::REQUIRED, 'Plugin that you want to enable');
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						protected function execute(InputInterface $input, OutputInterface $output): int
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							require SYSTEM . 'init.php';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							$io = new SymfonyStyle($input, $output);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							$pluginName = $input->getArgument('plugin-name');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (!Plugins::enable($pluginName)) {
 | 
				
			||||||
 | 
								$io->error('Error while enabling plugin ' . $pluginName . ': ' . Plugins::getError());
 | 
				
			||||||
 | 
								return 2;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							$io->success('Successfully enabled plugin ' . $pluginName);
 | 
				
			||||||
 | 
							return Command::SUCCESS;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -8,11 +8,12 @@ use Symfony\Component\Console\Input\InputInterface;
 | 
				
			|||||||
use Symfony\Component\Console\Output\OutputInterface;
 | 
					use Symfony\Component\Console\Output\OutputInterface;
 | 
				
			||||||
use Symfony\Component\Console\Style\SymfonyStyle;
 | 
					use Symfony\Component\Console\Style\SymfonyStyle;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class PluginInstallInstallCommand extends Command
 | 
					class PluginSetupCommand extends Command
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	protected function configure(): void
 | 
						protected function configure(): void
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		$this->setName('plugin:install:install')
 | 
							$this->setName('plugin:setup')
 | 
				
			||||||
 | 
								->setAliases(['plugin:install:install'])
 | 
				
			||||||
			->setDescription('This command executes the "install" part of the plugin')
 | 
								->setDescription('This command executes the "install" part of the plugin')
 | 
				
			||||||
			->addArgument('plugin', InputArgument::REQUIRED, 'Plugin name');
 | 
								->addArgument('plugin', InputArgument::REQUIRED, 'Plugin name');
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
							
								
								
									
										40
									
								
								system/src/Commands/PluginUninstallCommand.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								system/src/Commands/PluginUninstallCommand.php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,40 @@
 | 
				
			|||||||
 | 
					<?php
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace MyAAC\Commands;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use MyAAC\Plugins;
 | 
				
			||||||
 | 
					use Symfony\Component\Console\Input\InputArgument;
 | 
				
			||||||
 | 
					use Symfony\Component\Console\Input\InputInterface;
 | 
				
			||||||
 | 
					use Symfony\Component\Console\Output\OutputInterface;
 | 
				
			||||||
 | 
					use Symfony\Component\Console\Style\SymfonyStyle;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class PluginUninstallCommand extends Command
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						protected function configure(): void
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							$this->setName('plugin:uninstall')
 | 
				
			||||||
 | 
								->setDescription('This command uninstalls plugin')
 | 
				
			||||||
 | 
								->addArgument('plugin-name', InputArgument::REQUIRED, 'Plugin that you want to uninstall');
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						protected function execute(InputInterface $input, OutputInterface $output): int
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							require SYSTEM . 'init.php';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							$io = new SymfonyStyle($input, $output);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							$pluginName = $input->getArgument('plugin-name');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (!Plugins::uninstall($pluginName)) {
 | 
				
			||||||
 | 
								$io->error('Error while uninstalling plugin ' . $pluginName . ': ' . Plugins::getError());
 | 
				
			||||||
 | 
								return 2;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							foreach(Plugins::getWarnings() as $warning) {
 | 
				
			||||||
 | 
								$io->warning($warning);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							$io->success('Successfully uninstalled plugin ' . $pluginName);
 | 
				
			||||||
 | 
							return Command::SUCCESS;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -3,6 +3,7 @@
 | 
				
			|||||||
namespace MyAAC\Commands;
 | 
					namespace MyAAC\Commands;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use MyAAC\Models\Settings as SettingsModel;
 | 
					use MyAAC\Models\Settings as SettingsModel;
 | 
				
			||||||
 | 
					use MyAAC\Plugins;
 | 
				
			||||||
use MyAAC\Settings;
 | 
					use MyAAC\Settings;
 | 
				
			||||||
use Symfony\Component\Console\Input\InputArgument;
 | 
					use Symfony\Component\Console\Input\InputArgument;
 | 
				
			||||||
use Symfony\Component\Console\Input\InputInterface;
 | 
					use Symfony\Component\Console\Input\InputInterface;
 | 
				
			||||||
@@ -34,7 +35,14 @@ class SettingsResetCommand extends Command
 | 
				
			|||||||
			return Command::FAILURE;
 | 
								return Command::FAILURE;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (!$name) {
 | 
							// find by plugin name
 | 
				
			||||||
 | 
							foreach (Plugins::getAllPluginsSettings() as $key => $setting) {
 | 
				
			||||||
 | 
								if ($setting['pluginFilename'] === $name) {
 | 
				
			||||||
 | 
									$name = $key;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (empty($name)) {
 | 
				
			||||||
			SettingsModel::truncate();
 | 
								SettingsModel::truncate();
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		else {
 | 
							else {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -3,6 +3,7 @@
 | 
				
			|||||||
namespace MyAAC\Commands;
 | 
					namespace MyAAC\Commands;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use MyAAC\Models\Settings as SettingsModel;
 | 
					use MyAAC\Models\Settings as SettingsModel;
 | 
				
			||||||
 | 
					use MyAAC\Plugins;
 | 
				
			||||||
use MyAAC\Settings;
 | 
					use MyAAC\Settings;
 | 
				
			||||||
use Symfony\Component\Console\Input\InputArgument;
 | 
					use Symfony\Component\Console\Input\InputArgument;
 | 
				
			||||||
use Symfony\Component\Console\Input\InputInterface;
 | 
					use Symfony\Component\Console\Input\InputInterface;
 | 
				
			||||||
@@ -17,7 +18,7 @@ class SettingsSetCommand extends Command
 | 
				
			|||||||
			->setDescription('Updates the setting specified by argument in database')
 | 
								->setDescription('Updates the setting specified by argument in database')
 | 
				
			||||||
			->addArgument('key',
 | 
								->addArgument('key',
 | 
				
			||||||
				InputArgument::REQUIRED,
 | 
									InputArgument::REQUIRED,
 | 
				
			||||||
				'Setting name/key'
 | 
									'Setting key in format name.key'
 | 
				
			||||||
			)
 | 
								)
 | 
				
			||||||
			->addArgument('value',
 | 
								->addArgument('value',
 | 
				
			||||||
				InputArgument::REQUIRED,
 | 
									InputArgument::REQUIRED,
 | 
				
			||||||
@@ -34,6 +35,18 @@ class SettingsSetCommand extends Command
 | 
				
			|||||||
		$key = $input->getArgument('key');
 | 
							$key = $input->getArgument('key');
 | 
				
			||||||
		$value = $input->getArgument('value');
 | 
							$value = $input->getArgument('value');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// format settings_name.key
 | 
				
			||||||
 | 
							// example: core.template
 | 
				
			||||||
 | 
							$explode = explode('.', $key);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// find by plugin name
 | 
				
			||||||
 | 
							foreach (Plugins::getAllPluginsSettings() as $_key => $setting) {
 | 
				
			||||||
 | 
								if ($setting['pluginFilename'] === $explode[0]) {
 | 
				
			||||||
 | 
									$explode[0] = $_key;
 | 
				
			||||||
 | 
									$key = implode('.', $explode);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		$settings = Settings::getInstance();
 | 
							$settings = Settings::getInstance();
 | 
				
			||||||
		$settings->clearCache();
 | 
							$settings->clearCache();
 | 
				
			||||||
		$settings->load();
 | 
							$settings->load();
 | 
				
			||||||
@@ -44,10 +57,6 @@ class SettingsSetCommand extends Command
 | 
				
			|||||||
			return Command::FAILURE;
 | 
								return Command::FAILURE;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// format plugin_name.key
 | 
					 | 
				
			||||||
		// example: core.template
 | 
					 | 
				
			||||||
		$explode = explode('.', $key);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		$settings->updateInDatabase($explode[0], $explode[1], $value);
 | 
							$settings->updateInDatabase($explode[0], $explode[1], $value);
 | 
				
			||||||
		$settings->clearCache();
 | 
							$settings->clearCache();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -76,10 +76,11 @@ class Items
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	public static function get($id) {
 | 
						public static function get($id) {
 | 
				
			||||||
		self::load();
 | 
							self::load();
 | 
				
			||||||
		return isset(self::$items[$id]) ? self::$items[$id] : [];
 | 
							return self::$items[$id] ?? [];
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	public static function getDescription($id, $count = 1) {
 | 
						public static function getDescription($id, $count = 1): string
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
		$item = self::get($id);
 | 
							$item = self::get($id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		$attr = $item['attributes'];
 | 
							$attr = $item['attributes'];
 | 
				
			||||||
@@ -112,15 +113,15 @@ class Items
 | 
				
			|||||||
			$s .= 'an item of type ' . $item['id'];
 | 
								$s .= 'an item of type ' . $item['id'];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if(isset($attr['type']) && strtolower($attr['type']) == 'rune') {
 | 
							if(isset($attr['type']) && strtolower($attr['type']) == 'rune') {
 | 
				
			||||||
			$item = Spell::where('item_id', $id)->first();
 | 
								$spell = Spell::where('item_id', $id)->first();
 | 
				
			||||||
			if($item) {
 | 
								if($spell) {
 | 
				
			||||||
				if($item->level > 0 && $item->maglevel > 0) {
 | 
									if($spell->level > 0 && $spell->maglevel > 0) {
 | 
				
			||||||
					$s .= '. ' . ($count > 1 ? "They" : "It") . ' can only be used by ';
 | 
										$s .= '. ' . ($count > 1 ? 'They' : 'It') . ' can only be used by ';
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				$configVocations = config('vocations');
 | 
									$configVocations = config('vocations');
 | 
				
			||||||
				if(!empty(trim($item->vocations))) {
 | 
									if(!empty(trim($spell->vocations))) {
 | 
				
			||||||
					$vocations = json_decode($item->vocations);
 | 
										$vocations = json_decode($spell->vocations);
 | 
				
			||||||
					if(count($vocations) > 0) {
 | 
										if(count($vocations) > 0) {
 | 
				
			||||||
						foreach($vocations as $voc => $show) {
 | 
											foreach($vocations as $voc => $show) {
 | 
				
			||||||
							$vocations[$configVocations[$voc]] = $show;
 | 
												$vocations[$configVocations[$voc]] = $show;
 | 
				
			||||||
@@ -133,8 +134,39 @@ class Items
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
				$s .= ' with';
 | 
									$s .= ' with';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									if ($spell->level > 0) {
 | 
				
			||||||
 | 
										$s .= ' level ' . $spell->level;
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									if ($spell->maglevel > 0) {
 | 
				
			||||||
 | 
										if ($spell->level > 0) {
 | 
				
			||||||
 | 
											$s .= ' and';
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										$s .= ' magic level ' . $spell->maglevel;
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									$s .= ' or higher';
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (!empty($item['weaponType'])) {
 | 
				
			||||||
 | 
								if ($item['weaponType'] == 'distance' && isset($item['ammoType'])) {
 | 
				
			||||||
 | 
									$s .= ' (Range:' . $item['range'];
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if (isset($item['attack']) && $item['attack'] != 0) {
 | 
				
			||||||
 | 
									$s .= ', Atk ' . ($item['attack'] > 0 ? '+' . $item['attack'] : '-' . $item['attack']);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if (isset($item['hitChance']) && $item['hitChance'] != -1) {
 | 
				
			||||||
 | 
									$s .= ', Hit% ' . ($item['hitChance'] > 0 ? '+' . $item['hitChance'] : '-' . $item['hitChance']);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								elseif ($item['weaponType'] != 'ammo') {
 | 
				
			||||||
 | 
									
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		return $s;
 | 
							return $s;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -5,11 +5,15 @@ namespace MyAAC\Models;
 | 
				
			|||||||
use Illuminate\Database\Eloquent\Model;
 | 
					use Illuminate\Database\Eloquent\Model;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 | 
					 * @property integer $premium_ends_at
 | 
				
			||||||
 | 
					 * @property integer $premend
 | 
				
			||||||
 * @property integer $lastday
 | 
					 * @property integer $lastday
 | 
				
			||||||
 * @property integer $premdays
 | 
					 * @property integer $premdays
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
class Account extends Model {
 | 
					class Account extends Model {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						const GRATIS_PREMIUM_DAYS = 65535;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	protected $table = 'accounts';
 | 
						protected $table = 'accounts';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	public $timestamps = false;
 | 
						public $timestamps = false;
 | 
				
			||||||
@@ -33,35 +37,35 @@ class Account extends Model {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	public function getPremiumDaysAttribute()
 | 
						public function getPremiumDaysAttribute()
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		if(isset($this->premium_ends_at) || isset($this->premend)) {
 | 
							if(isset($this->premium_ends_at) || isset($this->premend) ||
 | 
				
			||||||
			$col = isset($this->premium_ends_at) ? 'premium_ends_at' : 'premend';
 | 
								(isCanary() && isset($this->lastday))) {
 | 
				
			||||||
 | 
									$col = (isset($this->premium_ends_at) ? 'premium_ends_at' : (isset($this->lastday) ? 'lastday' : 'premend'));
 | 
				
			||||||
				$ret = ceil(($this->{$col} - time()) / (24 * 60 * 60));
 | 
									$ret = ceil(($this->{$col} - time()) / (24 * 60 * 60));
 | 
				
			||||||
			return $ret > 0 ? $ret : 0;
 | 
									return max($ret, 0);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if($this->premdays == 0) {
 | 
							if($this->premdays == 0) {
 | 
				
			||||||
			return 0;
 | 
								return 0;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if($this->premdays == 65535){
 | 
							if($this->premdays == self::GRATIS_PREMIUM_DAYS){
 | 
				
			||||||
			return 65535;
 | 
								return self::GRATIS_PREMIUM_DAYS;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		$ret = ceil($this->premdays - ((int)date("z", time()) + (365 * (date("Y", time()) - date("Y", $this->lastday))) - date("z", $this->lastday)));
 | 
							$ret = ceil($this->premdays - ((int)date("z", time()) + (365 * (date("Y", time()) - date("Y", $this->lastday))) - date("z", $this->lastday)));
 | 
				
			||||||
		return max($ret, 0);
 | 
							return max($ret, 0);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	public function getIsPremiumAttribute()
 | 
						public function getIsPremiumAttribute(): bool
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		global $config;
 | 
							if(isset($this->premium_ends_at) || isset($this->premend) ||
 | 
				
			||||||
        if(isset($config['lua']['freePremium']) && getBoolean($config['lua']['freePremium'])) return true;
 | 
								(isCanary() && isset($this->lastday))) {
 | 
				
			||||||
 | 
								$col = (isset($this->premium_ends_at) ? 'premium_ends_at' : (isset($this->lastday) ? 'lastday' : 'premend'));
 | 
				
			||||||
	    if(isset($this->premium_ends_at)) {
 | 
								return $this->{$col} > time();
 | 
				
			||||||
		    return $this->premium_ends_at > time();
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if(isset($this->premend)) {
 | 
							if($this->premdays == self::GRATIS_PREMIUM_DAYS){
 | 
				
			||||||
			return $this->premend > time();
 | 
								return true;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		return ($this->premdays - (date("z", time()) + (365 * (date("Y", time()) - date("Y", $this->lastday))) - date("z", $this->lastday)) > 0);
 | 
							return ($this->premdays - (date("z", time()) + (365 * (date("Y", time()) - date("Y", $this->lastday))) - date("z", $this->lastday)) > 0);
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										15
									
								
								system/src/Models/AccountEmailVerify.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								system/src/Models/AccountEmailVerify.php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,15 @@
 | 
				
			|||||||
 | 
					<?php
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace MyAAC\Models;
 | 
				
			||||||
 | 
					use Illuminate\Database\Eloquent\Model;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class AccountEmailVerify extends Model
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						protected $table = TABLE_PREFIX . 'account_emails_verify';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						public $timestamps = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						protected $fillable = ['account_id', 'hash', 'sent_at'];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -18,7 +18,16 @@ class Changelog extends Model {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	public $timestamps = false;
 | 
						public $timestamps = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						protected $fillable = [
 | 
				
			||||||
 | 
							'body', 'type', 'where',
 | 
				
			||||||
 | 
							'date', 'player_id', 'hide',
 | 
				
			||||||
 | 
						];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	public function scopeIsPublic($query) {
 | 
						public function scopeIsPublic($query) {
 | 
				
			||||||
		$query->where('hide', '!=', 1);
 | 
							$query->where('hide', '!=', 1);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						public function player() {
 | 
				
			||||||
 | 
							return $this->belongsTo(Player::class);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										16
									
								
								system/src/Models/ForumBoard.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								system/src/Models/ForumBoard.php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,16 @@
 | 
				
			|||||||
 | 
					<?php
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace MyAAC\Models;
 | 
				
			||||||
 | 
					use Illuminate\Database\Eloquent\Model;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class ForumBoard extends Model {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						protected $table = TABLE_PREFIX . 'forum_boards';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						public $timestamps = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						protected $fillable = [
 | 
				
			||||||
 | 
							'name', 'description', 'ordering',
 | 
				
			||||||
 | 
							'guild', 'access', 'closed', 'hide',
 | 
				
			||||||
 | 
						];
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -10,4 +10,9 @@ class Gallery extends Model {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	public $timestamps = false;
 | 
						public $timestamps = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						protected $fillable = [
 | 
				
			||||||
 | 
							'comment', 'image', 'thumb',
 | 
				
			||||||
 | 
							'author', 'ordering', 'hide',
 | 
				
			||||||
 | 
						];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										15
									
								
								system/src/Models/NewsCategory.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								system/src/Models/NewsCategory.php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,15 @@
 | 
				
			|||||||
 | 
					<?php
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace MyAAC\Models;
 | 
				
			||||||
 | 
					use Illuminate\Database\Eloquent\Model;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class NewsCategory extends Model {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						protected $table = TABLE_PREFIX . 'news_categories';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						public $timestamps = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						protected $fillable = [
 | 
				
			||||||
 | 
							'name', 'description', 'icon_id', 'hide'
 | 
				
			||||||
 | 
						];
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -9,6 +9,10 @@ class PlayerOnline extends Model {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	public $timestamps = false;
 | 
						public $timestamps = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						protected $fillable = [
 | 
				
			||||||
 | 
							'player_id',
 | 
				
			||||||
 | 
						];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	public function player()
 | 
						public function player()
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		return $this->belongsTo(Player::class);
 | 
							return $this->belongsTo(Player::class);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -532,8 +532,9 @@ class Plugins {
 | 
				
			|||||||
		self::$plugin_json = $plugin_json;
 | 
							self::$plugin_json = $plugin_json;
 | 
				
			||||||
		if ($plugin_json == null) {
 | 
							if ($plugin_json == null) {
 | 
				
			||||||
			self::$warnings[] = 'Cannot load ' . $file_name . '. File might be not a valid json code.';
 | 
								self::$warnings[] = 'Cannot load ' . $file_name . '. File might be not a valid json code.';
 | 
				
			||||||
 | 
								return false;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		else {
 | 
					
 | 
				
			||||||
		$continue = true;
 | 
							$continue = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if(!isset($plugin_json['name']) || empty(trim($plugin_json['name']))) {
 | 
							if(!isset($plugin_json['name']) || empty(trim($plugin_json['name']))) {
 | 
				
			||||||
@@ -689,7 +690,10 @@ class Plugins {
 | 
				
			|||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if($continue) {
 | 
							if(!$continue) {
 | 
				
			||||||
 | 
								return false;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if(!$zip->extractTo(BASE)) { // "Real" Install
 | 
							if(!$zip->extractTo(BASE)) { // "Real" Install
 | 
				
			||||||
			self::$error = 'There was a problem with extracting zip archive to base directory.';
 | 
								self::$error = 'There was a problem with extracting zip archive to base directory.';
 | 
				
			||||||
			$zip->close();
 | 
								$zip->close();
 | 
				
			||||||
@@ -713,13 +717,8 @@ class Plugins {
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		clearCache();
 | 
							clearCache();
 | 
				
			||||||
 | 
					 | 
				
			||||||
		return true;
 | 
							return true;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		return false;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	public static function isEnabled($pluginFileName): bool
 | 
						public static function isEnabled($pluginFileName): bool
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
@@ -781,15 +780,20 @@ class Plugins {
 | 
				
			|||||||
			return false;
 | 
								return false;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if(!isset($plugin_json['install'])) {
 | 
							$install = $plugin_json['install'] ?? '';
 | 
				
			||||||
			self::$error = "Plugin doesn't have install options defined. Skipping...";
 | 
							if (self::getAutoLoadOption($plugin_json, 'install', true) && is_file(PLUGINS . $plugin_name . '/install.php')) {
 | 
				
			||||||
 | 
								$install = 'plugins/' . $plugin_name . '/install.php';
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (empty($install)) {
 | 
				
			||||||
 | 
								self::$error = "This plugin doesn't seem to have install script defined.";
 | 
				
			||||||
			return false;
 | 
								return false;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		global $db;
 | 
							global $db;
 | 
				
			||||||
		if (file_exists(BASE . $plugin_json['install'])) {
 | 
							if (file_exists(BASE . $install)) {
 | 
				
			||||||
			$db->revalidateCache();
 | 
								$db->revalidateCache();
 | 
				
			||||||
			require BASE . $plugin_json['install'];
 | 
								require BASE . $install;
 | 
				
			||||||
			$db->revalidateCache();
 | 
								$db->revalidateCache();
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		else {
 | 
							else {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -7,16 +7,13 @@ use MyAAC\Models\Settings as ModelsSettings;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
class Settings implements \ArrayAccess
 | 
					class Settings implements \ArrayAccess
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	static private $instance;
 | 
						static private ?Settings $instance = null;
 | 
				
			||||||
	private $settingsFile = [];
 | 
						private array $settingsFile = [];
 | 
				
			||||||
	private $settingsDatabase = [];
 | 
						private array $settingsDatabase = [];
 | 
				
			||||||
	private $cache = [];
 | 
						private array $cache = [];
 | 
				
			||||||
	private $valuesAsked = [];
 | 
						private array $valuesAsked = [];
 | 
				
			||||||
	private $errors = [];
 | 
						private array $errors = [];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/**
 | 
					 | 
				
			||||||
	 * @return Settings
 | 
					 | 
				
			||||||
	 */
 | 
					 | 
				
			||||||
	public static function getInstance(): Settings
 | 
						public static function getInstance(): Settings
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		if (!self::$instance) {
 | 
							if (!self::$instance) {
 | 
				
			||||||
@@ -26,28 +23,21 @@ class Settings implements \ArrayAccess
 | 
				
			|||||||
		return self::$instance;
 | 
							return self::$instance;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	public function load()
 | 
						public function load(): void
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		$cache = Cache::getInstance();
 | 
							$this->settingsDatabase = Cache::remember('settings', 10 * 60, function () {
 | 
				
			||||||
		if ($cache->enabled()) {
 | 
								$settingsDatabase = [];
 | 
				
			||||||
			$tmp = '';
 | 
					 | 
				
			||||||
			if ($cache->fetch('settings', $tmp)) {
 | 
					 | 
				
			||||||
				$this->settingsDatabase = unserialize($tmp);
 | 
					 | 
				
			||||||
				return;
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
			$settings = ModelsSettings::all();
 | 
								$settings = ModelsSettings::all();
 | 
				
			||||||
			foreach ($settings as $setting) {
 | 
								foreach ($settings as $setting) {
 | 
				
			||||||
			$this->settingsDatabase[$setting->name][$setting->key] = $setting->value;
 | 
									$settingsDatabase[$setting->name][$setting->key] = $setting->value;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if ($cache->enabled()) {
 | 
								return $settingsDatabase;
 | 
				
			||||||
			$cache->set('settings', serialize($this->settingsDatabase), 600);
 | 
							});
 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	public function save($pluginName, $values)
 | 
						public function save($pluginName, $values): bool
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		$this->loadPlugin($pluginName);
 | 
							$this->loadPlugin($pluginName);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -104,7 +94,7 @@ class Settings implements \ArrayAccess
 | 
				
			|||||||
		return true;
 | 
							return true;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	public function updateInDatabase($pluginName, $key, $value)
 | 
						public function updateInDatabase($pluginName, $key, $value): void
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		if (ModelsSettings::where(['name' => $pluginName, 'key' => $key])->exists()) {
 | 
							if (ModelsSettings::where(['name' => $pluginName, 'key' => $key])->exists()) {
 | 
				
			||||||
			ModelsSettings::where(['name' => $pluginName, 'key' => $key])->update(['value' => $value]);
 | 
								ModelsSettings::where(['name' => $pluginName, 'key' => $key])->update(['value' => $value]);
 | 
				
			||||||
@@ -117,7 +107,7 @@ class Settings implements \ArrayAccess
 | 
				
			|||||||
		$this->clearCache();
 | 
							$this->clearCache();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	public function deleteFromDatabase($pluginName, $key = null)
 | 
						public function deleteFromDatabase($pluginName, $key = null): void
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		if (!isset($key)) {
 | 
							if (!isset($key)) {
 | 
				
			||||||
			ModelsSettings::where('name', $pluginName)->delete();
 | 
								ModelsSettings::where('name', $pluginName)->delete();
 | 
				
			||||||
@@ -217,7 +207,7 @@ class Settings implements \ArrayAccess
 | 
				
			|||||||
				if (isset($setting['hidden']) && $setting['hidden']) {
 | 
									if (isset($setting['hidden']) && $setting['hidden']) {
 | 
				
			||||||
					$value = '';
 | 
										$value = '';
 | 
				
			||||||
					if ($setting['type'] === 'boolean') {
 | 
										if ($setting['type'] === 'boolean') {
 | 
				
			||||||
						$value = ($setting['default'] ? 'true' : 'false');
 | 
											$value = (getBoolean($setting['default']) ? 'true' : 'false');
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
					else if (in_array($setting['type'], ['text', 'number', 'float', 'double', 'email', 'password', 'textarea'])) {
 | 
										else if (in_array($setting['type'], ['text', 'number', 'float', 'double', 'email', 'password', 'textarea'])) {
 | 
				
			||||||
						$value = $setting['default'];
 | 
											$value = $setting['default'];
 | 
				
			||||||
@@ -230,12 +220,7 @@ class Settings implements \ArrayAccess
 | 
				
			|||||||
				}
 | 
									}
 | 
				
			||||||
				else if ($setting['type'] === 'boolean') {
 | 
									else if ($setting['type'] === 'boolean') {
 | 
				
			||||||
					if(isset($settingsDb[$key])) {
 | 
										if(isset($settingsDb[$key])) {
 | 
				
			||||||
						if($settingsDb[$key] === 'true') {
 | 
											$value = getBoolean($settingsDb[$key]);
 | 
				
			||||||
							$value = true;
 | 
					 | 
				
			||||||
						}
 | 
					 | 
				
			||||||
						else {
 | 
					 | 
				
			||||||
							$value = false;
 | 
					 | 
				
			||||||
						}
 | 
					 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
					else {
 | 
										else {
 | 
				
			||||||
						$value = ($setting['default'] ?? false);
 | 
											$value = ($setting['default'] ?? false);
 | 
				
			||||||
@@ -383,7 +368,7 @@ class Settings implements \ArrayAccess
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	#[\ReturnTypeWillChange]
 | 
						#[\ReturnTypeWillChange]
 | 
				
			||||||
	public function offsetSet($offset, $value)
 | 
						public function offsetSet($offset, $value): void
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		if (is_null($offset)) {
 | 
							if (is_null($offset)) {
 | 
				
			||||||
			throw new \RuntimeException("Settings: You cannot set empty offset with value: $value!");
 | 
								throw new \RuntimeException("Settings: You cannot set empty offset with value: $value!");
 | 
				
			||||||
@@ -423,7 +408,7 @@ class Settings implements \ArrayAccess
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	#[\ReturnTypeWillChange]
 | 
						#[\ReturnTypeWillChange]
 | 
				
			||||||
	public function offsetUnset($offset)
 | 
						public function offsetUnset($offset): void
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		$this->loadPlugin($offset);
 | 
							$this->loadPlugin($offset);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -455,7 +440,7 @@ class Settings implements \ArrayAccess
 | 
				
			|||||||
	 * @return array|mixed
 | 
						 * @return array|mixed
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	#[\ReturnTypeWillChange]
 | 
						#[\ReturnTypeWillChange]
 | 
				
			||||||
	public function offsetGet($offset)
 | 
						public function offsetGet($offset): mixed
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		// try cache hit
 | 
							// try cache hit
 | 
				
			||||||
		if(isset($this->cache[$offset])) {
 | 
							if(isset($this->cache[$offset])) {
 | 
				
			||||||
@@ -472,24 +457,22 @@ class Settings implements \ArrayAccess
 | 
				
			|||||||
			if (!isset($this->settingsFile[$pluginKeyName]['settings'])) {
 | 
								if (!isset($this->settingsFile[$pluginKeyName]['settings'])) {
 | 
				
			||||||
				throw new \RuntimeException('Unknown plugin settings: ' . $pluginKeyName);
 | 
									throw new \RuntimeException('Unknown plugin settings: ' . $pluginKeyName);
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			return $this->settingsFile[$pluginKeyName]['settings'];
 | 
								return $this->settingsFile[$pluginKeyName]['settings'];
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		$ret = [];
 | 
							if (!isset($this->settingsFile[$pluginKeyName]['settings'][$key])) {
 | 
				
			||||||
		if(isset($this->settingsFile[$pluginKeyName]['settings'][$key])) {
 | 
								return null;
 | 
				
			||||||
			$ret = $this->settingsFile[$pluginKeyName]['settings'][$key];
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							$ret = $this->settingsFile[$pluginKeyName]['settings'][$key];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if(isset($this->settingsDatabase[$pluginKeyName][$key])) {
 | 
							if(isset($this->settingsDatabase[$pluginKeyName][$key])) {
 | 
				
			||||||
			$value = $this->settingsDatabase[$pluginKeyName][$key];
 | 
								$value = $this->settingsDatabase[$pluginKeyName][$key];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			$ret['value'] = $value;
 | 
								$ret['value'] = $value;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		else {
 | 
							else {
 | 
				
			||||||
			if (!isset($this->settingsFile[$pluginKeyName]['settings'][$key])) {
 | 
					 | 
				
			||||||
				return null;
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			$ret['value'] = $this->settingsFile[$pluginKeyName]['settings'][$key]['default'];
 | 
								$ret['value'] = $this->settingsFile[$pluginKeyName]['settings'][$key]['default'];
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -523,7 +506,7 @@ class Settings implements \ArrayAccess
 | 
				
			|||||||
		return $ret;
 | 
							return $ret;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	private function updateValuesAsked($offset)
 | 
						private function updateValuesAsked($offset): void
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		$pluginKeyName = $offset;
 | 
							$pluginKeyName = $offset;
 | 
				
			||||||
		if (strpos($offset, '.')) {
 | 
							if (strpos($offset, '.')) {
 | 
				
			||||||
@@ -539,7 +522,7 @@ class Settings implements \ArrayAccess
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	private function loadPlugin($offset)
 | 
						private function loadPlugin($offset): void
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		$this->updateValuesAsked($offset);
 | 
							$this->updateValuesAsked($offset);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -568,7 +551,7 @@ class Settings implements \ArrayAccess
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	public static function saveConfig($config, $filename, &$content = '')
 | 
						public static function saveConfig($config, $filename, &$content = ''): bool|int
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		$content = "<?php" . PHP_EOL;
 | 
							$content = "<?php" . PHP_EOL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -28,6 +28,8 @@ define('HOOK_CHARACTERS_AFTER_CHARACTERS', ++$i);
 | 
				
			|||||||
define('HOOK_LOGIN', ++$i);
 | 
					define('HOOK_LOGIN', ++$i);
 | 
				
			||||||
define('HOOK_LOGIN_ATTEMPT', ++$i);
 | 
					define('HOOK_LOGIN_ATTEMPT', ++$i);
 | 
				
			||||||
define('HOOK_LOGOUT', ++$i);
 | 
					define('HOOK_LOGOUT', ++$i);
 | 
				
			||||||
 | 
					define('HOOK_ACCOUNT_CHANGE_PASSWORD_AFTER_OLD_PASSWORD', ++$i);
 | 
				
			||||||
 | 
					define('HOOK_ACCOUNT_CHANGE_PASSWORD_AFTER_NEW_PASSWORD', ++$i);
 | 
				
			||||||
define('HOOK_ACCOUNT_CHANGE_PASSWORD_POST', ++$i);
 | 
					define('HOOK_ACCOUNT_CHANGE_PASSWORD_POST', ++$i);
 | 
				
			||||||
define('HOOK_ACCOUNT_CREATE_BEFORE_FORM', ++$i);
 | 
					define('HOOK_ACCOUNT_CREATE_BEFORE_FORM', ++$i);
 | 
				
			||||||
define('HOOK_ACCOUNT_CREATE_BEFORE_BOXES', ++$i);
 | 
					define('HOOK_ACCOUNT_CREATE_BEFORE_BOXES', ++$i);
 | 
				
			||||||
@@ -54,6 +56,7 @@ define('HOOK_ACCOUNT_MANAGE_BEFORE_GENERAL_INFORMATION', ++$i);
 | 
				
			|||||||
define('HOOK_ACCOUNT_MANAGE_BEFORE_PUBLIC_INFORMATION', ++$i);
 | 
					define('HOOK_ACCOUNT_MANAGE_BEFORE_PUBLIC_INFORMATION', ++$i);
 | 
				
			||||||
define('HOOK_ACCOUNT_MANAGE_BEFORE_ACCOUNT_LOGS', ++$i);
 | 
					define('HOOK_ACCOUNT_MANAGE_BEFORE_ACCOUNT_LOGS', ++$i);
 | 
				
			||||||
define('HOOK_ACCOUNT_MANAGE_BEFORE_CHARACTERS', ++$i);
 | 
					define('HOOK_ACCOUNT_MANAGE_BEFORE_CHARACTERS', ++$i);
 | 
				
			||||||
 | 
					define('HOOK_ACCOUNT_MANAGE_AFTER_CHARACTERS', ++$i);
 | 
				
			||||||
define('HOOK_ACCOUNT_LOGIN_BEFORE_PAGE', ++$i);
 | 
					define('HOOK_ACCOUNT_LOGIN_BEFORE_PAGE', ++$i);
 | 
				
			||||||
define('HOOK_ACCOUNT_LOGIN_BEFORE_ACCOUNT', ++$i);
 | 
					define('HOOK_ACCOUNT_LOGIN_BEFORE_ACCOUNT', ++$i);
 | 
				
			||||||
define('HOOK_ACCOUNT_LOGIN_AFTER_ACCOUNT', ++$i);
 | 
					define('HOOK_ACCOUNT_LOGIN_AFTER_ACCOUNT', ++$i);
 | 
				
			||||||
@@ -92,6 +95,7 @@ define('HOOK_EMAIL_CONFIRMED', ++$i);
 | 
				
			|||||||
define('HOOK_GUILDS_BEFORE_GUILD_HEADER', ++$i);
 | 
					define('HOOK_GUILDS_BEFORE_GUILD_HEADER', ++$i);
 | 
				
			||||||
define('HOOK_GUILDS_AFTER_GUILD_HEADER', ++$i);
 | 
					define('HOOK_GUILDS_AFTER_GUILD_HEADER', ++$i);
 | 
				
			||||||
define('HOOK_GUILDS_AFTER_GUILD_INFORMATION', ++$i);
 | 
					define('HOOK_GUILDS_AFTER_GUILD_INFORMATION', ++$i);
 | 
				
			||||||
 | 
					define('HOOK_GUILDS_AFTER_MANAGE_BUTTON', ++$i);
 | 
				
			||||||
define('HOOK_GUILDS_AFTER_GUILD_MEMBERS', ++$i);
 | 
					define('HOOK_GUILDS_AFTER_GUILD_MEMBERS', ++$i);
 | 
				
			||||||
define('HOOK_GUILDS_AFTER_INVITED_CHARACTERS', ++$i);
 | 
					define('HOOK_GUILDS_AFTER_INVITED_CHARACTERS', ++$i);
 | 
				
			||||||
define('HOOK_TWIG', ++$i);
 | 
					define('HOOK_TWIG', ++$i);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -91,7 +91,7 @@ else {
 | 
				
			|||||||
			$file = BASE . $template_path . '/layout_config.ini';
 | 
								$file = BASE . $template_path . '/layout_config.ini';
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		$template_ini = parse_ini_file($file);
 | 
							$template_ini = parse_ini_file($file, true);
 | 
				
			||||||
		unset($file);
 | 
							unset($file);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if ($cache->enabled()) {
 | 
							if ($cache->enabled()) {
 | 
				
			||||||
@@ -148,7 +148,7 @@ function get_template_menus(): array
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
	global $template_name;
 | 
						global $template_name;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	$result = Cache::remember('template_menus', 10 * 60, function () use ($template_name) {
 | 
						$result = Cache::remember('template_menus_' . $template_name, 10 * 60, function () use ($template_name) {
 | 
				
			||||||
		$result = Menu::select(['name', 'link', 'blank', 'color', 'category'])
 | 
							$result = Menu::select(['name', 'link', 'blank', 'color', 'category'])
 | 
				
			||||||
			->where('template', $template_name)
 | 
								->where('template', $template_name)
 | 
				
			||||||
			->orderBy('category')
 | 
								->orderBy('category')
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,7 +1,26 @@
 | 
				
			|||||||
{% if new_line is defined and new_line %}
 | 
					{% if new_line is defined and new_line %}
 | 
				
			||||||
	<br/>
 | 
						<br/>
 | 
				
			||||||
{% endif %}
 | 
					{% endif %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{% set _center = false %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{% if center is defined and center %}
 | 
				
			||||||
 | 
					{% set _center = true %}
 | 
				
			||||||
 | 
					{% endif %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{% if _center %}
 | 
				
			||||||
 | 
					<table border="0" cellspacing="1" cellpadding="4" width="100%">
 | 
				
			||||||
 | 
						<tbody>
 | 
				
			||||||
 | 
						<tr>
 | 
				
			||||||
 | 
							<td align="center">
 | 
				
			||||||
 | 
					{% endif %}
 | 
				
			||||||
			<form action="{% if action is not defined %}{{ getLink('account/manage') }}{% else %}{{ action }}{% endif %}" method="post">
 | 
								<form action="{% if action is not defined %}{{ getLink('account/manage') }}{% else %}{{ action }}{% endif %}" method="post">
 | 
				
			||||||
				{{ csrf() }}
 | 
									{{ csrf() }}
 | 
				
			||||||
				{{ include('buttons.back.html.twig') }}
 | 
									{{ include('buttons.back.html.twig') }}
 | 
				
			||||||
			</form>
 | 
								</form>
 | 
				
			||||||
 | 
					{% if _center %}
 | 
				
			||||||
 | 
							</td>
 | 
				
			||||||
 | 
						</tr>
 | 
				
			||||||
 | 
						</tbody>
 | 
				
			||||||
 | 
					</table>
 | 
				
			||||||
 | 
					{% endif %}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -28,7 +28,7 @@ Please enter your password and the new email address. Make sure that you enter a
 | 
				
			|||||||
		<td>
 | 
							<td>
 | 
				
			||||||
			<table border="0" cellspacing="0" cellpadding="0">
 | 
								<table border="0" cellspacing="0" cellpadding="0">
 | 
				
			||||||
				<tr>
 | 
									<tr>
 | 
				
			||||||
					<td style="border:0px;">
 | 
										<td style="border:0;">
 | 
				
			||||||
						<form id="form" action="{{ getLink('account/change-email') }}" method="post">
 | 
											<form id="form" action="{{ getLink('account/change-email') }}" method="post">
 | 
				
			||||||
							{{ csrf() }}
 | 
												{{ csrf() }}
 | 
				
			||||||
							<input type="hidden" name="changeemailsave" value="1"/>
 | 
												<input type="hidden" name="changeemailsave" value="1"/>
 | 
				
			||||||
@@ -40,14 +40,14 @@ Please enter your password and the new email address. Make sure that you enter a
 | 
				
			|||||||
		</td>
 | 
							</td>
 | 
				
			||||||
		<td>
 | 
							<td>
 | 
				
			||||||
			<table border="0" cellspacing="0" cellpadding="0">
 | 
								<table border="0" cellspacing="0" cellpadding="0">
 | 
				
			||||||
 | 
									<tr>
 | 
				
			||||||
 | 
										<td style="border:0;">
 | 
				
			||||||
						<form action="{{ getLink('account/manage') }}" method="post">
 | 
											<form action="{{ getLink('account/manage') }}" method="post">
 | 
				
			||||||
							{{ csrf() }}
 | 
												{{ csrf() }}
 | 
				
			||||||
					<tr>
 | 
					 | 
				
			||||||
						<td style="border:0px;">
 | 
					 | 
				
			||||||
							{{ include('buttons.back.html.twig') }}
 | 
												{{ include('buttons.back.html.twig') }}
 | 
				
			||||||
						</td>
 | 
					 | 
				
			||||||
					</tr>
 | 
					 | 
				
			||||||
						</form>
 | 
											</form>
 | 
				
			||||||
 | 
										</td>
 | 
				
			||||||
 | 
									</tr>
 | 
				
			||||||
			</table>
 | 
								</table>
 | 
				
			||||||
		</td>
 | 
							</td>
 | 
				
			||||||
	</tr>
 | 
						</tr>
 | 
				
			||||||
 
 | 
				
			|||||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user