Compare commits
	
		
			1130 Commits
		
	
	
		
			v0.3.0
			...
			v0.9.0-alp
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | c247789adf | ||
|   | cd22f8def5 | ||
|   | 52ac011556 | ||
|   | f34e5f2ac0 | ||
|   | ca8db22639 | ||
|   | 1846bf5255 | ||
|   | dce0ac2f8f | ||
|   | 9cc60983d0 | ||
|   | 7c2c88f780 | ||
|   | 7690811da3 | ||
|   | 7dc2e404ed | ||
|   | 080ab56ea9 | ||
|   | 83915f080c | ||
|   | 2841f17729 | ||
|   | 0187ba4938 | ||
|   | bedfc0a2e0 | ||
|   | ea08c04963 | ||
|   | 067f2af3e5 | ||
|   | 8d98306f8e | ||
|   | 09a045334c | ||
|   | bc8e5fc144 | ||
|   | 77e0d28a9d | ||
|   | 480a054f0c | ||
|   | 26c895d475 | ||
|   | 5cbb55cfb1 | ||
|   | dcb9506a1b | ||
|   | 2acec4df12 | ||
|   | 4bd761c726 | ||
|   | 2f732b8411 | ||
|   | 5aa02055bf | ||
|   | 6ed15565c8 | ||
|   | 77a2c55c87 | ||
|   | 4a9fa01eb7 | ||
|   | bd031d8980 | ||
|   | b76a037a94 | ||
|   | e71daa2520 | ||
|   | f372aeb067 | ||
|   | ef37bbcb81 | ||
|   | 944457463e | ||
|   | 6f7f25bb46 | ||
|   | d60d7f2250 | ||
|   | 2b8c4b3eca | ||
|   | 7039bda359 | ||
|   | d346a8f73f | ||
|   | 523f2dee7c | ||
|   | b33e39491b | ||
|   | 317ebf4387 | ||
|   | 31ba780099 | ||
|   | d1b30619e2 | ||
|   | 3fab52296a | ||
|   | a6e109799a | ||
|   | 80af2cd691 | ||
|   | d911b55e25 | ||
|   | eb73fc4538 | ||
|   | 75f77ec7a3 | ||
|   | a1d969bbfd | ||
|   | 11f1ad6d76 | ||
|   | 7facf0adad | ||
|   | 2b739c2b40 | ||
|   | 269ae323e0 | ||
|   | 0d0e5812dd | ||
|   | 61c2661377 | ||
|   | de710dff94 | ||
|   | 8c524171fb | ||
|   | 946d24690c | ||
|   | bf137189c5 | ||
|   | da4e18cb69 | ||
|   | 85769c1439 | ||
|   | 4d3ad4b6b9 | ||
|   | e900a62e75 | ||
|   | c3969364aa | ||
|   | e9df9f10dc | ||
|   | f78f5b5361 | ||
|   | c061438a35 | ||
|   | 8441dbe007 | ||
|   | e21a741a78 | ||
|   | 955f437e6c | ||
|   | fd419076c2 | ||
|   | 7569536d56 | ||
|   | 3a6102900f | ||
|   | 6dbc694409 | ||
|   | 7a3dcc4dc6 | ||
|   | 23393b5d3e | ||
|   | 863f3ad510 | ||
|   | e6d86ca280 | ||
|   | c22e25e3d2 | ||
|   | 52ffb195ec | ||
|   | 92a51af638 | ||
|   | d7a9158cf2 | ||
|   | f0f84090d2 | ||
|   | 9d78a3b5cf | ||
|   | 2fc163af5a | ||
|   | 10be98e371 | ||
|   | e0eb083e44 | ||
|   | e17cd78153 | ||
|   | 0015f511f8 | ||
|   | f0f71c9f85 | ||
|   | 0002543cca | ||
|   | c1096415aa | ||
|   | 6625768228 | ||
|   | a27f601fe8 | ||
|   | 72a877d9ca | ||
|   | b7ba09a551 | ||
|   | a98cb66c53 | ||
|   | 6785ecad1d | ||
|   | 937af536b6 | ||
|   | 5487314230 | ||
|   | 51e9bb2a7f | ||
|   | 376bb981ae | ||
|   | ed9d78d2f3 | ||
|   | 3c4e50dbda | ||
|   | 523f9dd95a | ||
|   | a43742c8b1 | ||
|   | c49e4fd63d | ||
|   | 905cce7021 | ||
|   | 7a49b5dedc | ||
|   | 3a2870a6bb | ||
|   | 9a475f2c57 | ||
|   | 58598742e8 | ||
|   | d04e44f52f | ||
|   | c7ec1f44e9 | ||
|   | 3ed9a5d3d8 | ||
|   | 61285b6b8c | ||
|   | d17c547bca | ||
|   | 7bc20b0993 | ||
|   | 6c4b3dea96 | ||
|   | 6ae1bf5814 | ||
|   | 8503135ce0 | ||
|   | 590fe0762d | ||
|   | d565b90736 | ||
|   | c88156802a | ||
|   | 7d8dbcbde7 | ||
|   | 66ec66b291 | ||
|   | fc0eb0e793 | ||
|   | ed7e9e1eae | ||
|   | 8985917a96 | ||
|   | 3a3411c117 | ||
|   | 1166ddfe87 | ||
|   | 574e361f90 | ||
|   | f3745a2752 | ||
|   | a2fb9a183b | ||
|   | 295c5de0d6 | ||
|   | d4650afa0e | ||
|   | 07da4ca028 | ||
|   | feffdd1837 | ||
|   | 979532d3df | ||
|   | 3c77c54c8e | ||
|   | 74d013049d | ||
|   | 708aa2d72f | ||
|   | dd6581f7f7 | ||
|   | 8c801dddec | ||
|   | 9de8145f82 | ||
|   | 77460b0832 | ||
|   | 1fb1fb3ae9 | ||
|   | 1d1e927d56 | ||
|   | 036abf83e5 | ||
|   | e737cf612c | ||
|   | 78622fb47a | ||
|   | 9560494ab0 | ||
|   | 8aac3ec2e5 | ||
|   | 269ca501f1 | ||
|   | 20638f430a | ||
|   | acb551c5b0 | ||
|   | 44a6400fcf | ||
|   | 847c3db625 | ||
|   | f30181d485 | ||
|   | 118e8c487e | ||
|   | c73e476e88 | ||
|   | ac5b864ea9 | ||
|   | 42d531838c | ||
|   | 2321cf84b0 | ||
|   | a570363fe0 | ||
|   | 616b8eb61a | ||
|   | e1d486c8c8 | ||
|   | b841c9f631 | ||
|   | e6c72efd18 | ||
|   | 9693fd260c | ||
|   | 717b5fdd15 | ||
|   | 32cf487128 | ||
|   | a9941dea8a | ||
|   | 5c9737f281 | ||
|   | 87a98531d9 | ||
|   | 6d142dcbfe | ||
|   | 90f00e9960 | ||
|   | 8711e178e9 | ||
|   | eb28b38709 | ||
|   | afea618867 | ||
|   | 0abb9384a6 | ||
|   | 2563583f84 | ||
|   | 6acbbe3fa1 | ||
|   | 6c157f3f6c | ||
|   | c4737eca72 | ||
|   | 5428f5e2cf | ||
|   | 7d6d77cfbc | ||
|   | 87eacd17c5 | ||
|   | dd4420dcfd | ||
|   | b8843a29eb | ||
|   | a12262df55 | ||
|   | 091828e8f1 | ||
|   | 8bca099037 | ||
|   | a43d641b5f | ||
|   | 46c058df25 | ||
|   | fa7c6497e6 | ||
|   | 82b41d4df5 | ||
|   | fd2c2d552a | ||
|   | 78ae456b45 | ||
|   | 7e5528b7e1 | ||
|   | a97f55e189 | ||
|   | 50dd65c6de | ||
|   | 16aeb12111 | ||
|   | 96a7c43cb5 | ||
|   | ee20ee2ecd | ||
|   | efdd156d5e | ||
|   | be41023005 | ||
|   | d143f05bb1 | ||
|   | fdc229b196 | ||
|   | f6a5552296 | ||
|   | 62a4b4d3ec | ||
|   | ef24d6739a | ||
|   | 1831198349 | ||
|   | ddf764e308 | ||
|   | 988c757ca6 | ||
|   | cedcd14550 | ||
|   | 0ff290f868 | ||
|   | 1764ce0519 | ||
|   | f3b49d7cba | ||
|   | 6d19d69d20 | ||
|   | 9ad367370a | ||
|   | eb091e487d | ||
|   | a5ccc794bc | ||
|   | 1427dc3ede | ||
|   | e47bb11883 | ||
|   | 6f3ba9c34b | ||
|   | 0f3d2424ce | ||
|   | 8ecd8a10c0 | ||
|   | 3cc3e3a8e9 | ||
|   | be1086bcba | ||
|   | f9abe9a8e3 | ||
|   | 632ecb6d20 | ||
|   | db554df041 | ||
|   | 7300e4f1ad | ||
|   | 9b84532e57 | ||
|   | 14870d74df | ||
|   | 9c7794fe13 | ||
|   | d9526d4021 | ||
|   | 454e09ec3d | ||
|   | c687f64ced | ||
|   | 80623580f2 | ||
|   | 135f393fc4 | ||
|   | e03da2876c | ||
|   | 44fff9dcd1 | ||
|   | 02f993baea | ||
|   | f9302d4f9d | ||
|   | 780f8d193f | ||
|   | 4e85f857a4 | ||
|   | ea035136e1 | ||
|   | 9d8f398d9f | ||
|   | 31f0050f4e | ||
|   | 7ce005341e | ||
|   | 84447ef178 | ||
|   | b99d3b4960 | ||
|   | 0fc64478e0 | ||
|   | e7a3d563aa | ||
|   | bda020ef93 | ||
|   | f0c136c421 | ||
|   | 5fa1321619 | ||
|   | 792ec17d18 | ||
|   | 19ffd57b34 | ||
|   | ebda456862 | ||
|   | 5bd5aa0edf | ||
|   | 6b07d56627 | ||
|   | 15d381adfd | ||
|   | 23b44d6c8a | ||
|   | e3f2abc06e | ||
|   | 3d73de13d8 | ||
|   | 71f7bb2e75 | ||
|   | ebe900fca8 | ||
|   | 5a8bcec014 | ||
|   | a1c7c2768c | ||
|   | 565e6e3a3d | ||
|   | 855e9aa3b9 | ||
|   | a271edec47 | ||
|   | 81b293a5a6 | ||
|   | 8b41e144f8 | ||
|   | a41f653e05 | ||
|   | f24ff295e8 | ||
|   | b399bee3ac | ||
|   | 8f88c82a13 | ||
|   | d8ac88b7d9 | ||
|   | 443c5a80b4 | ||
|   | ba56ef5e33 | ||
|   | b24370e7ed | ||
|   | b2b0b31168 | ||
|   | 1e969f8d8a | ||
|   | bca098e074 | ||
|   | 98bd51436b | ||
|   | 1fa4b1e660 | ||
|   | 04a36b1d11 | ||
|   | 611d6f505d | ||
|   | 62b485abf9 | ||
|   | 61eae7d7c4 | ||
|   | af161b5143 | ||
|   | d5880eac8c | ||
|   | 02d6ab5fe7 | ||
|   | 5547ccffd6 | ||
|   | 8c06bd1738 | ||
|   | 469a8c1017 | ||
|   | bb3602073c | ||
|   | 6c6af59b22 | ||
|   | a8a36c73e6 | ||
|   | 98b1d854f9 | ||
|   | 1ada2317fd | ||
|   | 40722c8c30 | ||
|   | ff9e255f1b | ||
|   | fbe9c31d10 | ||
|   | 0aed705a6a | ||
|   | 06e864c954 | ||
|   | 1d68d013df | ||
|   | 8e6bc73ca6 | ||
|   | 7e0fded595 | ||
|   | c8443228fb | ||
|   | 64fe0062ee | ||
|   | 3b78516ef2 | ||
|   | 8f345126f7 | ||
|   | daaa472dfe | ||
|   | 87f35da3b6 | ||
|   | 6f42a60e59 | ||
|   | 3beedc1747 | ||
|   | 6603815a81 | ||
|   | c1027d3663 | ||
|   | 6cec5ba5bf | ||
|   | d70b70b63c | ||
|   | 7d73e3cd98 | ||
|   | 5087fc4a00 | ||
|   | 30cdb1ba73 | ||
|   | 0f6612904e | ||
|   | e5b5b4d3ef | ||
|   | 9bc63bb55c | ||
|   | dcf83d5608 | ||
|   | 8fe82bb5c0 | ||
|   | 6f74029d76 | ||
|   | 01e3d366ba | ||
|   | 41d5b4a22f | ||
|   | 7814636caf | ||
|   | cf2c5e36bc | ||
|   | 5d5875d540 | ||
|   | 95c2adc02e | ||
|   | 73f1ba10f9 | ||
|   | 9fe419cfe7 | ||
|   | 41e24ca535 | ||
|   | 42a628731d | ||
|   | 2ba702df21 | ||
|   | 0171962306 | ||
|   | 2daa42e124 | ||
|   | abfd2c94f5 | ||
|   | fd51fa7779 | ||
|   | 1a36aa8904 | ||
|   | 881a28138a | ||
|   | 26fb1698b8 | ||
|   | 13d7dd98bd | ||
|   | 672a9f1712 | ||
|   | 2e560ac081 | ||
|   | 39d1127cf1 | ||
|   | 13586e664f | ||
|   | 6e6db543f7 | ||
|   | ea8ae2372e | ||
|   | 928de13459 | ||
|   | e213c3e7d8 | ||
|   | 65b4b2d183 | ||
|   | 94b145b215 | ||
|   | 6c9e6af154 | ||
|   | b5736ad559 | ||
|   | ab3912b378 | ||
|   | 3090989dea | ||
|   | 92314b8dac | ||
|   | a52396008d | ||
|   | ae7350e3a0 | ||
|   | c30300c368 | ||
|   | ed3d415c05 | ||
|   | bb353d617a | ||
|   | d7f41748ad | ||
|   | 915ae47971 | ||
|   | 40b151b4c5 | ||
|   | 1992410a7b | ||
|   | 48874f5b07 | ||
|   | 2144a4eb7c | ||
|   | cbdbf11edc | ||
|   | 515db04023 | ||
|   | d3811f1bf1 | ||
|   | 815fedf8e7 | ||
|   | 929a7b9cfa | ||
|   | f85361dbc5 | ||
|   | cb6509d09d | ||
|   | f09c129c6d | ||
|   | 602a4aa835 | ||
|   | 14d5c6311b | ||
|   | 289dd3c170 | ||
|   | 60eac97945 | ||
|   | de1d6b9629 | ||
|   | 722264a083 | ||
|   | 357d487af7 | ||
|   | 1b802b040d | ||
|   | 25afbd935c | ||
|   | e61bfd2722 | ||
|   | fe571cbef3 | ||
|   | a7c5cb8f5a | ||
|   | dedb96ef4a | ||
|   | ee49efd215 | ||
|   | 56a35eb864 | ||
|   | d478fe0c71 | ||
|   | 03467ea64e | ||
|   | 3368fbd058 | ||
|   | e84c6f7a24 | ||
|   | a0006bad73 | ||
|   | 2458393d22 | ||
|   | 787416e552 | ||
|   | 1c6b241239 | ||
|   | 7469d520c9 | ||
|   | 7e00e62427 | ||
|   | 0e39a969c3 | ||
|   | 0ad1647930 | ||
|   | d7fc45a72d | ||
|   | 54dfb642b1 | ||
|   | 40626d0f42 | ||
|   | 523afccb51 | ||
|   | 1087aefe0a | ||
|   | 9b66edc148 | ||
|   | 2c09b0ae86 | ||
|   | 8de8ad13bf | ||
|   | 70bd442bb0 | ||
|   | 5250b3189b | ||
|   | 2534651e20 | ||
|   | f46a42023f | ||
|   | e2ab301340 | ||
|   | 700f835243 | ||
|   | 9ce7162a04 | ||
|   | af85a8b711 | ||
|   | cd58008a0f | ||
|   | 1f6bd975d0 | ||
|   | b3556c008e | ||
|   | dbe83f8a74 | ||
|   | d1c50f00a0 | ||
|   | bd9d3154db | ||
|   | 1f0b4425a4 | ||
|   | 47bfea4c56 | ||
|   | 416de6b584 | ||
|   | 3d3d141b25 | ||
|   | 2ff56c17e3 | ||
|   | fb326d0354 | ||
|   | e84933cf26 | ||
|   | 8e04328482 | ||
|   | d148b71f0f | ||
|   | 4e68838172 | ||
|   | d281fc588b | ||
|   | 1799ef42a7 | ||
|   | a0d5a863e0 | ||
|   | df59b104db | ||
|   | e7e327c238 | ||
|   | ee6e68d0bf | ||
|   | d7333b3f21 | ||
|   | 375bd58a0c | ||
|   | cddd915adf | ||
|   | 9e0ad271f6 | ||
|   | a0afeb2a7a | ||
|   | 7c208b38ed | ||
|   | eaa11c68f3 | ||
|   | 92c0671da2 | ||
|   | 33d7a0436b | ||
|   | 0525295d7e | ||
|   | 87e54ac14f | ||
|   | e7fa5eb38a | ||
|   | 71b4f4a64a | ||
|   | 64de46943b | ||
|   | 90d691f251 | ||
|   | df2d83b8a0 | ||
|   | ab94d0e752 | ||
|   | b4645553f2 | ||
|   | 324ebcc997 | ||
|   | b7bb570420 | ||
|   | c991e085d4 | ||
|   | 4e935719d3 | ||
|   | 22b71ae477 | ||
|   | 305884b5ee | ||
|   | 9c143a3461 | ||
|   | d94499af86 | ||
|   | 91fd6cb4e6 | ||
|   | fcfad7cef9 | ||
|   | 7424901aca | ||
|   | 8c680608ff | ||
|   | f8ef1b3b61 | ||
|   | 2c114aa559 | ||
|   | daf8beaf26 | ||
|   | 959788cee8 | ||
|   | 7b75a61cdb | ||
|   | c071d65c67 | ||
|   | 044271ad00 | ||
|   | b8130d3fd3 | ||
|   | 4468f3dd37 | ||
|   | 0c9219f885 | ||
|   | 25ab4e187c | ||
|   | 83a51eebfb | ||
|   | 6e99c6d41f | ||
|   | ad570688c9 | ||
|   | 8378bc0d57 | ||
|   | c74bef475b | ||
|   | 3224dd9862 | ||
|   | adf47bb31c | ||
|   | 66cb0455fd | ||
|   | d56965552f | ||
|   | 07946cbeb2 | ||
|   | 33de478450 | ||
|   | bf867c522a | ||
|   | b3a4ffd4a7 | ||
|   | ff2b9c7988 | ||
|   | ad072ea83a | ||
|   | 9dae06b589 | ||
|   | 09db8e072e | ||
|   | 5ac6ff1405 | ||
|   | 9b3dbdc54f | ||
|   | e11d70de46 | ||
|   | f3ddf631c1 | ||
|   | f1c95b315c | ||
|   | 518ae4d97a | ||
|   | 2a9c28e63b | ||
|   | 900500ef28 | ||
|   | 27d76dfa42 | ||
|   | 51b848c43e | ||
|   | f005b7338f | ||
|   | 04a88c9cbd | ||
|   | 7c0c85f650 | ||
|   | ee9e939f88 | ||
|   | e5ca3daa54 | ||
|   | 8021308822 | ||
|   | d9e449b6cf | ||
|   | c94bb09123 | ||
|   | 1cd3ebf3bb | ||
|   | 2070f91a8f | ||
|   | 5b6b37a867 | ||
|   | 2dbf189f43 | ||
|   | 82e64559a8 | ||
|   | d0d77b8775 | ||
|   | 35c4988c98 | ||
|   | 10cad086f6 | ||
|   | 4d5ba90d38 | ||
|   | 3eb75708de | ||
|   | b95d333dc9 | ||
|   | 887a080198 | ||
|   | 8f3c3c6ba3 | ||
|   | f7c7552d5a | ||
|   | b61c6151eb | ||
|   | 37e2849a3a | ||
|   | a4eca93584 | ||
|   | 13d0718780 | ||
|   | 38693521b3 | ||
|   | 447ddeb6d3 | ||
|   | f11b2e9132 | ||
|   | 9d69b9d173 | ||
|   | 27a44bf9af | ||
|   | b68077d969 | ||
|   | f475c671f7 | ||
|   | 1ab32ca3ba | ||
|   | 8345b839e7 | ||
|   | 259cda150d | ||
|   | 8146c90efa | ||
|   | da3d078917 | ||
|   | 72c79e005a | ||
|   | d252138867 | ||
|   | c20183c547 | ||
|   | cd94abb7fd | ||
|   | f886245e3c | ||
|   | 4f413eec12 | ||
|   | 441bfe74c1 | ||
|   | 071289bc48 | ||
|   | 1ba2381437 | ||
|   | 1e5e576bd0 | ||
|   | 059b8824a2 | ||
|   | d7e6916d8f | ||
|   | c821f76f0f | ||
|   | e5ad1b45bd | ||
|   | 08f011eb33 | ||
|   | 1a6044090a | ||
|   | 697bf590ff | ||
|   | 4073da2431 | ||
|   | fbca43b239 | ||
|   | a03a8bf0d5 | ||
|   | 75d1ed6eea | ||
|   | dd1e604155 | ||
|   | c7f2cab56a | ||
|   | 2bd372dbaa | ||
|   | 45ecc29e12 | ||
|   | 69d068e73f | ||
|   | 0f55211dc9 | ||
|   | dbf09ef361 | ||
|   | e08557e5ae | ||
|   | aaaba5cc84 | ||
|   | 2cfd0242bd | ||
|   | 0711d555e1 | ||
|   | e8363d7310 | ||
|   | be9ce34dc8 | ||
|   | bb60d17ccc | ||
|   | 1aa8062310 | ||
|   | 711027e450 | ||
|   | 8115cc5ecc | ||
|   | 8bae67d9ef | ||
|   | bc3fd61bde | ||
|   | ba1d52d6dd | ||
|   | c02d0fc927 | ||
|   | 56738389f8 | ||
|   | d511679dbd | ||
|   | 6b931de37d | ||
|   | 56e9d85fc2 | ||
|   | 405f890dfc | ||
|   | 1145c26f2b | ||
|   | 3890222bbc | ||
|   | fba9f66a1f | ||
|   | 668387e372 | ||
|   | f85fad447e | ||
|   | 56616b805f | ||
|   | b9729ad763 | ||
|   | a26538c3f0 | ||
|   | a55ec208aa | ||
|   | 1970a00bb6 | ||
|   | 1e2267bd31 | ||
|   | 092a03e2cf | ||
|   | 065661e419 | ||
|   | 72d7dae7fa | ||
|   | 5624022064 | ||
|   | 944d532ad1 | ||
|   | 11727785c7 | ||
|   | 9b04dc0e44 | ||
|   | ca4f786aa8 | ||
|   | 152114b054 | ||
|   | 6aef5ecf4b | ||
|   | 645e7ee95f | ||
|   | 798d0948d1 | ||
|   | 008374748e | ||
|   | 3333ab4ade | ||
|   | f8c2f0f01b | ||
|   | 6dc62cca13 | ||
|   | f3e9f17b85 | ||
|   | ed14f9ada0 | ||
|   | 9250f20559 | ||
|   | 6157fdc007 | ||
|   | 5a97e53e21 | ||
|   | 901cb9eaf6 | ||
|   | 79de744936 | ||
|   | d8a70a3da6 | ||
|   | 813de7eb3c | ||
|   | 410c15c997 | ||
|   | fb9ead2690 | ||
|   | e7c381d651 | ||
|   | dca74d7b11 | ||
|   | 415b31e1b4 | ||
|   | af1a6cf5ff | ||
|   | d79ae8e927 | ||
|   | 49fe7a4b38 | ||
|   | f5374e8ce7 | ||
|   | 0c207ce12d | ||
|   | 3945c2ad52 | ||
|   | bc8f24afad | ||
|   | fd91d1fb06 | ||
|   | 6a81794bba | ||
|   | 6a89b12258 | ||
|   | 219f128cb7 | ||
|   | 89a24442c4 | ||
|   | 62eab175ab | ||
|   | e3af63bd93 | ||
|   | 78454657ca | ||
|   | 7b770e09f7 | ||
|   | 933b25194c | ||
|   | 1cbe452f9c | ||
|   | 920e9b915f | ||
|   | 99e38b1b60 | ||
|   | 2964089483 | ||
|   | 624a99b179 | ||
|   | 705277ceb5 | ||
|   | bf709786f3 | ||
|   | bda7982134 | ||
|   | abb2b36ae6 | ||
|   | 945442a842 | ||
|   | 30b231cfdf | ||
|   | cbdac66fd0 | ||
|   | 257d4dbdad | ||
|   | 69064839a7 | ||
|   | ed6a740eee | ||
|   | d594fa1a54 | ||
|   | 35e4cd4596 | ||
|   | 24319ddc7a | ||
|   | d3e3efd05e | ||
|   | 14cb37725e | ||
|   | fc3bd432ef | ||
|   | b0a5220159 | ||
|   | 9620ac7d25 | ||
|   | 7b1989cef2 | ||
|   | 601d2808a2 | ||
|   | 71b4963ed8 | ||
|   | f124c4844f | ||
|   | 7f9877b3da | ||
|   | 1526dde39d | ||
|   | 7dd6925049 | ||
|   | 6163d3fbed | ||
|   | 630d23141d | ||
|   | 0252006eb1 | ||
|   | 162777bb46 | ||
|   | 0d5b9c2f98 | ||
|   | 5f22ab0361 | ||
|   | b1fd1263f1 | ||
|   | 6226203b0e | ||
|   | 9f31f90146 | ||
|   | 5aaf15f81c | ||
|   | 5ad82a305e | ||
|   | 296e99772a | ||
|   | 1365f41b2d | ||
|   | 13199744ef | ||
|   | 4e937c32b4 | ||
|   | 559d13dfd9 | ||
|   | a94a9291e6 | ||
|   | 6ccaf316ab | ||
|   | 9fff996393 | ||
|   | 3febb340d4 | ||
|   | 5abc08ba9d | ||
|   | 2164e9a5a0 | ||
|   | c87100c0fe | ||
|   | 6a167e99dc | ||
|   | 052672402e | ||
|   | 4d566500e9 | ||
|   | 2dd51d0202 | ||
|   | 862b58c176 | ||
|   | 09b6f16a51 | ||
|   | ffebcee48b | ||
|   | 8c50a84516 | ||
|   | 7c8f87bd78 | ||
|   | ded5274be7 | ||
|   | d03989481b | ||
|   | dac59d3133 | ||
|   | 7a5333ba62 | ||
|   | f8e9fe376b | ||
|   | f9ea7af3ab | ||
|   | 622122562f | ||
|   | 3b96b21683 | ||
|   | 3fc8d01070 | ||
|   | b0603c6c7d | ||
|   | 276f3a5516 | ||
|   | 1859867039 | ||
|   | 8c83eb805b | ||
|   | 2667d2b41c | ||
|   | 1b539f82ac | ||
|   | 876b1b988a | ||
|   | e3bcbc4da9 | ||
|   | 1f9aa96486 | ||
|   | 2d17116119 | ||
|   | b592d02bb7 | ||
|   | 961d1acd51 | ||
|   | 138d22976a | ||
|   | 848507f7e8 | ||
|   | 82fed8abfe | ||
|   | 7941bdc55e | ||
|   | d1e6061541 | ||
|   | 96e55b17b1 | ||
|   | 6dab50cbd8 | ||
|   | 89f24c631c | ||
|   | 5d0a0d352b | ||
|   | 63bc0a9620 | ||
|   | 0791ccbcf5 | ||
|   | d03ab6c79f | ||
|   | 72e2a762da | ||
|   | cd0b1f10cc | ||
|   | a81824a7eb | ||
|   | 589d07ed40 | ||
|   | 9a86f1ebed | ||
|   | 2695995211 | ||
|   | ff8105f809 | ||
|   | 98a05f53d2 | ||
|   | 549b1a2f13 | ||
|   | b50d0cd710 | ||
|   | ff135c034c | ||
|   | eb93b08342 | ||
|   | 048c40c16c | ||
|   | 33b871efa6 | ||
|   | 2010094f83 | ||
|   | 693e201900 | ||
|   | 2333180c50 | ||
|   | 915e9409dc | ||
|   | b6be3226c5 | ||
|   | b83cad36b6 | ||
|   | fb1b9fea09 | ||
|   | 45a387000d | ||
|   | e6b052f8e9 | ||
|   | 6365105515 | ||
|   | 550b664a61 | ||
|   | 510459b046 | ||
|   | adbec47fad | ||
|   | ae24a4ea4c | ||
|   | db67bb0b98 | ||
|   | 857ce1324c | ||
|   | 82d6467cee | ||
|   | 887c792a76 | ||
|   | b3625dffbc | ||
|   | 90cd5dfae7 | ||
|   | 8ce791368c | ||
|   | 05e15ce9ad | ||
|   | 1926c5ec5b | ||
|   | 0bb1d869af | ||
|   | c654ea329c | ||
|   | 68d74a490b | ||
|   | 857aa110c8 | ||
|   | 6ba24eebb0 | ||
|   | 023eb3b0ff | ||
|   | bf361238cb | ||
|   | 42d23e9b37 | ||
|   | e1ddf58119 | ||
|   | 4023fda5b6 | ||
|   | f34f2da9b9 | ||
|   | 050f596429 | ||
|   | de36cfd2eb | ||
|   | b828b8e44a | ||
|   | 15da31d3eb | ||
|   | 6158d81b5e | ||
|   | b714bf4abe | ||
|   | 46ca6262b5 | ||
|   | cfef209cb7 | ||
|   | 654c038eab | ||
|   | a6beb0d2d5 | ||
|   | 515b42cd51 | ||
|   | 6668c47368 | ||
|   | b801fdc14f | ||
|   | 15dcc7b802 | ||
|   | 3ec6d5e905 | ||
|   | 92cd64c8e8 | ||
|   | 955396e575 | ||
|   | 52efadd442 | ||
|   | 09234e65fe | ||
|   | 4d0d601127 | ||
|   | bce3756e83 | ||
|   | 0cf21671a4 | ||
|   | 5d3fbb4bff | ||
|   | 68bbf4182f | ||
|   | eab416c0b4 | ||
|   | c48452b37d | ||
|   | a636a87c2b | ||
|   | ba8e1c5647 | ||
|   | fc30e28e84 | ||
|   | cfca37b09c | ||
|   | 31a3f594f1 | ||
|   | 9c536bd845 | ||
|   | 808612cd10 | ||
|   | f2c3e558cc | ||
|   | 3324154208 | ||
|   | 9c0068d470 | ||
|   | 5079027978 | ||
|   | 04dca2f274 | ||
|   | 168df5d4e2 | ||
|   | 6cf6f0460e | ||
|   | 57d8e0b06f | ||
|   | 55ab90a481 | ||
|   | 0a8fb40bd7 | ||
|   | fb026ec07f | ||
|   | 79697e9030 | ||
|   | 873e05538e | ||
|   | 9dd18a97e8 | ||
|   | 51acb739e9 | ||
|   | 7e2be69749 | ||
|   | 8e0ec47229 | ||
|   | ca4b243daa | ||
|   | 755adb0863 | ||
|   | fc6cd29e84 | ||
|   | ab73c602c3 | ||
|   | 862533fd7f | ||
|   | ffa3bed620 | ||
|   | ba8d56f6ab | ||
|   | 4bfc804d85 | ||
|   | 40981daf33 | ||
|   | 16bcb70863 | ||
|   | b1c72df333 | ||
|   | 39ced581b8 | ||
|   | 18a325cad8 | ||
|   | 7b0e891ab3 | ||
|   | fc243466da | ||
|   | 9738c1896d | ||
|   | d0976cead9 | ||
|   | 2e46d80bce | ||
|   | 283806369a | ||
|   | 500cb23ab9 | ||
|   | 88cabf88b2 | ||
|   | 9dc3d6d8d6 | ||
|   | cb8d8c4173 | ||
|   | 1949c197d6 | ||
|   | 16dab3a2cc | ||
|   | 497a073162 | ||
|   | 22e245ecff | ||
|   | b03433d8a8 | ||
|   | 4f0fca021c | ||
|   | 5aa1ae003e | ||
|   | f29758939c | ||
|   | 3703c2b431 | ||
|   | d289d9a8ff | ||
|   | a083dd048d | ||
|   | f09c30d370 | ||
|   | 9e28d46ee7 | ||
|   | c133482659 | ||
|   | bf71c1aee8 | ||
|   | 4102b44352 | ||
|   | acf2e2fb4a | ||
|   | f9de0b5eb9 | ||
|   | 85083f5979 | ||
|   | 087988dde3 | ||
|   | 2dddb853f2 | ||
|   | a92355181f | ||
|   | 2085f7e128 | ||
|   | de7366e9a9 | ||
|   | 7ab1c1170f | ||
|   | 792770e5e2 | ||
|   | dece42c155 | ||
|   | 1025fad0e6 | ||
|   | 31537687c1 | ||
|   | 9c281511fa | ||
|   | 544375378f | ||
|   | c2574235ea | ||
|   | 0533b8c946 | ||
|   | 5475bd6b5f | ||
|   | 2e4321872a | ||
|   | 515790b1a0 | ||
|   | 35c9ffcdca | ||
|   | 920c8a936f | ||
|   | 6863ba4883 | ||
|   | 2f49413867 | ||
|   | 854560b2f5 | ||
|   | 4a948b8ba2 | ||
|   | 01c0d021b2 | ||
|   | 3e49ef42a2 | ||
|   | efb1775aff | ||
|   | 2a1f1c3cd9 | ||
|   | 3c4ab10b36 | ||
|   | 1c94169182 | ||
|   | 53ab7af8dc | ||
|   | 8d173d369d | ||
|   | 4535687b48 | ||
|   | c415cf5ffb | ||
|   | a95c93cd5b | ||
|   | 62443257fc | ||
|   | 60a8317115 | ||
|   | 73ed384215 | ||
|   | c4a1f7df5f | ||
|   | 8b4eccc064 | ||
|   | 6528a4a60c | ||
|   | 4d690992ac | ||
|   | b83fb05b82 | ||
|   | cf12265cd8 | ||
|   | e4110a6981 | ||
|   | 412908026d | ||
|   | 8a7887cf06 | ||
|   | 779dd003dd | ||
|   | 0b2895dc56 | ||
|   | fed5d08703 | ||
|   | f131f27ac3 | ||
|   | 19dbbdcf4f | ||
|   | d650035980 | ||
|   | fbc803d09f | ||
|   | df4c594d4f | ||
|   | 482445cb98 | ||
|   | 1c002c63a3 | ||
|   | cd366b6087 | ||
|   | 83dc5b7650 | ||
|   | d9675b1bc6 | ||
|   | 036520566c | ||
|   | 8b302749ff | ||
|   | 68b3e2cfee | ||
|   | 9ee6906e4d | ||
|   | be38f51cc7 | ||
|   | aaed21f752 | ||
|   | a1dddd7df8 | ||
|   | f26795ca7a | ||
|   | 7d6bbb3385 | ||
|   | 37f792d9ce | ||
|   | 867c86d702 | ||
|   | 05f8756a12 | ||
|   | c581c35a73 | ||
|   | b37bd5f0ae | ||
|   | 56a01e1e64 | ||
|   | 6aa58bddd8 | ||
|   | 0515f2825a | ||
|   | 0d37e07a0d | ||
|   | ab69b182e6 | ||
|   | 7b84614a79 | ||
|   | 361e536243 | ||
|   | 39fee6e57d | ||
|   | 56a0c6e6bf | ||
|   | eb8993e746 | ||
|   | edeb781600 | ||
|   | 9aa4e308c1 | ||
|   | 05abf41b64 | ||
|   | ac9c43e280 | ||
|   | c05e7f29c5 | ||
|   | 583f3394fc | ||
|   | 5e414ebda8 | ||
|   | 21b1383c9a | ||
|   | 6c9e09ea73 | ||
|   | 195ec4b11e | ||
|   | bf988a7f6e | ||
|   | 25f8028ae3 | ||
|   | 28299744c4 | ||
|   | 72212f8256 | ||
|   | 1610a4ab91 | ||
|   | 87a3d1e5d1 | ||
|   | 2b6d65e955 | ||
|   | cd44d28674 | ||
|   | 2edeb1b3e2 | ||
|   | 9f946d4bc4 | ||
|   | 5266f33af5 | ||
|   | 85c9a1e84d | ||
|   | 5951fe21ec | ||
|   | c6b6638705 | ||
|   | 8ab7be9fb8 | ||
|   | 762fa31c28 | ||
|   | c2678aa91f | ||
|   | d4900eac84 | ||
|   | f9b6e9fa2e | ||
|   | cfb460c137 | ||
|   | f9e6966687 | ||
|   | 913b4297cf | ||
|   | 23c1df72aa | ||
|   | cde42ec3fa | ||
|   | 0104d2fd36 | ||
|   | 85d1f3419a | ||
|   | e45d27b5c7 | ||
|   | a3d94db6eb | ||
|   | ef904c854b | ||
|   | 7a7eb4e553 | ||
|   | c7f549742d | ||
|   | 1850ef70d8 | ||
|   | 0b693a02bd | ||
|   | 508db95cba | ||
|   | bbae0c3ade | ||
|   | 0239f940a0 | ||
|   | 1df0c2b313 | ||
|   | a9d9ace532 | ||
|   | cb83e17710 | ||
|   | 1727df7082 | ||
|   | 3d585a3d02 | ||
|   | 69f822b69c | ||
|   | abfe3b08af | ||
|   | 66a3c46aaf | ||
|   | c914a73352 | ||
|   | 5041ed1564 | ||
|   | 4daaa67710 | ||
|   | dd572b00d0 | ||
|   | 3fef1a6eec | ||
|   | 6d81a29bb6 | ||
|   | 3f1c638a14 | ||
|   | 7caca74d57 | ||
|   | d95aea319e | ||
|   | 9aed09d250 | ||
|   | 3ebcd788fb | ||
|   | 816751f464 | ||
|   | f84ae88aa4 | ||
|   | 315e0400ff | ||
|   | 22cf7f5d4f | ||
|   | 6ec829e47f | ||
|   | a119d75589 | ||
|   | 92028a2492 | ||
|   | 42ef8487c8 | ||
|   | e92e5d1040 | ||
|   | a1950cf27e | ||
|   | 27fb0ffb06 | ||
|   | 6c3439acf9 | ||
|   | 005356ebb3 | ||
|   | f0adabf567 | ||
|   | 739782109e | ||
|   | 87ba018ab8 | ||
|   | 041702615f | ||
|   | 0a82f306f6 | ||
|   | 856e72150c | ||
|   | e2857f8ca5 | ||
|   | 04d9ec9c94 | ||
|   | e984a467ef | ||
|   | 8342a7b8a8 | ||
|   | 269af1930c | ||
|   | b7bb950abc | ||
|   | 4a19458c15 | ||
|   | b6db420465 | ||
|   | 7b234ad41f | ||
|   | 35b0795b51 | ||
|   | 04a7796665 | ||
|   | 755deae717 | ||
|   | 6d66dc9043 | ||
|   | bbd9cd2101 | ||
|   | b6ccde075d | ||
|   | e94b9006e6 | ||
|   | e9c8159bf3 | ||
|   | 919f69ef46 | ||
|   | 4ac2fe27d5 | ||
|   | be2daeb4ab | ||
|   | 7b96ce9b8c | ||
|   | 801188f957 | ||
|   | c546a46847 | ||
|   | 6527d21794 | ||
|   | 7fad722927 | ||
|   | ab249eb95f | ||
|   | bdbd215aad | ||
|   | 68212a36bb | ||
|   | ac3691dc08 | ||
|   | 3a6aab67d5 | ||
|   | 2c5b3f4da3 | ||
|   | 73eca63c4f | ||
|   | c504588993 | ||
|   | 5b14c6d4d4 | ||
|   | 4685c7b868 | ||
|   | 0e185c8bcf | ||
|   | e230949edd | ||
|   | a897b5e98c | ||
|   | 186d3dbd38 | ||
|   | 127c04070b | ||
|   | 6ff65050f5 | ||
|   | d605ef4b28 | ||
|   | 9466b7ce75 | ||
|   | 7f6eff666e | ||
|   | e878b4df48 | ||
|   | 2c3c1529a7 | ||
|   | ecce524c7b | ||
|   | 5af617b869 | ||
|   | 3f886c9f7c | ||
|   | d50fb7a291 | ||
|   | 37502c5562 | ||
|   | 7620ec896b | ||
|   | 8a87186833 | ||
|   | b0f8013762 | ||
|   | 3a6a1c448a | ||
|   | 2cd9f80b34 | ||
|   | d88de8e072 | ||
|   | 6e6ce55a7b | 
							
								
								
									
										19
									
								
								.editorconfig
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,19 @@ | ||||
| # EditorConfig is awesome: https://EditorConfig.org | ||||
|  | ||||
| # top-most EditorConfig file | ||||
| root = true | ||||
|  | ||||
| # with a newline ending every file | ||||
| [*] | ||||
| indent_style = tab | ||||
| indent_size = 4 | ||||
| insert_final_newline = true | ||||
|  | ||||
| [*.md] | ||||
| trim_trailing_whitespace = false | ||||
|  | ||||
| [{composer.json,package.json}] | ||||
| indent_style = space | ||||
|  | ||||
| [package.json] | ||||
| indent_size = 2 | ||||
							
								
								
									
										14
									
								
								.gitattributes
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,14 @@ | ||||
| * text=auto | ||||
| .gitattributes export-ignore | ||||
| .gitignore export-ignore | ||||
| .github export-ignore | ||||
| .editorconfig export-ignore | ||||
| _config.yml export-ignore | ||||
| release.sh export-ignore | ||||
|  | ||||
| # cypress | ||||
| cypress export-ignore | ||||
| cypress.config.js export-ignore | ||||
| cypress.env.json | ||||
|  | ||||
| *.sh text eol=lf | ||||
							
								
								
									
										12
									
								
								.github/FUNDING.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,12 @@ | ||||
| # These are supported funding model platforms | ||||
|  | ||||
| github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] | ||||
| patreon: # Replace with a single Patreon username | ||||
| open_collective: # Replace with a single Open Collective username | ||||
| ko_fi: # Replace with a single Ko-fi username | ||||
| tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel | ||||
| community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry | ||||
| liberapay: # Replace with a single Liberapay username | ||||
| issuehunt: # Replace with a single IssueHunt username | ||||
| otechie: # Replace with a single Otechie username | ||||
| custom: paypal.me/slawkens # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] | ||||
							
								
								
									
										29
									
								
								.github/ISSUE_TEMPLATE.md
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,29 @@ | ||||
| <!-- | ||||
| Please use this issue tracker only for reporting MyAAC bugs. | ||||
|  | ||||
| If you need support, please use the discord server: | ||||
|  | ||||
| - https://discord.gg/2J39Wus (we have an own channel named #my-aac there) | ||||
|  | ||||
| or use otland support boards: | ||||
|  | ||||
| - https://otland.net/forums/support.16/ | ||||
|  | ||||
| --> | ||||
|  | ||||
| ### Server configuration | ||||
| - Operating System:  | ||||
| - Web Server (+ version):  | ||||
| - PHP Version:  | ||||
| - Server name and version (for example: TFS 0.3):  | ||||
| - MyAAC Version:  | ||||
|  | ||||
| ### Client configuration (Your Computer) | ||||
|  | ||||
| - Browser:  | ||||
| - Operating System:  | ||||
|  | ||||
| ### Description: | ||||
|  | ||||
|  | ||||
| ### Steps To Reproduce: | ||||
							
								
								
									
										120
									
								
								.github/workflows/cypress.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,120 @@ | ||||
| name: Cypress | ||||
| on: | ||||
|   pull_request: | ||||
|     branches: [develop] | ||||
|   push: | ||||
|     branches: [develop] | ||||
|  | ||||
| jobs: | ||||
|   cypress: | ||||
|     runs-on: ubuntu-latest | ||||
|     services: | ||||
|       mysql: | ||||
|         image: mysql:8.0 | ||||
|         env: | ||||
|           MYSQL_ROOT_PASSWORD: root | ||||
|           MYSQL_DATABASE: myaac | ||||
|           MYSQL_USER: myaac | ||||
|           MYSQL_PASSWORD: myaac | ||||
|         ports: | ||||
|           - 3306/tcp | ||||
|         options: --health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=3 | ||||
|     strategy: | ||||
|       fail-fast: false | ||||
|       matrix: | ||||
|         php-versions: [ '7.4', '8.0', '8.1' ] | ||||
|     name: MyAAC on PHP ${{ matrix.php-versions }} | ||||
|     steps: | ||||
|         - name: 📌 MySQL Start & init & show db | ||||
|           run: | | ||||
|             sudo /etc/init.d/mysql start | ||||
|             mysql -e 'CREATE DATABASE myaac;' -uroot -proot | ||||
|             mysql -e "SHOW DATABASES" -uroot -proot | ||||
|  | ||||
|         - name: Checkout MyAAC | ||||
|           uses: actions/checkout@v3 | ||||
|           with: | ||||
|             ref: develop | ||||
|  | ||||
|         - name: Checkout TFS | ||||
|           uses: actions/checkout@v3 | ||||
|           with: | ||||
|             repository: otland/forgottenserver | ||||
|             ref: 1.4 | ||||
|             path: tfs | ||||
|  | ||||
|         - name: Import TFS Schema | ||||
|           run: | | ||||
|               mysql -uroot -proot myaac < tfs/schema.sql | ||||
|  | ||||
|         - name: Rename config.lua | ||||
|           run: mv tfs/config.lua.dist tfs/config.lua | ||||
|  | ||||
|         - name: Replace mysqlUser | ||||
|           uses: jacobtomlinson/gha-find-replace@v2 | ||||
|           with: | ||||
|             find: 'mysqlUser = "forgottenserver"' | ||||
|             replace: 'mysqlUser = "root"' | ||||
|             regex: false | ||||
|             include: 'tfs/config.lua' | ||||
|  | ||||
|         - name: Replace mysqlPass | ||||
|           uses: jacobtomlinson/gha-find-replace@v2 | ||||
|           with: | ||||
|               find: 'mysqlPass = ""' | ||||
|               replace: 'mysqlPass = "root"' | ||||
|               regex: false | ||||
|               include: 'tfs/config.lua' | ||||
|  | ||||
|         - name: Replace mysqlDatabase | ||||
|           uses: jacobtomlinson/gha-find-replace@v2 | ||||
|           with: | ||||
|               find: 'mysqlDatabase = "forgottenserver"' | ||||
|               replace: 'mysqlDatabase = "myaac"' | ||||
|               regex: false | ||||
|               include: 'tfs/config.lua' | ||||
|  | ||||
|         - name: Setup PHP | ||||
|           uses: shivammathur/setup-php@v2 | ||||
|           with: | ||||
|             php-version: ${{ matrix.php-versions }} | ||||
|             extensions: mbstring, dom, fileinfo, mysql, json, xml, pdo, pdo_mysql | ||||
|  | ||||
|         - name: Get composer cache directory | ||||
|           id: composer-cache | ||||
|           run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT | ||||
|  | ||||
|         - name: Cache composer dependencies | ||||
|           uses: actions/cache@v3 | ||||
|           with: | ||||
|             path: ${{ steps.composer-cache.outputs.dir }} | ||||
|             # Use composer.json for key, if composer.lock is not committed. | ||||
|             # key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }} | ||||
|             key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} | ||||
|             restore-keys: ${{ runner.os }}-composer- | ||||
|  | ||||
|         - name: Install Composer dependencies | ||||
|           run: composer install --no-progress --prefer-dist --optimize-autoloader | ||||
|  | ||||
|         - name: Run PHP server | ||||
|           run: nohup php -S localhost:8080 > php.log 2>&1 & | ||||
|  | ||||
|         - name: Cypress Run | ||||
|           uses: cypress-io/github-action@v5 | ||||
|           env: | ||||
|             CYPRESS_URL: http://localhost:8080 | ||||
|             CYPRESS_SERVER_PATH: /home/runner/work/myaac/myaac/tfs | ||||
|  | ||||
|         - name: Save screenshots | ||||
|           uses: actions/upload-artifact@v3 | ||||
|           if: always() | ||||
|           with: | ||||
|             name: cypress-screenshots | ||||
|             path: cypress/screenshots | ||||
|  | ||||
|         - name: Upload Cypress Videos | ||||
|           uses: actions/upload-artifact@v3 | ||||
|           if: always() | ||||
|           with: | ||||
|             name: cypress-videos | ||||
|             path: cypress/videos | ||||
							
								
								
									
										16
									
								
								.github/workflows/phplint.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,16 @@ | ||||
| name: PHP Linting | ||||
| on: | ||||
|   pull_request: | ||||
|     branches: [develop] | ||||
|   push: | ||||
|     branches: [develop] | ||||
|  | ||||
| jobs: | ||||
|   phplint: | ||||
|     runs-on: ubuntu-latest | ||||
|     steps: | ||||
|       - uses: actions/checkout@v3 | ||||
|       - uses: overtrue/phplint@8.2 | ||||
|         with: | ||||
|           path: . | ||||
|           options: --exclude=*.log | ||||
							
								
								
									
										68
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,68 @@ | ||||
| Thumbs.db | ||||
| .DS_Store | ||||
| .idea | ||||
|  | ||||
| # composer | ||||
| composer.lock | ||||
| vendor | ||||
|  | ||||
| # npm | ||||
| node_modules | ||||
|  | ||||
| # cypress | ||||
| cypress.env.json | ||||
| cypress/e2e/2-advanced-examples | ||||
|  | ||||
| # created by release.sh | ||||
| releases | ||||
| tmp | ||||
|  | ||||
| config.local.php | ||||
|  | ||||
| # all custom templates | ||||
| templates/* | ||||
| !templates/tibiacom | ||||
| !templates/kathrine | ||||
|  | ||||
| # guild images | ||||
| images/guilds/* | ||||
| !images/guilds/default.gif | ||||
|  | ||||
| # editor images | ||||
| images/editor/* | ||||
| !images/editor/index.html | ||||
|  | ||||
| # cache | ||||
| system/cache/* | ||||
| !system/cache/index.html | ||||
| !system/cache/twig/index.html | ||||
| !system/cache/signatures/index.html | ||||
| !system/cache/plugins/index.html | ||||
|  | ||||
| # logs | ||||
| system/logs/* | ||||
| !system/logs/index.html | ||||
|  | ||||
| # data | ||||
| system/data/* | ||||
| !system/data/index.html | ||||
|  | ||||
| # php sessions | ||||
| system/php_sessions/* | ||||
| !system/php_sessions/index.html | ||||
|  | ||||
| # plugins | ||||
| plugins/* | ||||
| !plugins/.htaccess | ||||
| !plugins/example.json | ||||
| !plugins/account-create-hint.json | ||||
| !plugins/account-create-hint | ||||
| !plugins/email-confirmed-reward.json | ||||
| !plugins/email-confirmed-reward | ||||
| landing | ||||
|  | ||||
| # system | ||||
| system/functions_custom.php | ||||
|  | ||||
| # others/rest | ||||
| system/pages/downloads.php | ||||
							
								
								
									
										21
									
								
								.htaccess
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,21 @@ | ||||
| <IfModule mod_autoindex.c> | ||||
| 	Options -Indexes | ||||
| </IfModule> | ||||
|  | ||||
| <IfModule mod_negotiation.c> | ||||
| 	Options -MultiViews | ||||
| </IfModule> | ||||
|  | ||||
| <FilesMatch "^(CHANGELOG\.md|README\.md|composer\.json|composer\.lock|package\.json|package-lock\.json|cypress\.env\.json)$"> | ||||
| 	Require all denied | ||||
| </FilesMatch> | ||||
|  | ||||
| <IfModule mod_rewrite.c> | ||||
| 	RewriteEngine On | ||||
|  | ||||
| 	#RewriteBase /myaac/ | ||||
|  | ||||
| 	RewriteCond %{REQUEST_FILENAME} !-f | ||||
| 	RewriteCond %{REQUEST_FILENAME} !-d | ||||
| 	RewriteRule ^.*$ index.php [L] | ||||
| </IfModule> | ||||
| @@ -1,33 +0,0 @@ | ||||
| Options -Indexes -MultiViews | ||||
|  | ||||
| RewriteEngine On | ||||
| #RewriteBase / | ||||
|  | ||||
| # Page parser | ||||
| RewriteCond %{REQUEST_FILENAME} !-f | ||||
| RewriteCond %{REQUEST_FILENAME} !-d | ||||
| RewriteRule ^([A-Za-z0-9-_+']+)\.png/?$ tools/signature/index.php?name=$1 [L] | ||||
| RewriteRule ^characters/([A-Za-z0-9-_+']+)$ index.php?subtopic=characters&name=$1 | ||||
| RewriteRule ^guilds/([A-Za-z0-9-_+']+)$ index.php?subtopic=guilds&action=show&guild=$1 | ||||
| RewriteRule ^forum/board/([0-9]+)$ index.php?subtopic=forum&action=show_board&id=$1 | ||||
| RewriteRule ^forum/board/([0-9]+)/([0-9]+)$ index.php?subtopic=forum&action=show_board&id=$1&page=$2 | ||||
| RewriteRule ^forum/thread/([0-9]+)$ index.php?subtopic=forum&action=show_thread&id=$1 | ||||
| RewriteRule ^forum/thread/([0-9]+)/([0-9]+)$ index.php?subtopic=forum&action=show_thread&id=$1&page=$2 | ||||
| RewriteRule ^forum/board/([0-9]+)/([0-9]+)$ index.php?subtopic=forum&action=show_thread&id=$1&page=$2 | ||||
| RewriteRule ^account/manage$ index.php?subtopic=accountmanagement | ||||
| RewriteRule ^account/create$ index.php?subtopic=createaccount | ||||
| RewriteRule ^account/lost$ index.php?subtopic=lostaccount | ||||
| RewriteRule ^account/logout$ index.php?subtopic=accountmanagement&action=logout | ||||
| RewriteRule ^news/archive/([0-9]+)$ index.php?subtopic=newsarchive&id=$1 | ||||
| RewriteRule ^news/archive$ index.php?subtopic=newsarchive | ||||
| RewriteRule ^highscores/([A-Za-z0-9-_]+)/([A-Za-z0-9-_]+)?$ index.php?subtopic=highscores&list=$1&vocation=$2 | ||||
| RewriteRule ^highscores/([A-Za-z0-9-_']+)$ index.php?subtopic=highscores&list=$1 | ||||
| RewriteRule ^polls/([0-9]+)$ index.php?subtopic=polls&id=$1 | ||||
| RewriteRule ^admin/$ admin/index.php | ||||
| RewriteRule ^install/$ install/index.php | ||||
|  | ||||
| # temp solution >.> | ||||
| RewriteCond %{REQUEST_FILENAME} !-f | ||||
| RewriteCond %{REQUEST_FILENAME} !-d | ||||
| RewriteRule ^([A-Za-z0-9-_]+)/?$ index.php?p=$1  [L] | ||||
| RewriteRule ^([A-Za-z0-9-_]+)/([A-Za-z0-9-_]+)?$ index.php?p=$1&action=$2  [L] | ||||
							
								
								
									
										159
									
								
								CHANGELOG
									
									
									
									
									
								
							
							
						
						| @@ -1,159 +0,0 @@ | ||||
| [0.3.0 - 28.08.2017] | ||||
| 	- added administration panel for screenshots management with auto thumbnail generator and image auto-resizing | ||||
| 	- added Twig template engine and moved some html-in-php code to it | ||||
| 	- automatically detect player country based on user location (IP) on create account | ||||
| 	- player sex (gender) is now configurable at $config['genders'] | ||||
| 	- fixed recovering account and changing password when salt is enabled | ||||
| 	- fixed installing samples when for example Rook Sample already exist and other samples not | ||||
| 	- fixed some mysql error when character you trying to create already exist | ||||
| 	- fixed some warning when you select nonexistent country | ||||
| 	- password change minimal/maximal length notice is now more precise | ||||
| 	- added 'enabled' field in myaac_hooks table, which can enable or disable specified hook | ||||
| 	- removed DEFAULT '' for TEXT field. It didn't worked under some systems like MAC OS X. | ||||
| 	- minimum PHP version to install the MyAAC is now 5.2.0 cause of pathinfo (extension) function | ||||
| 	- removed unused admin stylish template | ||||
| 	- removed some unused cities field from myaac_spells table | ||||
| 	- moved news adding at installation from schema.sql to finish.php | ||||
| 	- some optimizations | ||||
|  | ||||
| [0.2.4 - 09.06.2017] | ||||
| 	- fixed invite to guild | ||||
| 	- added id field on monsters, so you can delete them in phpmyadmin | ||||
| 	- fixed adding some creatures with ' and " | ||||
| 	- fixed when there are spaces at beginning of the file (creatures) | ||||
| 	- fixed when file is unable to parse (creatures) | ||||
| 	- fixed typo loss_items => loss_containers | ||||
| 	- more elegant way of showing message on reload creatures and spells | ||||
|  | ||||
| [0.2.3 - 31.05.2017] | ||||
| 	- fixed guild management on OTHire 0.0.3 | ||||
| 	- set default skills to 10 when creating new character | ||||
| 	- fixed displaying of "Create forum thread" in newses | ||||
| 	- fixed deleting guild on servers that use players.rank_id field | ||||
| 	- fixed phpmailer class loading (https://otland.net/threads/myaac-v0-0-1.251454/page-8#post-2445222) | ||||
| 	- fixed displaying vocation amount on online page | ||||
| 	- better support for custom vocations, you just need to set in config vocations_amount to yours. | ||||
| 	- fixed huge space in player name (https://otland.net/threads/myaac-v0-0-1.251454/page-7#post-2444328) | ||||
| 	- fixed Undefined variable (https://otland.net/threads/myaac-v0-0-1.251454/page-7#post-2444034) | ||||
| 	- fixed Undefined offset (https://otland.net/threads/myaac-v0-0-1.251454/page-7#post-2444035) | ||||
|  | ||||
| [0.2.2 - 22.05.2017] | ||||
| 	- added missing cache/signature directory | ||||
| 	- fixed https://otland.net/threads/myaac-v0-0-1.251454/page-7#post-2443868 | ||||
|  | ||||
| [0.2.1 - 21.05.2017] | ||||
| 	- added Swedish translation by Sizaro | ||||
| 	- fixed some bugs with installlation & characters & houses | ||||
|  | ||||
| [0.2.0 - 21.05.2017] | ||||
| 	- added option to change character sex for premium points | ||||
| 	- moved site_closed to database, now you can close your site through admin panel | ||||
| 	- added option to admin panel: clear cache | ||||
| 	- added experiencetable_rows configurable | ||||
| 	- optimized OTS_Account->getGroupId(), now its using like 20 queries less | ||||
| 	- optimized OTS_Player->load($id) function, should be much faster now | ||||
| 	- fixed displaying on highscores special outfits | ||||
| 	- fixed skull images displaying | ||||
| 	- fixed displaying unlimited premium account | ||||
| 	- fixed bug where players.lookaddons doesn't exist (OTHire etc.) (https://otland.net/threads/myaac-v0-0-1.251454/page-6#post-2442407) | ||||
| 	- fixed signature tibian for OTHire and other servers that doesnt use accounts.premdays field | ||||
| 	- fixed when player name in signature containst space | ||||
| 	- don't show "Create forum thread" when editing | ||||
| 	- fixed red color table after create account | ||||
| 	- updated download links, as clients.halfaway.net isn't working anymore | ||||
| 	- fixed some bugs while installing when field `email_next` or `hidden` already exist | ||||
| 	- fixed movies unexpected comment | ||||
| 	- added template_place_holder('center_top') to kathrine template | ||||
|  | ||||
| [0.1.5 - 13.05.2017] | ||||
| 	- fixed bug with "Integrity constraint violation: 1048 Column 'ip' cannot be null" | ||||
|  | ||||
| [0.1.4 - 13.05.2017] | ||||
| 	- added outfit shower, in characters, online, and highscores | ||||
| 	- updated database to version 2 | ||||
| 	- fixed item images (now using item-images.ots.me host by default) | ||||
| 	- fixed news ticket and posting long newses (https://otland.net/threads/myaac-v0-0-1.251454/page-5#post-2442026) | ||||
| 	- news body limit increased to 65535 (mysql text field) | ||||
| 	- removed some unused code from my old server | ||||
| 	- added spells & monsters to kathrine template | ||||
|  | ||||
| [0.1.3 - 11.05.2017] | ||||
| 	- this is just release to update version number | ||||
|  | ||||
| [0.1.2 - 11.05.2017] | ||||
| 	- forgot to update CHANGELOG and MYAAC_VERSION | ||||
|  | ||||
| [0.1.1 - 11.05.2017] | ||||
| 	- fixed updating myaac_config with database_version to 1 | ||||
| 	- fixed database updater | ||||
|  | ||||
| [0.1.0 - 11.05.2017] | ||||
| 	- added new feature: change character name for premium points (disabled by default, you can enable it in config under account_change_character_name in config.php) | ||||
| 	- added automatic database updater (data migrations) | ||||
| 	- renamed events to hooks | ||||
| 	- moved hooks to database | ||||
| 	- now you can use hooks in plugins | ||||
| 	- set account.type field to 5 on install, if TFS 1.0+ | ||||
| 	- added example plugin | ||||
| 	- new, latest google analytics code | ||||
| 	- fixed bug with loading account.name that has numbers in it | ||||
| 	- fixed many bugs in player editor in admin panel | ||||
| 	- added error handling to plugin manager and some more verification in | ||||
| 	- file has been correctly unpacked/uploaded | ||||
| 	- fixed Statistics page in admin panel when using account.number | ||||
| 	- fixed bug when creating/recovering account on servers with | ||||
| 	- account.salt field (TFS 0.3 for example) | ||||
| 	- fixed forum showing thread with html tags (added from news manager) | ||||
| 	- new, latest code for youtube videos in movies page | ||||
| 	- fixed showing vocation images when using $config['online_vocations_images'] | ||||
| 	- many fixes in polls (also importing proper schema) | ||||
| 	- fixed hovering on buttons in kathrine template (on accountmanagement page) | ||||
| 	- fixed signatures (many fixes) | ||||
| 	- added missing gesior signature system | ||||
|  | ||||
| [0.0.6 - 06.05.2017] | ||||
| 	- fixed bug while installing (https://otland.net/threads/myaac-v0-0-1.251454/page-3#post-2440543) | ||||
| 	- fixed bug when creating character (not showing errors) (one more time) | ||||
| 	- fixed support for TFS 0.2 series | ||||
| 	- added FAQ link | ||||
| 	 | ||||
| [0.0.5 - 05.05.2017] | ||||
| 	- fixed bug when creating character (not showing errors) | ||||
| 	- Fixed characters loading with names that has been created with other AAC | ||||
| 	- fixed links to shop in default template | ||||
| 	- fixed some weird PHP 7.1 warnings/notices | ||||
| 	- Fixed config loading with some weird comments | ||||
| 	- fixed bug with status info utf8 encoding (https://otland.net/threads/myaac-v0-0-1.251454/page-2#post-2440259) | ||||
| 	- fixed when ip in log_action is NULL (https://otland.net/threads/myaac-v0-0-1.251454/page-2#post-2440357) | ||||
| 	- fixed bug when guild doesn't exist on characters page (https://otland.net/threads/myaac-v0-0-1.251454/page-2#post-2440320) | ||||
| 	- disabled friendly_urls by default | ||||
| 	- fixes when $config['database_*'] is set | ||||
| 	- added CHANGELOG | ||||
|  | ||||
| [0.0.3 - 03.05.2017] | ||||
| 	- Full support for OTHire 0.0.3 | ||||
| 	- added support for otservers that doesn't use account.name field, instead just account number will be used | ||||
| 	- fixed encryption detection on TFS 0.3 | ||||
| 	- fixed bug when server_config table doesn't exist | ||||
| 	- (install) moved admin account creation to new step | ||||
| 	- fixed news comment link | ||||
| 	- by default, the installer creates now the Admin player, for admin account | ||||
| 	- fixed installation errors | ||||
| 	- fixed config.lua loading with some weird comments | ||||
|  | ||||
| [0.0.2 - 02.05.2017] | ||||
| 	- updated forum links to use friendly_urls | ||||
| 	- some more info will be shown when cannot connect to database | ||||
| 	- show more error infos when creating character | ||||
| 	- fixed forum link on newses | ||||
| 	- fixed spells loading when there's vocation name instead of id | ||||
| 	- fixed bug when you have changed template but it doesn't exist anymore | ||||
| 	- fixed vocations with promotion loading | ||||
| 	- fixed support for gesior pages and templates | ||||
| 	- added function OTS_Acount:getGroupId() | ||||
|  | ||||
| [0.0.1 - 01.05.2017] | ||||
| 	This is first official release of MyAAC. | ||||
| 	Features are listed here | ||||
|  | ||||
| 	For more information, see the release announcement on OTLand: https://otland.net/threads/myaac-v0-0-1.251454/ | ||||
							
								
								
									
										55
									
								
								CHANGELOG.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,55 @@ | ||||
| # Changelog | ||||
|  | ||||
| ## [0.9.0-alpha - 02.06.2023] | ||||
|  | ||||
| Minimum PHP version for this release is 7.2.5. | ||||
|  | ||||
| ### Added | ||||
| * reworked Admin Panel (@Leesneaks, @gpedro, @slawkens) | ||||
|   * updated to Bootstrap v4 | ||||
|   * new Menu | ||||
|   * new Dashboard: statistics, server status | ||||
|   * new Admin Bar showed on top when admin logged in | ||||
|   * new page: Server Data, to reload server data | ||||
|   * new pages: mass account & teleport tools | ||||
|   * changelogs editor | ||||
|   * revised Accounts & Players editors | ||||
|   * option to add/modify menus with plugins | ||||
|   * option to enable/disable plugins | ||||
|   * better, updated TinyMCE editor (v6.x) | ||||
|     * with option to upload images | ||||
|   * list of open source libraries used in project | ||||
| * brand new charming installation page (by @fernandomatos) | ||||
|   * using Bootstrap | ||||
| * new pages router: nikic/fast-route, allowing for better customisation | ||||
| * Guild Wars support (available as plugin) | ||||
| * support for login and create account only by email (configurable) | ||||
|   * with no need for account name | ||||
| * Google ReCAPTCHA v3 support (available as plugin) | ||||
| * automatically load towns names from .OTBM file | ||||
| * support for Account Number | ||||
|   * suggest account number option | ||||
| * many new functions, hooks and configurables | ||||
| * better Exception Handler (Whoops - https://github.com/filp/whoops) | ||||
| * add Cypress testing | ||||
|  | ||||
| ### Changed | ||||
| * Composer is now used for external libraries like: Twig, PHPMailer, fast-route etc. | ||||
| * mail support is disabled on fresh install, can be manually enabled by user | ||||
| * disable add php pages in admin panel for security. Option to disable plugins upload | ||||
| * visitors counter shows now user browser, and also if its bot | ||||
| * changes in required and optional PHP extensions | ||||
| * reworked Pages: | ||||
| 	* Bans | ||||
| 		* works now for TFS 1.x | ||||
| 	* Highscores | ||||
| 		* frags works for TFS 1.x | ||||
| 		* cached | ||||
| 	* creatures | ||||
| * moved pages to Twig: | ||||
|   * experience stages | ||||
| * update player_deaths entries on name change | ||||
| * change_password email to be more informal | ||||
|  | ||||
| ### Fixed | ||||
| * hundrets of bug fixes, mostly patched from 0.8, so it makes no sense writing them again here | ||||
							
								
								
									
										14
									
								
								CONTRIBUTORS.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,14 @@ | ||||
| # automatically exported using this script: | ||||
| # git log --all --format='%cN <%cE>' | sort -u > contributors | ||||
| # in no particular order | ||||
| # cleaned for readability | ||||
|  | ||||
| Evil Puncker <EPuncker@users.noreply.github.com> | ||||
| Fernando Matos <fernando@pixele.com.br> | ||||
| Lee <42119604+Leesneaks@users.noreply.github.com> | ||||
| caio <caio.zucoli@gmail.com> | ||||
| slawkens <slawkens@gmail.com> | ||||
| tobi132 <52947952+tobi132@users.noreply.github.com> | ||||
| vankk <nwtr.otland@hotmail.com> | ||||
| whiteblXK <krzys16001@gmail.com> | ||||
| xitobuh <jonas.hockert92@gmail.com> | ||||
							
								
								
									
										3
									
								
								CREDITS
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,3 @@ | ||||
| * Gesior.pl (2007 - 2008) | ||||
| * Slawkens (2009 - 2023) | ||||
| * Contributors listed in CONTRIBUTORS.txt | ||||
							
								
								
									
										60
									
								
								README.md
									
									
									
									
									
								
							
							
						
						| @@ -1,18 +1,26 @@ | ||||
| # myaac | ||||
| # [MyAAC](https://my-aac.org) | ||||
|  | ||||
| [](https://travis-ci.org/github/slawkens/myaac) | ||||
| [](https://opensource.org/licenses/gpl-license) | ||||
| [](https://github.com/slawkens/myaac/releases) | ||||
| [](https://github.com/slawkens/myaac/blob/d8b3b4135827ee17e3c6d41f08a925e718c587ed/.travis.yml#L3) | ||||
| [](https://discord.gg/2J39Wus) | ||||
| [](https://github.com/slawkens/myaac/issues?q=is%3Aissue+is%3Aclosed) | ||||
|  | ||||
| MyAAC is a free and open-source Automatic Account Creator (AAC) written in PHP. It is a fork of the [Gesior](https://github.com/gesior/Gesior2012) project. It supports only MySQL databases. | ||||
|  | ||||
| Official website: http://my-aac.org | ||||
| Official website: https://my-aac.org | ||||
|  | ||||
| ### REQUIREMENTS | ||||
| ### Requirements | ||||
|  | ||||
| 	- PHP 5.2.0 or later | ||||
| 	- PHP 5.6 or later | ||||
| 	- MySQL database | ||||
| 	- PDO PHP Extension | ||||
| 	- XML PHP Extension | ||||
| 	- ZIP PHP Extension | ||||
| 	- (optional) mod_rewrite to use friendly_urls | ||||
|  | ||||
| ### INSTALLATION AND CONFIGURATION | ||||
| ### Installation | ||||
|  | ||||
| 	Just decompress and untar the source (which you should have done by now, | ||||
| 	if you're reading this), into your webserver's document root. | ||||
| @@ -27,19 +35,45 @@ Official website: http://my-aac.org | ||||
| 			chmod 660 config.local.php | ||||
| 			chmod 660 images/guilds | ||||
| 			chmod 660 images/houses | ||||
| 			chmod 660 images/screenshots | ||||
| 			chmod 660 images/gallery | ||||
| 			chmod -R 760 system/cache | ||||
|  | ||||
| 	Visit http://your_domain/install (http://localhost/install) and follow instructions in the browser. | ||||
|  | ||||
| ### KNOWN PROBLEMS | ||||
| ### Configuration | ||||
|  | ||||
| 	- none - | ||||
| Check *config.php* to get more informations. | ||||
| Use *config.local.php* for your local configuration changes. | ||||
|  | ||||
| ### OTHER NOTES | ||||
| ### Branches | ||||
|  | ||||
| 	If you have a great idea or want contribute to the project - visit our website at http://www.my-aac.org | ||||
| This repository follows the Git Flow Workflow. | ||||
| Cheatsheet: [Git-Flow-Cheetsheet](https://danielkummer.github.io/git-flow-cheatsheet) | ||||
|  | ||||
| ### LICENSING | ||||
| That means, we use: | ||||
| * master branch, for current stable release | ||||
| * develop branch, for development version (next release) | ||||
| * feature branches, for features etc. | ||||
|  | ||||
| 	This program and all associated files are released under the GNU Public | ||||
| 	License, see LICENSE for details. | ||||
| ### Known Problems | ||||
|  | ||||
| - Some compatibility issues with some exotical distibutions. | ||||
|  | ||||
| ### Contributing | ||||
|  | ||||
| Contributions are more than welcome.  | ||||
|  | ||||
| Pull requests should be made to the *develop* branch as that is the working branch, master is for release code.   | ||||
|  | ||||
| Bug fixes to current release should be done to master branch. | ||||
|  | ||||
| Look: [Contributing](https://github.com/otsoft/myaac/wiki/Contributing) in our wiki. | ||||
|  | ||||
| ### Other Notes | ||||
|  | ||||
| 	If you have a great idea or want contribute to the project - visit our website at https://www.my-aac.org | ||||
|  | ||||
| ### License | ||||
|  | ||||
| This program and all associated files are released under the GNU Public License.   | ||||
| See [LICENSE](https://github.com/slawkens/myaac/blob/master/LICENSE) for details. | ||||
|   | ||||
							
								
								
									
										1
									
								
								_config.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1 @@ | ||||
| theme: jekyll-theme-slate | ||||
							
								
								
									
										
											BIN
										
									
								
								admin/images/logo.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 4.3 KiB | 
| @@ -1,49 +1,87 @@ | ||||
| <?php | ||||
|  | ||||
| // few things we'll need | ||||
| require('../common.php'); | ||||
| require_once(BASE . 'config.local.php'); | ||||
| require '../common.php'; | ||||
|  | ||||
| const ADMIN_PANEL = true; | ||||
| const MYAAC_ADMIN = true; | ||||
|  | ||||
| if(file_exists(BASE . 'config.local.php')) { | ||||
| 	require_once BASE . 'config.local.php'; | ||||
| } | ||||
|  | ||||
| if(file_exists(BASE . 'install') && (!isset($config['installed']) || !$config['installed'])) | ||||
| { | ||||
| 	header('Location: ' . BASE_URL . 'install/'); | ||||
| 	die('Setup detected that <b>install/</b> directory exists. Please visit <a href="' . BASE_URL . 'install">this</a> url to start MyAAC Installation.<br/>Delete <b>install/</b> directory if you already installed MyAAC.<br/>Remember to REFRESH this page when you\'re done!'); | ||||
| 	throw new RuntimeException('Setup detected that <b>install/</b> directory exists. Please visit <a href="' . BASE_URL . 'install">this</a> url to start MyAAC Installation.<br/>Delete <b>install/</b> directory if you already installed MyAAC.<br/>Remember to REFRESH this page when you\'re done!'); | ||||
| } | ||||
|  | ||||
| $content = ''; | ||||
|  | ||||
| // validate page | ||||
| $page = isset($_GET['p']) ? $_GET['p'] : ''; | ||||
| if(empty($page) || preg_match("/[^a-zA-Z0-9_\-]/", $page)) | ||||
| $page = $_GET['p'] ?? ''; | ||||
| if(empty($page) || preg_match("/[^a-zA-Z0-9_\-\/.]/", $page)) | ||||
| 	$page = 'dashboard'; | ||||
|  | ||||
| $page = strtolower($page); | ||||
| define('PAGE', $page); | ||||
|  | ||||
| require(SYSTEM . 'functions.php'); | ||||
| require(SYSTEM . 'init.php'); | ||||
| require(SYSTEM . 'status.php'); | ||||
| require(SYSTEM . 'login.php'); | ||||
| require(ADMIN . 'includes/functions.php'); | ||||
| require SYSTEM . 'functions.php'; | ||||
| require SYSTEM . 'init.php'; | ||||
|  | ||||
| // verify myaac tables exists in database | ||||
| if(!$db->hasTable('myaac_account_actions')) { | ||||
| 	throw new RuntimeException('Seems that the table <strong>myaac_account_actions</strong> of MyAAC doesn\'t exist in the database. This is a fatal error. You can try to reinstall MyAAC by visiting <a href="' . BASE_URL . 'install">this</a> url.'); | ||||
| } | ||||
|  | ||||
| if(config('env') === 'dev') { | ||||
| 	ini_set('display_errors', 1); | ||||
| 	ini_set('display_startup_errors', 1); | ||||
| 	error_reporting(E_ALL); | ||||
| } | ||||
|  | ||||
| // event system | ||||
| require_once SYSTEM . 'hooks.php'; | ||||
| $hooks = new Hooks(); | ||||
| $hooks->load(); | ||||
|  | ||||
| require SYSTEM . 'status.php'; | ||||
| require SYSTEM . 'login.php'; | ||||
| require SYSTEM . 'migrate.php'; | ||||
| require __DIR__ . '/includes/functions.php'; | ||||
|  | ||||
| $twig->addGlobal('config', $config); | ||||
| $twig->addGlobal('status', $status); | ||||
|  | ||||
| if (ACTION == 'logout') { | ||||
| 	require SYSTEM . 'logout.php'; | ||||
| } | ||||
|  | ||||
| // if we're not logged in - show login box | ||||
| if(!$logged || !admin()) { | ||||
| 	$page = 'login'; | ||||
| } | ||||
|  | ||||
| // include our page  | ||||
| $file = SYSTEM . 'pages/admin/' . $page . '.php'; | ||||
| // include our page | ||||
| $file = __DIR__ . '/pages/' . $page . '.php'; | ||||
| if(!@file_exists($file)) { | ||||
| 	$page = '404'; | ||||
| 	$file = SYSTEM . 'pages/404.php'; | ||||
| 	if (strpos($page, 'plugins/') !== false) { | ||||
| 		$file = BASE . $page; | ||||
| 	} | ||||
| 	else { | ||||
| 		$page = '404'; | ||||
| 		$file = SYSTEM . 'pages/404.php'; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| ob_start(); | ||||
| include($file); | ||||
| if($hooks->trigger(HOOK_ADMIN_BEFORE_PAGE)) { | ||||
| 	require $file; | ||||
| } | ||||
|  | ||||
| $content .= ob_get_contents(); | ||||
| ob_end_clean(); | ||||
|  | ||||
| // template | ||||
| $template_path = 'template/'; | ||||
| require(ADMIN . $template_path . 'template.php'); | ||||
| ?> | ||||
| require __DIR__ . '/' . $template_path . 'template.php'; | ||||
|   | ||||
							
								
								
									
										599
									
								
								admin/pages/accounts.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,599 @@ | ||||
| <?php | ||||
| /** | ||||
|  * Account editor | ||||
|  * | ||||
|  * @package   MyAAC | ||||
|  * @author    Lee | ||||
|  * @copyright 2020 MyAAC | ||||
|  * @link      https://my-aac.org | ||||
|  */ | ||||
| defined('MYAAC') or die('Direct access not allowed!'); | ||||
|  | ||||
| $title = 'Account editor'; | ||||
| $admin_base = ADMIN_URL . '?p=accounts'; | ||||
| $use_datatable = true; | ||||
|  | ||||
| if ($config['account_country']) | ||||
| 	require SYSTEM . 'countries.conf.php'; | ||||
|  | ||||
| $nameOrNumberColumn = 'name'; | ||||
| if (USE_ACCOUNT_NUMBER) { | ||||
| 	$nameOrNumberColumn = 'number'; | ||||
| } | ||||
|  | ||||
| $hasSecretColumn = $db->hasColumn('accounts', 'secret'); | ||||
| $hasCoinsColumn = $db->hasColumn('accounts', 'coins'); | ||||
| $hasPointsColumn = $db->hasColumn('accounts', 'premium_points'); | ||||
| $hasTypeColumn = $db->hasColumn('accounts', 'type'); | ||||
| $hasGroupColumn = $db->hasColumn('accounts', 'group_id'); | ||||
|  | ||||
| if ($config['account_country']) { | ||||
| 	$countries = array(); | ||||
| 	foreach (array('pl', 'se', 'br', 'us', 'gb') as $c) | ||||
| 		$countries[$c] = $config['countries'][$c]; | ||||
|  | ||||
| 	$countries['--'] = '----------'; | ||||
| 	foreach ($config['countries'] as $code => $c) | ||||
| 		$countries[$code] = $c; | ||||
| } | ||||
| $web_acc = ACCOUNT_WEB_FLAGS; | ||||
| $acc_type = config('account_types'); | ||||
| ?> | ||||
|  | ||||
| <link rel="stylesheet" type="text/css" href="<?php echo BASE_URL; ?>tools/css/jquery.datetimepicker.css"/ > | ||||
| <script src="<?php echo BASE_URL; ?>tools/js/jquery.datetimepicker.js"></script> | ||||
|  | ||||
| <?php | ||||
| $id = 0; | ||||
| $search_account = ''; | ||||
| if (isset($_REQUEST['id'])) | ||||
| 	$id = (int)$_REQUEST['id']; | ||||
| else if (isset($_REQUEST['search'])) { | ||||
| 	$search_account = $_REQUEST['search']; | ||||
| 	if (strlen($search_account) < 3 && !Validator::number($search_account)) { | ||||
| 		echo_error('Player name is too short.'); | ||||
| 	} else { | ||||
| 		$query = $db->query('SELECT `id` FROM `accounts` WHERE `' . $nameOrNumberColumn . '` = ' . $db->quote($search_account)); | ||||
| 		if ($query->rowCount() == 1) { | ||||
| 			$query = $query->fetch(); | ||||
| 			$id = (int)$query['id']; | ||||
| 		} else { | ||||
| 			$query = $db->query('SELECT `id`, `' . $nameOrNumberColumn . '` FROM `accounts` WHERE `' . $nameOrNumberColumn . '` LIKE ' . $db->quote('%' . $search_account . '%')); | ||||
| 			if ($query->rowCount() > 0 && $query->rowCount() <= 10) { | ||||
| 				$str_construct = 'Do you mean?<ul class="mb-0">'; | ||||
| 				foreach ($query as $row) | ||||
| 					$str_construct .= '<li><a href="' . $admin_base . '&id=' . $row['id'] . '">' . $row[$nameOrNumberColumn] . '</a></li>'; | ||||
| 				$str_construct .= '</ul>'; | ||||
| 				echo_error($str_construct); | ||||
| 			} else if ($query->rowCount() > 10) | ||||
| 				echo_error('Specified name resulted with too many accounts.'); | ||||
| 			else | ||||
| 				echo_error('No entries found.'); | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| ?> | ||||
| <div class="row"> | ||||
| 	<?php | ||||
| 	if ($id > 0) { | ||||
| 		$account = new OTS_Account(); | ||||
| 		$account->load($id); | ||||
|  | ||||
| 		if (isset($account, $_POST['save']) && $account->isLoaded()) { | ||||
| 			$error = false; | ||||
|  | ||||
| 			$_error = ''; | ||||
| 			$account_db = new OTS_Account(); | ||||
| 			if (USE_ACCOUNT_NAME) { | ||||
| 				$name = $_POST['name']; | ||||
|  | ||||
| 				$account_db->find($name); | ||||
| 				if ($account_db->isLoaded() && $account->getName() != $name) | ||||
| 					echo_error('This name is already used. Please choose another name!'); | ||||
| 			} | ||||
|  | ||||
| 			$account_db->load($id); | ||||
| 			if (!$account_db->isLoaded()) | ||||
| 				echo_error('Account with this id doesn\'t exist.'); | ||||
|  | ||||
| 			//type/group | ||||
| 			if ($hasTypeColumn || $hasGroupColumn) { | ||||
| 				$group = $_POST['group']; | ||||
| 			} | ||||
|  | ||||
| 			$password = ((!empty($_POST["pass"]) ? $_POST['pass'] : null)); | ||||
| 			if (!Validator::password($password)) { | ||||
| 				$errors['password'] = Validator::getLastError(); | ||||
| 			} | ||||
|  | ||||
| 			//secret | ||||
| 			if ($hasSecretColumn) { | ||||
| 				$secret = $_POST['secret']; | ||||
| 			} | ||||
|  | ||||
| 			//key | ||||
| 			$key = $_POST['key']; | ||||
| 			$email = $_POST['email']; | ||||
| 			if (!Validator::email($email)) | ||||
| 				$errors['email'] = Validator::getLastError(); | ||||
|  | ||||
| 			//tibia coins | ||||
| 			if ($hasCoinsColumn) { | ||||
| 				$t_coins = $_POST['t_coins']; | ||||
| 				verify_number($t_coins, 'Tibia coins', 12); | ||||
| 			} | ||||
| 			// prem days | ||||
| 			$p_days = (int)$_POST['p_days']; | ||||
| 			verify_number($p_days, 'Prem days', 11); | ||||
|  | ||||
| 			//prem points | ||||
| 			$p_points = $_POST['p_points']; | ||||
| 			verify_number($p_points, 'Prem Points', 11); | ||||
|  | ||||
| 			//rl name | ||||
| 			$rl_name = $_POST['rl_name']; | ||||
|  | ||||
| 			//location | ||||
| 			$rl_loca = $_POST['rl_loca']; | ||||
|  | ||||
| 			//country | ||||
| 			$rl_country = $_POST['rl_country']; | ||||
|  | ||||
| 			$web_flags = $_POST['web_flags']; | ||||
| 			verify_number($web_flags, 'Web Flags', 1); | ||||
|  | ||||
| 			//created | ||||
| 			$created = strtotime($_POST['created']); | ||||
| 			verify_number($created, 'Created', 11); | ||||
|  | ||||
| 			//web last login | ||||
| 			$web_lastlogin = strtotime($_POST['web_lastlogin']); | ||||
| 			verify_number($web_lastlogin, 'Web Last login', 11); | ||||
|  | ||||
| 			if (!$error && $hooks->trigger(HOOK_ADMIN_ACCOUNTS_SAVE_POST, ['account_id' => $account->getId(), 'account_email' =>  $account->getEMail()])) { | ||||
| 				if (USE_ACCOUNT_NAME) { | ||||
| 					$account->setName($name); | ||||
| 				} | ||||
|  | ||||
| 				if ($hasTypeColumn) { | ||||
| 					$account->setCustomField('type', $group); | ||||
| 				} elseif ($hasGroupColumn) { | ||||
| 					$account->setCustomField('group_id', $group); | ||||
| 				} | ||||
|  | ||||
| 				if ($hasSecretColumn) { | ||||
| 					$account->setCustomField('secret', $secret); | ||||
| 				} | ||||
| 				$account->setCustomField('key', $key); | ||||
| 				$account->setEMail($email); | ||||
| 				if ($hasCoinsColumn) { | ||||
| 					$account->setCustomField('coins', $t_coins); | ||||
| 				} | ||||
|  | ||||
| 				$lastDay = 0; | ||||
| 				if($p_days != 0 && $p_days != OTS_Account::GRATIS_PREMIUM_DAYS) { | ||||
| 					$lastDay = time(); | ||||
| 				} else if ($lastDay != 0) { | ||||
| 					$lastDay = 0; | ||||
| 				} | ||||
|  | ||||
| 				$account->setPremDays($p_days); | ||||
| 				$account->setLastLogin($lastDay); | ||||
| 				if ($hasPointsColumn) { | ||||
| 					$account->setCustomField('premium_points', $p_points); | ||||
| 				} | ||||
| 				$account->setRLName($rl_name); | ||||
| 				$account->setLocation($rl_loca); | ||||
| 				$account->setCountry($rl_country); | ||||
| 				$account->setCustomField('created', $created); | ||||
| 				$account->setWebFlags($web_flags); | ||||
| 				$account->setCustomField('web_lastlogin', $web_lastlogin); | ||||
|  | ||||
| 				if (isset($password)) { | ||||
| 					if (USE_ACCOUNT_SALT) { | ||||
| 						$salt = generateRandomString(10, false, true, true); | ||||
| 						$password = $salt . $password; | ||||
| 						$account->setCustomField('salt', $salt); | ||||
| 					} | ||||
|  | ||||
| 					$password = encrypt($password); | ||||
| 					$account->setPassword($password); | ||||
|  | ||||
| 					if (USE_ACCOUNT_SALT) | ||||
| 						$account->setCustomField('salt', $salt); | ||||
| 				} | ||||
|  | ||||
| 				$account->save(); | ||||
| 				echo_success('Account saved at: ' . date('G:i')); | ||||
| 			} | ||||
| 		} | ||||
| 	} else if ($id == 0) { | ||||
| 		$accounts_db = $db->query('SELECT `id`, `' . $nameOrNumberColumn . '`' . ($hasTypeColumn ? ',type' : ($hasGroupColumn ? ',group_id' : '')) . ' FROM `accounts` ORDER BY `id` ASC'); | ||||
| 		?> | ||||
| 		<div class="col-12 col-sm-12 col-lg-10"> | ||||
| 			<div class="card card-info card-outline"> | ||||
| 				<div class="card-header"> | ||||
| 					<h5 class="m-0">Accounts</h5> | ||||
| 				</div> | ||||
| 				<div class="card-body"> | ||||
| 					<table class="acc_datatable table table-striped table-bordered table-responsive d-md-table"> | ||||
| 						<thead> | ||||
| 						<tr> | ||||
| 							<th>ID</th> | ||||
| 							<th><?= ($nameOrNumberColumn == 'number' ? 'Number' : 'Name'); ?></th> | ||||
| 							<?php if($hasTypeColumn || $hasGroupColumn): ?> | ||||
| 							<th>Position</th> | ||||
| 							<?php endif; ?> | ||||
| 							<th style="width: 40px">Edit</th> | ||||
| 						</tr> | ||||
| 						</thead> | ||||
| 						<tbody> | ||||
| 						<?php foreach ($accounts_db as $account_lst): ?> | ||||
| 							<tr> | ||||
| 								<th><?php echo $account_lst['id']; ?></th> | ||||
| 								<td><?php echo $account_lst[$nameOrNumberColumn]; ?></a></td> | ||||
| 								<?php if($hasTypeColumn || $hasGroupColumn): ?> | ||||
| 								<td> | ||||
| 									<?php if ($hasTypeColumn) { | ||||
| 										echo $acc_type[$account_lst['type']]; | ||||
| 									} elseif ($hasGroupColumn) { | ||||
| 										$group = $groups->getGroups(); | ||||
| 										echo $group[$account_lst['group_id']]; | ||||
| 									} ?> | ||||
| 								</td> | ||||
| 								<?php endif; ?> | ||||
| 								<td><a href="?p=accounts&id=<?php echo $account_lst['id']; ?>" class="btn btn-success btn-sm" title="Edit"> | ||||
| 										<i class="fas fa-pencil-alt"></i> | ||||
| 									</a> | ||||
| 								</td> | ||||
| 							</tr> | ||||
| 						<?php endforeach; ?> | ||||
| 						</tbody> | ||||
| 					</table> | ||||
| 				</div> | ||||
| 			</div> | ||||
| 		</div> | ||||
| 	<?php } ?> | ||||
|  | ||||
| 	<?php if (isset($account) && $account->isLoaded()) { ?> | ||||
| 		<div class="col-12 col-sm-12 col-lg-10"> | ||||
| 			<div class="card card-primary card-outline card-outline-tabs"> | ||||
| 				<div class="card-header p-0 border-bottom-0"> | ||||
| 					<ul class="nav nav-tabs" id="accounts-tab" role="tablist"> | ||||
| 						<li class="nav-item"> | ||||
| 							<a class="nav-link active" id="accounts-acc-tab" data-toggle="pill" href="#accounts-acc">Account</a> | ||||
| 						</li> | ||||
| 						<li class="nav-item"> | ||||
| 							<a class="nav-link" id="accounts-chars-tab" data-toggle="pill" href="#accounts-chars">Characters</a> | ||||
| 						</li> | ||||
| 						<?php if ($db->hasTable('bans')) : ?> | ||||
| 							<li class="nav-item"> | ||||
| 								<a class="nav-link" id="accounts-bans-tab" data-toggle="pill" href="#accounts-bans">Bans</a> | ||||
| 							</li> | ||||
| 						<?php endif; | ||||
|  | ||||
| 						if ($db->hasTable('store_history')) : ?> | ||||
| 							<li class="nav-item"> | ||||
| 								<a class="nav-link" id="accounts-store-tab" data-toggle="pill" href="#accounts-store">Store History</a> | ||||
| 							</li> | ||||
| 						<?php endif; ?> | ||||
| 					</ul> | ||||
| 				</div> | ||||
| 				<div class="card-body"> | ||||
| 					<div class="tab-content" id="accounts-tabContent"> | ||||
| 						<div class="tab-pane fade active show" id="accounts-acc"> | ||||
| 							<form action="<?php echo $admin_base . ((isset($id) && $id > 0) ? '&id=' . $id : ''); ?>" method="post"> | ||||
| 								<div class="form-group row"> | ||||
| 									<?php if (USE_ACCOUNT_NAME): ?> | ||||
| 										<div class="col-12 col-sm-12 col-lg-4"> | ||||
| 											<label for="name">Account Name:</label> | ||||
| 											<input type="text" class="form-control" id="name" name="name" autocomplete="off" value="<?php echo $account->getName(); ?>"/> | ||||
| 										</div> | ||||
| 									<?php elseif (USE_ACCOUNT_NUMBER): ?> | ||||
| 										<div class="col-12 col-sm-12 col-lg-4"> | ||||
| 											<label for="name">Account Number:</label> | ||||
| 											<input type="text" class="form-control" id="name" name="name" autocomplete="off" value="<?php echo $account->getNumber(); ?>"/> | ||||
| 										</div> | ||||
| 									<?php endif; ?> | ||||
| 									<div class="col-12 col-sm-12 col-lg-5"> | ||||
| 										<div class="form-check"> | ||||
| 											<input type="checkbox" | ||||
| 												   name="c_pass" | ||||
| 												   id="c_pass" | ||||
| 												   value="false" | ||||
| 												   class="form-check-input"/> | ||||
| 											<label for="c_pass">Password: (check to change)</label> | ||||
| 										</div> | ||||
| 										<div class="input-group"> | ||||
| 											<input type="text" class="form-control" id="pass" name="pass" autocomplete="off" maxlength="20" value=""/> | ||||
| 										</div> | ||||
| 									</div> | ||||
| 									<div class="col-12 col-sm-12 col-lg-3"> | ||||
| 										<label for="account_id" class="control-label">Account ID:</label> | ||||
| 										<input type="text" class="form-control" id="account_id" name="account_id" autocomplete="off" size="8" maxlength="11" disabled value="<?php echo $account->getId(); ?>"/> | ||||
| 									</div> | ||||
| 								</div> | ||||
| 								<div class="form-group row"> | ||||
| 									<?php | ||||
| 									$acc_group = $account->getAccGroupId(); | ||||
| 									if ($hasTypeColumn) { | ||||
| 										?> | ||||
| 										<div class="col-12 col-sm-12 col-lg-6"> | ||||
| 											<label for="group">Account Type:</label> | ||||
| 											<select name="group" id="group" class="form-control"> | ||||
| 												<?php foreach ($acc_type as $id => $a_type): ?> | ||||
| 													<option value="<?php echo($id); ?>" <?php echo($acc_group == ($id) ? 'selected' : ''); ?>><?php echo $a_type; ?></option> | ||||
| 												<?php endforeach; ?> | ||||
| 											</select> | ||||
| 										</div> | ||||
| 										<?php | ||||
| 									} elseif ($hasGroupColumn) { | ||||
| 										?> | ||||
| 										<div class="col-12 col-sm-12 col-lg-6"> | ||||
| 											<label for="group">Account Type:</label> | ||||
| 											<select name="group" id="group" class="form-control"> | ||||
| 												<?php foreach ($groups->getGroups() as $id => $group): ?> | ||||
| 													<option value="<?php echo $id; ?>" <?php echo($acc_group == $id ? 'selected' : ''); ?>><?php echo $group->getName(); ?></option> | ||||
| 												<?php endforeach; ?> | ||||
| 											</select> | ||||
| 										</div> | ||||
| 									<?php } ?> | ||||
| 									<div class="col-12 col-sm-12 col-lg-6"> | ||||
| 										<label for="web_flags">Website Access:</label> | ||||
| 										<select name="web_flags" id="web_flags" class="form-control"> | ||||
| 											<?php foreach ($web_acc as $id => $a_type): ?> | ||||
| 												<option value="<?php echo($id); ?>" <?php echo($account->getWebFlags() == ($id) ? 'selected' : ''); ?>><?php echo $a_type; ?></option> | ||||
| 											<?php endforeach; ?> | ||||
| 										</select> | ||||
| 									</div> | ||||
| 								</div> | ||||
| 								<div class="form-group row"> | ||||
| 									<?php if ($hasSecretColumn): ?> | ||||
| 										<div class="col-12 col-sm-12 col-lg-6"> | ||||
| 											<label for="secret">Secret:</label> | ||||
| 											<input type="text" class="form-control" id="secret" name="secret" autocomplete="off" value="<?php echo $account->getCustomField('secret'); ?>"/> | ||||
| 										</div> | ||||
| 									<?php endif; ?> | ||||
| 									<div class="col-12 col-sm-12 col-lg-6"> | ||||
| 										<label for="key">Recovery Key:</label> | ||||
| 										<input type="text" class="form-control" id="key" name="key" autocomplete="off" value="<?php echo $account->getCustomField('key'); ?>"/> | ||||
| 									</div> | ||||
| 								</div> | ||||
| 								<div class="form-group row"> | ||||
| 									<div class="col-12 col-sm-12 col-lg-6"> | ||||
| 										<label for="email">Email:</label><?php echo (config('mail_enabled') ? ' (<a href="' . ADMIN_URL . '?p=mailer&mail_to=' . $account->getEMail() . '">Send Mail</a>)' : ''); ?> | ||||
| 										<input type="text" class="form-control" id="email" name="email" autocomplete="off" value="<?php echo $account->getEMail(); ?>"/> | ||||
| 									</div> | ||||
| 									<?php if ($hasCoinsColumn): ?> | ||||
| 										<div class="col-12 col-sm-12 col-lg-6"> | ||||
| 											<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') ?>"/> | ||||
| 										</div> | ||||
| 									<?php endif; ?> | ||||
| 									<div class="col-12 col-sm-12 col-lg-6"> | ||||
| 										<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(); ?>"/> | ||||
| 									</div> | ||||
| 									<?php if ($hasPointsColumn): ?> | ||||
| 										<div class="col-12 col-sm-12 col-lg-6"> | ||||
| 											<label for="p_points" class="control-label">Premium Points:</label> | ||||
| 											<input type="text" class="form-control" id="p_points" name="p_points" autocomplete="off" maxlength="8" value="<?php echo $account->getCustomField('premium_points') ?>"/> | ||||
| 										</div> | ||||
| 									<?php endif; ?> | ||||
| 								</div> | ||||
| 								<div class="form-group row"> | ||||
| 									<div class="col-12 col-sm-12 col-lg-4"> | ||||
| 										<label for="rl_name">RL Name:</label> | ||||
| 										<input type="text" class="form-control" id="rl_name" name="rl_name" | ||||
| 											   autocomplete="off" maxlength="20" | ||||
| 											   value="<?php echo $account->getRLName(); ?>"/> | ||||
| 									</div> | ||||
| 									<div class="col-12 col-sm-12 col-lg-4"> | ||||
| 										<label for="rl_loca">Location:</label> | ||||
| 										<input type="text" class="form-control" id="rl_loca" name="rl_loca" | ||||
| 											   autocomplete="off" maxlength="20" | ||||
| 											   value="<?php echo $account->getLocation(); ?>"/> | ||||
| 									</div> | ||||
| 									<div class="col-12 col-sm-12 col-lg-4"> | ||||
| 										<label for="rl_country">Country:</label> | ||||
| 										<select name="rl_country" id="rl_country" class="form-control"> | ||||
| 											<?php foreach ($countries as $id => $a_type): ?> | ||||
| 												<option value="<?php echo($id); ?>" <?php echo($account->getCountry() == ($id) ? 'selected' : ''); ?>><?php echo $a_type; ?></option> | ||||
| 											<?php endforeach; ?> | ||||
| 										</select> | ||||
| 									</div> | ||||
| 								</div> | ||||
| 								<div class="form-group row"> | ||||
| 									<div class="col-12 col-sm-12 col-lg-6"> | ||||
| 										<label for="created" class="control-label">Created:</label> | ||||
| 										<input type="text" class="form-control" id="created" name="created" autocomplete="off" maxlength="20" value="<?php echo date("M d Y, H:i:s", $account->getCustomField('created')); ?>"/> | ||||
| 									</div> | ||||
| 									<div class="col-12 col-sm-12 col-lg-6"> | ||||
| 										<label for="web_lastlogin" class="control-label">Web Last Login:</label> | ||||
| 										<input type="text" class="form-control" id="web_lastlogin" name="web_lastlogin" autocomplete="off" maxlength="20" value="<?php echo date("M d Y, H:i:s", $account->getCustomField('web_lastlogin')); ?>"/> | ||||
| 									</div> | ||||
| 								</div> | ||||
|  | ||||
| 								<input type="hidden" name="save" value="yes"/> | ||||
|  | ||||
| 								<button type="submit" class="btn btn-info"><i class="fas fa-update"></i> Update</button> | ||||
| 								<a href="<?php echo ADMIN_URL; ?>?p=accounts" class="btn btn-danger float-right"><i class="fas fa-cancel"></i> Cancel</a> | ||||
| 							</form> | ||||
| 						</div> | ||||
| 						<div class="tab-pane fade" id="accounts-chars"> | ||||
| 							<div class="row"> | ||||
| 								<?php | ||||
| 								if (isset($account) && $account->isLoaded()) { | ||||
| 									$account_players = $account->getPlayersList(); | ||||
| 									$account_players->orderBy('id'); | ||||
| 									if (isset($account_players)) { ?> | ||||
| 										<table class="table table-striped table-condensed table-responsive d-md-table"> | ||||
| 											<thead> | ||||
| 											<tr> | ||||
| 												<th>#</th> | ||||
| 												<th>Name</th> | ||||
| 												<th>Level</th> | ||||
| 												<th>Vocation</th> | ||||
| 												<th style="width: 40px">Edit</th> | ||||
| 											</tr> | ||||
| 											</thead> | ||||
| 											<tbody> | ||||
| 											<?php $i= 0; | ||||
| 											foreach ($account_players as $i => $player): | ||||
| 												$i++; | ||||
| 												$player_vocation = $player->getVocation(); | ||||
| 												$player_promotion = $player->getPromotion(); | ||||
| 												if (isset($player_promotion)) { | ||||
| 													if ((int)$player_promotion > 0) | ||||
| 														$player_vocation += ($player_promotion * $config['vocations_amount']); | ||||
| 												} | ||||
|  | ||||
| 												if (isset($config['vocations'][$player_vocation])) { | ||||
| 													$vocation_name = $config['vocations'][$player_vocation]; | ||||
| 												} ?> | ||||
| 												<tr> | ||||
| 													<th><?php echo $i; ?></th> | ||||
| 													<td><?php echo $player->getName(); ?></td> | ||||
| 													<td><?php echo $player->getLevel(); ?></td> | ||||
| 													<td><?php echo $vocation_name; ?></td> | ||||
| 													<td><a href="?p=players&id=<?php echo $player->getId() ?>" class=" btn btn-success btn-sm" title="Edit"><i class="fas fa-pencil-alt"></i></a></td> | ||||
| 												</tr> | ||||
| 											<?php endforeach ?> | ||||
| 											</tbody> | ||||
| 										</table> | ||||
| 										<?php | ||||
| 									} | ||||
| 								} ?> | ||||
| 							</div> | ||||
| 						</div> | ||||
| 						<?php if ($db->hasTable('bans')) : ?> | ||||
| 							<div class="tab-pane fade" id="accounts-bans"> | ||||
| 								<?php | ||||
| 								$bans = $db->query('SELECT * FROM ' . $db->tableName('bans') . ' WHERE ' . $db->fieldName('active') . ' = 1 AND ' . $db->fieldName('id') . ' = ' . $account->getId() . ' ORDER BY ' . $db->fieldName('added') . ' DESC LIMIT 10'); | ||||
| 								if ($bans->rowCount()) { | ||||
| 									?> | ||||
| 									<table class="table table-striped table-condensed table-responsive d-md-table"> | ||||
| 										<thead> | ||||
| 										<tr> | ||||
| 											<th>Nick</th> | ||||
| 											<th>Type</th> | ||||
| 											<th>Expires</th> | ||||
| 											<th>Reason</th> | ||||
| 											<th>Comment</th> | ||||
| 											<th>Added by:</th> | ||||
| 										</tr> | ||||
| 										</thead> | ||||
| 										<tbody> | ||||
| 										<?php | ||||
| 										foreach ($bans as $ban) { | ||||
| 											?> | ||||
| 											<tr> | ||||
| 												<td><?php | ||||
| 													$pName = getPlayerNameByAccount($ban['value']); | ||||
| 													echo '<a href="?p=players&search=' . $pName . '">' . $pName . '</a>'; ?> | ||||
| 												</td> | ||||
| 												<td><?php echo getBanType($ban['type']); ?></td> | ||||
| 												<td> | ||||
| 													<?php | ||||
| 													if ($ban['expires'] == "-1") | ||||
| 														echo 'Never'; | ||||
| 													else | ||||
| 														echo date("H:i:s", $ban['expires']) . '<br/>' . date("d M Y", $ban['expires']); | ||||
| 													?> | ||||
| 												</td> | ||||
| 												<td><?php echo getBanReason($ban['reason']); ?></td> | ||||
| 												<td><?php echo $ban['comment']; ?></td> | ||||
| 												<td> | ||||
| 													<?php | ||||
| 													if ($ban['admin_id'] == "0") | ||||
| 														echo 'Autoban'; | ||||
| 													else | ||||
| 														$aName = getPlayerNameByAccount($ban['admin_id']); | ||||
| 													echo '<a href="?p=players&search=' . $aName . '">' . $aName . '</a>'; | ||||
| 													echo '<br/>' . date("d.m.Y", $ban['added']); | ||||
| 													?> | ||||
| 												</td> | ||||
| 											</tr> | ||||
| 										<?php } ?> | ||||
| 										</tbody> | ||||
| 									</table> | ||||
| 									<?php | ||||
| 								} else { | ||||
| 									echo 'No Account bans.'; | ||||
| 								} ?> | ||||
| 							</div> | ||||
| 						<?php endif; | ||||
| 						if ($db->hasTable('store_history')) { ?> | ||||
| 							<div class="tab-pane fade" id="accounts-store"> | ||||
| 								<?php $store_history = $db->query('SELECT * FROM `store_history` WHERE `account_id` = "' . $account->getId() . '" ORDER BY `time` DESC')->fetchAll(); ?> | ||||
| 								<table class="table table-striped table-condensed table-responsive d-md-table"> | ||||
| 									<thead> | ||||
| 									<tr> | ||||
| 										<th>Description</th> | ||||
| 										<th>Coins</th> | ||||
| 										<th>Date</th> | ||||
| 									</tr> | ||||
| 									</thead> | ||||
| 									<tbody> | ||||
| 									<?php foreach ($store_history as $p): ?> | ||||
| 										<tr> | ||||
| 											<td><?php echo $p['description']; ?></td> | ||||
| 											<td><?php echo $p['coin_amount']; ?></td> | ||||
| 											<td><?php echo date('d M y H:i:s', $p['time']); ?></td> | ||||
| 										</tr> | ||||
| 									<?php endforeach; ?> | ||||
| 									</tbody> | ||||
| 								</table> | ||||
| 							</div> | ||||
| 						<?php } ?> | ||||
| 					</div> | ||||
| 				</div> | ||||
| 			</div> | ||||
| 		</div> | ||||
| 	<?php } ?> | ||||
| 	<div class="col-12 col-sm-12 col-lg-2"> | ||||
| 		<div class="card card-info card-outline"> | ||||
| 			<div class="card-header"> | ||||
| 				<h5 class="m-0">Search Accounts</h5> | ||||
| 			</div> | ||||
| 			<div class="card-body"> | ||||
| 				<div class="row"> | ||||
| 					<div class="col-6 col-lg-12"> | ||||
| 						<form action="<?php echo $admin_base; ?>" method="post"> | ||||
| 							<label for="name">Account Name:</label> | ||||
| 							<div class="input-group input-group-sm"> | ||||
| 								<input type="text" class="form-control" name="search" value="<?php echo $search_account; ?>" maxlength="32" size="32"> | ||||
| 								<span class="input-group-append"><button type="submit" class="btn btn-info btn-flat">Search</button></span> | ||||
| 							</div> | ||||
| 						</form> | ||||
| 					</div> | ||||
| 					<div class="col-6 col-lg-12"> | ||||
| 						<form action="<?php echo $admin_base; ?>" method="post"> | ||||
| 							<label for="name">Account ID:</label> | ||||
| 							<div class="input-group input-group-sm"> | ||||
| 								<input type="text" class="form-control" name="id" value="" maxlength="32" size="32"> | ||||
| 								<span class="input-group-append"><button type="submit" class="btn btn-info btn-flat">Search</button></span> | ||||
| 							</div> | ||||
| 						</form> | ||||
| 					</div> | ||||
| 				</div> | ||||
| 			</div> | ||||
| 		</div> | ||||
| 	</div> | ||||
| </div> | ||||
| <script> | ||||
| 	$(document).ready(function () { | ||||
| 		$('#created').datetimepicker({format: "M d Y, H:i:s",}); | ||||
| 		$('#web_lastlogin').datetimepicker({format: 'M d Y, H:i:s'}); | ||||
|  | ||||
| 		$('#c_pass').change(function () { | ||||
| 			const ipass = $('input[name=pass]'); | ||||
| 			ipass[0].disabled = !this.checked; | ||||
| 			ipass[0].value = ''; | ||||
| 		}).change(); | ||||
|  | ||||
| 		$('.acc_datatable').DataTable({ | ||||
| 			"order": [[0, "asc"]] | ||||
| 		}); | ||||
| 	}); | ||||
| </script> | ||||
							
								
								
									
										139
									
								
								admin/pages/changelog.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,139 @@ | ||||
| <?php | ||||
| /** | ||||
|  * CHANGELOG modifier | ||||
|  * | ||||
|  * @package   MyAAC | ||||
|  * @author    Slawkens <slawkens@gmail.com> | ||||
|  * @author    Lee | ||||
|  * @copyright 2020 MyAAC | ||||
|  * @link      https://my-aac.org | ||||
|  */ | ||||
| defined('MYAAC') or die('Direct access not allowed!'); | ||||
|  | ||||
| if (!hasFlag(FLAG_CONTENT_PAGES) && !superAdmin()) { | ||||
| 	echo 'Access denied.'; | ||||
| 	return; | ||||
| } | ||||
|  | ||||
| $title = 'Changelog'; | ||||
| $use_datatable = true; | ||||
| const CL_LIMIT = 600; // maximum changelog body length | ||||
| ?> | ||||
|  | ||||
| <link rel="stylesheet" type="text/css" href="<?php echo BASE_URL; ?>tools/css/jquery.datetimepicker.css"/ > | ||||
| <script src="<?php echo BASE_URL; ?>tools/js/jquery.datetimepicker.js"></script> | ||||
| <?php | ||||
| $id = $_GET['id'] ?? 0; | ||||
| require_once LIBS . 'changelog.php'; | ||||
|  | ||||
| if(!empty($action)) | ||||
| { | ||||
| 	$id = $_REQUEST['id'] ?? null; | ||||
| 	$body = isset($_REQUEST['body']) ? stripslashes($_REQUEST['body']) : null; | ||||
| 	$create_date = isset($_REQUEST['createdate']) ? (int)strtotime($_REQUEST['createdate'] ): null; | ||||
| 	$player_id = isset($_REQUEST['player_id']) ? (int)$_REQUEST['player_id'] : null; | ||||
| 	$type = isset($_REQUEST['type']) ? (int)$_REQUEST['type'] : null; | ||||
| 	$where = isset($_REQUEST['where']) ? (int)$_REQUEST['where'] : null; | ||||
|  | ||||
| 	$errors = array(); | ||||
|  | ||||
| 	if($action == 'new') { | ||||
|  | ||||
| 		if(isset($body) && Changelog::add($body, $type, $where, $player_id, $create_date, $errors)) { | ||||
| 			$body = ''; | ||||
| 			$type = $where = $player_id = $create_date = 0; | ||||
|  | ||||
| 			success("Added successful."); | ||||
| 		} | ||||
| 	} | ||||
| 	else if($action == 'delete') { | ||||
| 		Changelog::delete($id, $errors); | ||||
| 		success("Deleted successful."); | ||||
| 	} | ||||
| 	else if($action == 'edit') | ||||
| 	{ | ||||
| 		if(isset($id) && !isset($body)) { | ||||
| 			$cl = Changelog::get($id); | ||||
| 			$body = $cl['body']; | ||||
| 			$type = $cl['type']; | ||||
| 			$where = $cl['where']; | ||||
| 			$create_date = $cl['date']; | ||||
| 			$player_id = $cl['player_id']; | ||||
| 		} | ||||
| 		else { | ||||
| 			if(Changelog::update($id, $body, $type, $where, $player_id, $create_date,$errors)) { | ||||
| 				$action = $body = ''; | ||||
| 				$type = $where = $player_id = $create_date = 0; | ||||
|  | ||||
| 				success("Updated successful."); | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	else if($action == 'hide') { | ||||
| 		Changelog::toggleHidden($id, $errors, $status); | ||||
| 		success(($status == 1 ? 'Show' : 'Hide') . " successful."); | ||||
| 	} | ||||
|  | ||||
| 	if(!empty($errors)) | ||||
| 		error(implode(", ", $errors)); | ||||
| } | ||||
|  | ||||
| $changelogs = $db->query('SELECT * FROM `' . TABLE_PREFIX . 'changelog' . '` ORDER BY `id` DESC')->fetchAll(); | ||||
|  | ||||
| $i = 0; | ||||
|  | ||||
| $log_type = [ | ||||
| 	['id' => 1, 'icon' => 'added'], | ||||
| 	['id' => 2, 'icon' => 'removed'], | ||||
| 	['id' => 3, 'icon' => 'changed'], | ||||
| 	['id' => 4, 'icon' => 'fixed'], | ||||
| ]; | ||||
|  | ||||
| $log_where = [ | ||||
| 	['id' => 1, 'icon' => 'server'], | ||||
| 	['id' => 2, 'icon' => 'website'], | ||||
| ]; | ||||
|  | ||||
| foreach($changelogs as $key => &$log) | ||||
| { | ||||
| 	$log['type'] = getChangelogType($log['type']); | ||||
| 	$log['where'] = getChangelogWhere($log['where']); | ||||
| } | ||||
|  | ||||
| if($action == 'edit' || $action == 'new') { | ||||
| 	if($action == 'edit') { | ||||
| 		$player = new OTS_Player(); | ||||
| 		$player->load($player_id); | ||||
| 	} | ||||
|  | ||||
| 	$account_players = $account_logged->getPlayersList(); | ||||
| 	$account_players->orderBy('group_id', POT::ORDER_DESC); | ||||
| 	$twig->display('admin.changelog.form.html.twig', array( | ||||
| 		'action' => $action, | ||||
| 		'cl_link_form' => constant('ADMIN_URL').'?p=changelog&action=' . ($action == 'edit' ? 'edit' : 'new'), | ||||
| 		'cl_id' => $id ?? null, | ||||
| 		'body' => isset($body) ? escapeHtml($body) : '', | ||||
| 		'create_date' => $create_date ?? '', | ||||
| 		'player_id' => $player_id ?? null, | ||||
| 		'account_players' => $account_players, | ||||
| 		'type' => $type ?? 0, | ||||
| 		'where' => $where ?? 0, | ||||
| 		'log_type' => $log_type, | ||||
| 		'log_where' => $log_where, | ||||
| 	)); | ||||
| } | ||||
| $twig->display('admin.changelog.html.twig', array( | ||||
| 	'changelogs' => $changelogs, | ||||
| )); | ||||
|  | ||||
| ?> | ||||
| <script> | ||||
| 	$(document).ready(function () { | ||||
| 		$('#createdate').datetimepicker({format: "M d Y, H:i:s",}); | ||||
|  | ||||
| 		$('.tb_datatable').DataTable({ | ||||
| 			"order": [[0, "desc"]], | ||||
| 			"columnDefs": [{targets: [1, 2,4,5],orderable: false}] | ||||
| 		}); | ||||
| 	}); | ||||
| </script> | ||||
							
								
								
									
										25
									
								
								admin/pages/clmd.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,25 @@ | ||||
| <?php | ||||
| /** | ||||
|  * CHANGELOG viewer | ||||
|  * | ||||
|  * @package   MyAAC | ||||
|  * @author    Slawkens <slawkens@gmail.com> | ||||
|  * @author    Lee | ||||
|  * @copyright 2020 MyAAC | ||||
|  * @link      https://my-aac.org | ||||
|  */ | ||||
| defined('MYAAC') or die('Direct access not allowed!'); | ||||
| $title = 'MyAAC Changelog'; | ||||
|  | ||||
| if (!file_exists(BASE . 'CHANGELOG.md')) { | ||||
| 	echo 'File CHANGELOG.md doesn\'t exist.'; | ||||
| 	return; | ||||
| } | ||||
|  | ||||
| $changelog = file_get_contents(BASE . 'CHANGELOG.md'); | ||||
|  | ||||
| $Parsedown = new Parsedown(); | ||||
|  | ||||
| $changelog = $Parsedown->text($changelog); # prints: <p>Hello <em>Parsedown</em>!</p> | ||||
|  | ||||
| echo '<div>' . $changelog . '</div>'; | ||||
							
								
								
									
										62
									
								
								admin/pages/dashboard.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,62 @@ | ||||
| <?php | ||||
| /** | ||||
|  * Dashboard | ||||
|  * | ||||
|  * @package   MyAAC | ||||
|  * @author    Slawkens <slawkens@gmail.com> | ||||
|  * @copyright 2019 MyAAC | ||||
|  * @link      https://my-aac.org | ||||
|  */ | ||||
| defined('MYAAC') or die('Direct access not allowed!'); | ||||
| $title = 'Dashboard'; | ||||
|  | ||||
| if (isset($_GET['clear_cache'])) { | ||||
| 	if (clearCache()) { | ||||
| 		success('Cache cleared.'); | ||||
| 	} else { | ||||
| 		error('Error while clearing cache.'); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| if (isset($_GET['maintenance'])) { | ||||
| 	$message = (!empty($_POST['message']) ? $_POST['message'] : null); | ||||
| 	$_status = (isset($_POST['status']) && $_POST['status'] == 'true'); | ||||
| 	$_status = ($_status ? '0' : '1'); | ||||
|  | ||||
| 	if (empty($message)) { | ||||
| 		error('Message cannot be empty.'); | ||||
| 	} else if (strlen($message) > 255) { | ||||
| 		error('Message is too long. Maximum length allowed is 255 chars.'); | ||||
| 	} else { | ||||
| 		$tmp = ''; | ||||
| 		if (fetchDatabaseConfig('site_closed', $tmp)) | ||||
| 			updateDatabaseConfig('site_closed', $_status); | ||||
| 		else | ||||
| 			registerDatabaseConfig('site_closed', $_status); | ||||
|  | ||||
| 		if (fetchDatabaseConfig('site_closed_message', $tmp)) | ||||
| 			updateDatabaseConfig('site_closed_message', $message); | ||||
| 		else | ||||
| 			registerDatabaseConfig('site_closed_message', $message); | ||||
| 	} | ||||
| } | ||||
| $is_closed = getDatabaseConfig('site_closed') == '1'; | ||||
|  | ||||
| $closed_message = 'Server is under maintenance, please visit later.'; | ||||
| $tmp = ''; | ||||
| if (fetchDatabaseConfig('site_closed_message', $tmp)) | ||||
| 	$closed_message = $tmp; | ||||
|  | ||||
| $configAdminPanelModules = config('admin_panel_modules'); | ||||
| if (isset($configAdminPanelModules)) { | ||||
| 	echo '<div class="row">'; | ||||
| 	$configAdminPanelModules = explode(',', $configAdminPanelModules); | ||||
| 	$twig_loader->prependPath(__DIR__ . '/modules/templates'); | ||||
| 	foreach ($configAdminPanelModules as $box) { | ||||
| 		$file = __DIR__ . '/modules/' . $box . '.php'; | ||||
| 		if (file_exists($file)) { | ||||
| 			include($file); | ||||
| 		} | ||||
| 	} | ||||
| echo '</div>'; | ||||
| } | ||||
							
								
								
									
										13
									
								
								admin/pages/data.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,13 @@ | ||||
| <?php | ||||
| /** | ||||
|  * Load items.xml | ||||
|  * | ||||
|  * @package   MyAAC | ||||
|  * @author    Slawkens <slawkens@gmail.com> | ||||
|  * @copyright 2019 MyAAC | ||||
|  * @link      https://my-aac.org | ||||
|  */ | ||||
| defined('MYAAC') or die('Direct access not allowed!'); | ||||
| $title = 'Server Data'; | ||||
|  | ||||
| $twig->display('admin.data.html.twig'); | ||||
							
								
								
									
										24
									
								
								admin/pages/login.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,24 @@ | ||||
| <?php | ||||
| /** | ||||
|  * Login | ||||
|  * | ||||
|  * @package   MyAAC | ||||
|  * @author    Slawkens <slawkens@gmail.com> | ||||
|  * @copyright 2019 MyAAC | ||||
|  * @link      https://my-aac.org | ||||
|  */ | ||||
| defined('MYAAC') or die('Direct access not allowed!'); | ||||
| $title = 'Login'; | ||||
|  | ||||
| require PAGES . 'account/login.php'; | ||||
| if ($logged) { | ||||
| 	header('Location: ' . ADMIN_URL); | ||||
| 	return; | ||||
| } | ||||
|  | ||||
| $twig->display('admin.login.html.twig', [ | ||||
| 	'logout' => (ACTION == 'logout' ? 'You have  been logged out!'  : ''), | ||||
| 	'account' => USE_ACCOUNT_NAME ? 'Name' : 'Number', | ||||
| 	'account_login_by' => getAccountLoginByLabel(), | ||||
| 	'errors' => $errors ?? '' | ||||
| ]); | ||||
							
								
								
									
										83
									
								
								admin/pages/logs.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,83 @@ | ||||
| <?php | ||||
| /** | ||||
|  * Logs | ||||
|  * | ||||
|  * @package   MyAAC | ||||
|  * @author    Slawkens <slawkens@gmail.com> | ||||
|  * @copyright 2020 MyAAC | ||||
|  * @link      https://my-aac.org | ||||
|  */ | ||||
| defined('MYAAC') or die('Direct access not allowed!'); | ||||
| $title = 'Logs Viewer'; | ||||
| $use_datatable = true; | ||||
|  | ||||
| $files = array(); | ||||
| $aac_path_logs = BASE . 'system/logs/'; | ||||
| foreach (scandir($aac_path_logs, SCANDIR_SORT_ASCENDING) as $f) { | ||||
| 	if ($f[0] === '.' || is_dir($aac_path_logs . $f) || $f === 'index.html') { | ||||
| 		continue; | ||||
| 	} | ||||
|  | ||||
| 	$files[] = array($f, $aac_path_logs); | ||||
| } | ||||
|  | ||||
| $server_path_logs = $config['server_path'] . 'logs/'; | ||||
| if (!file_exists($server_path_logs)) { | ||||
| 	$server_path_logs = $config['data_path'] . 'logs/'; | ||||
| } | ||||
|  | ||||
| if (file_exists($server_path_logs)) { | ||||
| 	foreach (scandir($server_path_logs, SCANDIR_SORT_ASCENDING) as $f) { | ||||
| 		if ($f[0] === '.') { | ||||
| 			continue; | ||||
| 		} | ||||
|  | ||||
| 		if (is_dir($server_path_logs . $f)) { | ||||
| 			foreach (scandir($server_path_logs . $f, SCANDIR_SORT_ASCENDING) as $f2) { | ||||
| 				if ($f2[0] === '.') { | ||||
| 					continue; | ||||
| 				} | ||||
|  | ||||
| 				$files[] = array($f . '/' . $f2, $server_path_logs); | ||||
| 			} | ||||
|  | ||||
| 			continue; | ||||
| 		} | ||||
|  | ||||
| 		$files[] = array($f, $server_path_logs); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| foreach ($files as &$f) { | ||||
| 	$f['mtime'] = filemtime($f[1] . $f[0]); | ||||
| 	$f['name'] = $f[0]; | ||||
| } | ||||
| unset($f); | ||||
|  | ||||
|  | ||||
| define('EXIST_NONE', 0); | ||||
| define('EXIST_SERVER_LOG', 1); | ||||
| define('EXIST_AAC_LOG', 2); | ||||
|  | ||||
| $exist = EXIST_NONE; | ||||
| $file = isset($_GET['file']) ? $_GET['file'] : null; | ||||
| if (!empty($file)) { | ||||
| 	if (!preg_match('/[^A-z0-9\' _\/\-\.]/', $file)) { | ||||
| 		if (file_exists($aac_path_logs . $file)) { | ||||
| 			$exist = EXIST_AAC_LOG; | ||||
| 		} else if (file_exists($server_path_logs . $file)) { | ||||
| 			$exist = EXIST_SERVER_LOG; | ||||
| 		} else { | ||||
| 			echo 'Specified file does not exist.'; | ||||
| 		} | ||||
|  | ||||
| 		if ($exist !== EXIST_NONE) { | ||||
| 			$file_content = nl2br(file_get_contents(($exist === EXIST_SERVER_LOG ? $server_path_logs : $aac_path_logs) . $file)); | ||||
| 			$twig->display('admin.logs.view.html.twig', array('file' => $file, 'content' => $file_content)); | ||||
| 		} | ||||
| 	} else { | ||||
| 		echo 'Invalid file name specified.'; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| $twig->display('admin.logs.html.twig', array('files' => $files)); | ||||
							
								
								
									
										83
									
								
								admin/pages/mailer.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,83 @@ | ||||
| <?php | ||||
| /** | ||||
|  * Mailer | ||||
|  * | ||||
|  * @package   MyAAC | ||||
|  * @author    Slawkens <slawkens@gmail.com> | ||||
|  * @copyright 2019 MyAAC | ||||
|  * @link      https://my-aac.org | ||||
|  */ | ||||
| defined('MYAAC') or die('Direct access not allowed!'); | ||||
| $title = 'Mailer'; | ||||
|  | ||||
| if (!hasFlag(FLAG_CONTENT_MAILER) && !superAdmin()) { | ||||
| 	echo 'Access denied.'; | ||||
| 	return; | ||||
| } | ||||
|  | ||||
| if (!config('mail_enabled')) { | ||||
| 	echo 'Mail support disabled in config.'; | ||||
| 	return; | ||||
| } | ||||
|  | ||||
| $mail_to = isset($_REQUEST['mail_to']) ? stripslashes(trim($_REQUEST['mail_to'])) : null; | ||||
| $mail_subject = isset($_POST['mail_subject']) ? stripslashes($_POST['mail_subject']) : null; | ||||
| $mail_content = isset($_POST['mail_content']) ? stripslashes($_POST['mail_content']) : null; | ||||
|  | ||||
| if (isset($_POST['submit'])) { | ||||
| 	if (empty($mail_subject)) { | ||||
| 		warning('Please enter subject of the message.'); | ||||
| 	} | ||||
|  | ||||
| 	if (empty($mail_content)) { | ||||
| 		warning('Please enter content of the message.'); | ||||
| 	} | ||||
| } | ||||
| if (!empty($mail_to)) { | ||||
| 	if(!Validator::email($mail_to)) { | ||||
| 		warning('E-Mail is invalid.'); | ||||
| 	} | ||||
| 	else { | ||||
| 		if (!empty($mail_content) && !empty($mail_subject)) { | ||||
| 			if (_mail($mail_to, $mail_subject, $mail_content)) { | ||||
| 				success("Successfully mailed <strong>$mail_to</strong>"); | ||||
| 			} | ||||
| 			else { | ||||
| 				error("Error while sending mail to <strong>$mail_to</strong>. More info can be found in system/logs/mailer-error.log"); | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| if (!empty($mail_content) && !empty($mail_subject) && empty($mail_to)) { | ||||
| 	$success = 0; | ||||
| 	$failed = 0; | ||||
|  | ||||
| 	$add = ''; | ||||
| 	if (config('account_mail_verify')) { | ||||
| 		note('Note: Sending only to users with verified E-Mail.'); | ||||
| 		$add = ' AND `email_verified` = 1'; | ||||
| 	} | ||||
|  | ||||
| 	$query = $db->query('SELECT `email` FROM `accounts` WHERE `email` != ""' . $add); | ||||
| 	foreach ($query as $email) { | ||||
| 		if (_mail($email['email'], $mail_subject, $mail_content)) { | ||||
| 			$success++; | ||||
| 		} | ||||
| 		else { | ||||
| 			$failed++; | ||||
| 			echo '<br />'; | ||||
| 			error('An error occorred while sending email to <b>' . $email['email'] . '</b>. For Admin: More info can be found in system/logs/mailer-error.log'); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	success('Mailing finished.'); | ||||
| 	success("$success emails delivered."); | ||||
| 	warning("$failed emails failed."); | ||||
| } | ||||
|  | ||||
| $twig->display('admin.mailer.html.twig', [ | ||||
| 	'mail_to' => $mail_to, | ||||
| 	'mail_subject' => $mail_subject, | ||||
| 	'mail_content' => $mail_content | ||||
| ]); | ||||
							
								
								
									
										215
									
								
								admin/pages/mass_account.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,215 @@ | ||||
| <?php | ||||
|  | ||||
| /** | ||||
|  * Account Admin Tool | ||||
|  * | ||||
|  * @package   MyAAC | ||||
|  * @author    Slawkens <slawkens@gmail.com> | ||||
|  * @author    Lee | ||||
|  * @copyright 2020 MyAAC | ||||
|  * @link      https://my-aac.org | ||||
|  */ | ||||
| defined('MYAAC') or die('Direct access not allowed!'); | ||||
|  | ||||
| $title = 'Mass Account Actions'; | ||||
|  | ||||
| $hasCoinsColumn = $db->hasColumn('accounts', 'coins'); | ||||
| $hasPointsColumn = $db->hasColumn('accounts', 'premium_points'); | ||||
| $freePremium = $config['lua']['freePremium']; | ||||
|  | ||||
| function admin_give_points($points) | ||||
| { | ||||
| 	global $db, $hasPointsColumn; | ||||
|  | ||||
| 	if (!$hasPointsColumn) { | ||||
| 		displayMessage('Points not supported.'); | ||||
| 		return; | ||||
| 	} | ||||
|  | ||||
| 	$statement = $db->prepare('UPDATE `accounts` SET `premium_points` = `premium_points` + :points'); | ||||
| 	if (!$statement) { | ||||
| 		displayMessage('Failed to prepare query statement.'); | ||||
| 		return; | ||||
| 	} | ||||
|  | ||||
| 	if (!$statement->execute([ | ||||
| 		'points' => $points | ||||
| 	])) { | ||||
| 		displayMessage('Failed to add points.'); | ||||
| 		return; | ||||
| 	} | ||||
| 	displayMessage($points . ' points added to all accounts.', true); | ||||
| } | ||||
|  | ||||
| function admin_give_coins($coins) | ||||
| { | ||||
| 	global $db, $hasCoinsColumn; | ||||
|  | ||||
| 	if (!$hasCoinsColumn) { | ||||
| 		displayMessage('Coins not supported.'); | ||||
| 		return; | ||||
| 	} | ||||
|  | ||||
| 	$statement = $db->prepare('UPDATE `accounts` SET `coins` = `coins` + :coins'); | ||||
| 	if (!$statement) { | ||||
| 		displayMessage('Failed to prepare query statement.'); | ||||
| 		return; | ||||
| 	} | ||||
|  | ||||
| 	if (!$statement->execute([ | ||||
| 		'coins' => $coins | ||||
| 	])) { | ||||
| 		displayMessage('Failed to add coins.'); | ||||
| 		return; | ||||
| 	} | ||||
|  | ||||
| 	displayMessage($coins . ' coins added to all accounts.', true); | ||||
| } | ||||
|  | ||||
| function query_add_premium($column, $value_query, $condition_query = '1=1', $params = []) | ||||
| { | ||||
| 	global $db; | ||||
|  | ||||
| 	$statement = $db->prepare("UPDATE `accounts` SET `{$column}` = $value_query WHERE $condition_query"); | ||||
| 	if (!$statement) { | ||||
| 		displayMessage('Failed to prepare query statement.'); | ||||
| 		return false; | ||||
| 	} | ||||
|  | ||||
| 	if (!$statement->execute($params)) { | ||||
| 		displayMessage('Failed to add premium days.'); | ||||
| 		return false; | ||||
| 	} | ||||
|  | ||||
| 	return true; | ||||
| } | ||||
|  | ||||
| function admin_give_premdays($days) | ||||
| { | ||||
| 	global $db, $freePremium; | ||||
|  | ||||
| 	if ($freePremium) { | ||||
| 		displayMessage('Premium days not supported. Free Premium enabled.'); | ||||
| 		return; | ||||
| 	} | ||||
|  | ||||
| 	$value = $days * 86400; | ||||
| 	$now = time(); | ||||
| 	// othire | ||||
| 	if ($db->hasColumn('accounts', 'premend')) { | ||||
| 		// append premend | ||||
| 		if (query_add_premium('premend', '`premend` + :value', '`premend` > :now', ['value' => $value, 'now' => $now])) { | ||||
| 			// set premend | ||||
| 			if (query_add_premium('premend', ':value', '`premend` <= :now', ['value' => $now + $value, 'now' => $now])) { | ||||
| 				displayMessage($days . ' premium days added to all accounts.', true); | ||||
| 				return; | ||||
| 			} else { | ||||
| 				displayMessage('Failed to execute set query.'); | ||||
| 				return; | ||||
| 			} | ||||
| 		} else { | ||||
| 			displayMessage('Failed to execute append query.'); | ||||
| 			return; | ||||
| 		} | ||||
|  | ||||
| 		return; | ||||
| 	} | ||||
|  | ||||
| 	// tfs 0.x | ||||
| 	if ($db->hasColumn('accounts', 'premdays')) { | ||||
| 		// append premdays | ||||
| 		if (query_add_premium('premdays', '`premdays` + :value', '1=1', ['value' => $days])) { | ||||
| 			// append lastday | ||||
| 			if (query_add_premium('lastday', '`lastday` + :value', '`lastday` > :now', ['value' => $value, 'now' => $now])) { | ||||
| 				// set lastday | ||||
| 				if (query_add_premium('lastday', ':value', '`lastday` <= :now', ['value' => $now + $value, 'now' => $now])) { | ||||
| 					displayMessage($days . ' premium days added to all accounts.', true); | ||||
| 					return; | ||||
| 				} else { | ||||
| 					displayMessage('Failed to execute set query.'); | ||||
| 					return; | ||||
| 				} | ||||
|  | ||||
| 				return; | ||||
| 			} else { | ||||
| 				displayMessage('Failed to execute append query.'); | ||||
| 				return; | ||||
| 			} | ||||
| 		} else { | ||||
| 			displayMessage('Failed to execute set days query.'); | ||||
| 			return; | ||||
| 		} | ||||
|  | ||||
| 		return; | ||||
| 	} | ||||
|  | ||||
| 	// tfs 1.x | ||||
| 	if ($db->hasColumn('accounts', 'premium_ends_at')) { | ||||
| 		// append premium_ends_at | ||||
| 		if (query_add_premium('premium_ends_at', '`premium_ends_at` + :value', '`premium_ends_at` > :now', ['value' => $value, 'now' => $now])) { | ||||
| 			// set premium_ends_at | ||||
| 			if (query_add_premium('premium_ends_at', ':value', '`premium_ends_at` <= :now', ['value' => $now + $value, 'now' => $now])) { | ||||
| 				displayMessage($days . ' premium days added to all accounts.', true); | ||||
| 				return; | ||||
| 			} else { | ||||
| 				displayMessage('Failed to execute set query.'); | ||||
| 				return; | ||||
| 			} | ||||
| 		} else { | ||||
| 			displayMessage('Failed to execute append query.'); | ||||
| 			return; | ||||
| 		} | ||||
|  | ||||
| 		return; | ||||
| 	} | ||||
|  | ||||
| 	displayMessage('Premium Days not supported.'); | ||||
| } | ||||
|  | ||||
| if (isset($_POST['action']) && $_POST['action']) { | ||||
|  | ||||
| 	$action = $_POST['action']; | ||||
|  | ||||
| 	if (preg_match("/[^A-z0-9_\-]/", $action)) { | ||||
| 		displayMessage('Invalid action.'); | ||||
| 	} else { | ||||
| 		$value = isset($_POST['value']) ? intval($_POST['value']) : 0; | ||||
|  | ||||
| 		if (!$value) { | ||||
| 			displayMessage('Please fill all inputs'); | ||||
| 		} else { | ||||
| 			switch ($action) { | ||||
| 				case 'give-points': | ||||
| 					admin_give_points($value); | ||||
| 					break; | ||||
| 				case 'give-coins': | ||||
| 					admin_give_coins($value); | ||||
| 					break; | ||||
| 				case 'give-premdays': | ||||
| 					admin_give_premdays($value); | ||||
| 					break; | ||||
| 				default: | ||||
| 					displayMessage('Action ' . $action . 'not found.'); | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| else { | ||||
| 	$twig->display('admin.tools.account.html.twig', array( | ||||
| 		'hasCoinsColumn' => $hasCoinsColumn, | ||||
| 		'hasPointsColumn' => $hasPointsColumn, | ||||
| 		'freePremium' => $freePremium, | ||||
| 	)); | ||||
| } | ||||
|  | ||||
| function displayMessage($message, $success = false) { | ||||
| 	global $twig, $hasCoinsColumn, $hasPointsColumn, $freePremium; | ||||
|  | ||||
| 	$success ? success($message): error($message); | ||||
|  | ||||
| 	$twig->display('admin.tools.account.html.twig', array( | ||||
| 		'hasCoinsColumn' => $hasCoinsColumn, | ||||
| 		'hasPointsColumn' => $hasPointsColumn, | ||||
| 		'freePremium' => $freePremium, | ||||
| 	)); | ||||
| } | ||||
							
								
								
									
										116
									
								
								admin/pages/mass_teleport.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,116 @@ | ||||
| <?php | ||||
| /** | ||||
|  * Teleport Admin Tool | ||||
|  * | ||||
|  * @package   MyAAC | ||||
|  * @author    Slawkens <slawkens@gmail.com> | ||||
|  * @author    Lee | ||||
|  * @copyright 2020 MyAAC | ||||
|  * @link      https://my-aac.org | ||||
|  */ | ||||
| defined('MYAAC') or die('Direct access not allowed!'); | ||||
|  | ||||
| $title = 'Mass Teleport Actions'; | ||||
|  | ||||
| function admin_teleport_position($x, $y, $z) { | ||||
| 	global $db; | ||||
| 	$statement = $db->prepare('UPDATE `players` SET `posx` = :x, `posy` = :y, `posz` = :z'); | ||||
| 	if (!$statement) { | ||||
| 		displayMessage('Failed to prepare query statement.'); | ||||
| 		return; | ||||
| 	} | ||||
|  | ||||
| 	if (!$statement->execute([ | ||||
| 		'x' => $x, 'y' => $y, 'z' => $z | ||||
| 	])) { | ||||
| 		displayMessage('Failed to execute query.'); | ||||
| 		return; | ||||
| 	} | ||||
|  | ||||
| 	displayMessage('Player\'s position updated.', true); | ||||
| } | ||||
|  | ||||
| function admin_teleport_town($town_id) { | ||||
| 	global $db; | ||||
| 	$statement = $db->prepare('UPDATE `players` SET `town_id` = :town_id'); | ||||
| 	if (!$statement) { | ||||
| 		displayMessage('Failed to prepare query statement.'); | ||||
| 		return; | ||||
| 	} | ||||
|  | ||||
| 	if (!$statement->execute([ | ||||
| 		'town_id' => $town_id | ||||
| 	])) { | ||||
| 		displayMessage('Failed to execute query.'); | ||||
| 		return; | ||||
| 	} | ||||
|  | ||||
| 	displayMessage('Player\'s town updated.', true); | ||||
| } | ||||
|  | ||||
| if (isset($_POST['action']) && $_POST['action'])    { | ||||
|  | ||||
| 	$action = $_POST['action']; | ||||
|  | ||||
| 	if (preg_match("/[^A-z0-9_\-]/", $action)) { | ||||
| 		displayMessage('Invalid action.'); | ||||
| 	} else { | ||||
|  | ||||
| 		$playersOnline = 0; | ||||
| 		if($db->hasTable('players_online')) {// tfs 1.0 | ||||
| 			$query = $db->query('SELECT count(*) AS `count` FROM `players_online`'); | ||||
| 		} else { | ||||
| 			$query = $db->query('SELECT count(*) AS `count` FROM `players` WHERE `players`.`online` > 0'); | ||||
| 		} | ||||
|  | ||||
| 		$playersOnline = $query->fetch(PDO::FETCH_ASSOC); | ||||
| 		if ($playersOnline['count'] > 0) { | ||||
| 			displayMessage('Please, close the server before execute this action otherwise players will not be affected.'); | ||||
| 			return; | ||||
| 		} | ||||
|  | ||||
| 		$town_id = isset($_POST['town_id']) ? intval($_POST['town_id']) : null; | ||||
| 		$posx = isset($_POST['posx']) ? intval($_POST['posx']) : null; | ||||
| 		$posy = isset($_POST['posy']) ? intval($_POST['posy']) : null; | ||||
| 		$posz = isset($_POST['posz']) ? intval($_POST['posz']) : null; | ||||
| 		$to_temple = $_POST['to_temple'] ?? null; | ||||
|  | ||||
| 		switch ($action) { | ||||
| 			case 'set-town': | ||||
| 				if (!$town_id) { | ||||
| 					displayMessage('Please fill all inputs'); | ||||
| 					return; | ||||
| 				} | ||||
|  | ||||
| 				if (!isset($config['towns'][$town_id])) { | ||||
| 					displayMessage('Specified town does not exist'); | ||||
| 					return; | ||||
| 				} | ||||
|  | ||||
| 				admin_teleport_town($town_id); | ||||
| 				break; | ||||
| 			case 'set-position': | ||||
| 				if (!$to_temple &&  ($posx < 0 || $posx > 65535 || $posy < 0 || $posy > 65535|| $posz < 0 || $posz > 16)) { | ||||
| 					displayMessage('Invalid Position'); | ||||
| 					return; | ||||
| 				} | ||||
|  | ||||
| 				admin_teleport_position($posx, $posy, $posz); | ||||
| 				break; | ||||
| 			default: | ||||
| 				displayMessage('Action ' . $action . 'not found.'); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| } | ||||
| else { | ||||
| 	$twig->display('admin.tools.teleport.html.twig', array()); | ||||
| } | ||||
|  | ||||
|  | ||||
| function displayMessage($message, $success = false) { | ||||
| 	global $twig; | ||||
|  | ||||
| 	$success ? success($message): error($message); | ||||
| 	$twig->display('admin.tools.teleport.html.twig', array()); | ||||
| } | ||||
							
								
								
									
										139
									
								
								admin/pages/menus.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,139 @@ | ||||
| <?php | ||||
| /** | ||||
|  * Menus | ||||
|  * | ||||
|  * @package   MyAAC | ||||
|  * @author    Slawkens <slawkens@gmail.com> | ||||
|  * @copyright 2019 MyAAC | ||||
|  * @link      https://my-aac.org | ||||
|  */ | ||||
| defined('MYAAC') or die('Direct access not allowed!'); | ||||
| $title = 'Menus'; | ||||
|  | ||||
| if (!hasFlag(FLAG_CONTENT_MENUS) && !superAdmin()) { | ||||
| 	echo 'Access denied.'; | ||||
| 	return; | ||||
| } | ||||
|  | ||||
| if (isset($_REQUEST['template'])) { | ||||
| 	$template = $_REQUEST['template']; | ||||
|  | ||||
| 	if (isset($_REQUEST['menu'])) { | ||||
| 		$post_menu = $_REQUEST['menu']; | ||||
| 		$post_menu_link = $_REQUEST['menu_link']; | ||||
| 		$post_menu_blank = $_REQUEST['menu_blank']; | ||||
| 		$post_menu_color = $_REQUEST['menu_color']; | ||||
| 		if (count($post_menu) != count($post_menu_link)) { | ||||
| 			echo 'Menu count is not equal menu links. Something went wrong when sending form.'; | ||||
| 			return; | ||||
| 		} | ||||
|  | ||||
| 		$db->query('DELETE FROM `' . TABLE_PREFIX . 'menu` WHERE `template` = ' . $db->quote($template)); | ||||
| 		foreach ($post_menu as $category => $menus) { | ||||
| 			foreach ($menus as $i => $menu) { | ||||
| 				if (empty($menu)) // don't save empty menu item | ||||
| 					continue; | ||||
|  | ||||
| 				try { | ||||
| 					$db->insert(TABLE_PREFIX . 'menu', array('template' => $template, 'name' => $menu, 'link' => $post_menu_link[$category][$i], 'blank' => $post_menu_blank[$category][$i] == 'on' ? 1 : 0, 'color' => str_replace('#', '', $post_menu_color[$category][$i]), 'category' => $category, 'ordering' => $i)); | ||||
| 				} catch (PDOException $error) { | ||||
| 					warning('Error while adding menu item (' . $menu . '): ' . $error->getMessage()); | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		$cache = Cache::getInstance(); | ||||
| 		if ($cache->enabled()) { | ||||
| 			$cache->delete('template_menus'); | ||||
| 		} | ||||
| 		success('Saved at ' . date('H:i')); | ||||
| 	} | ||||
|  | ||||
| 	$file = TEMPLATES . $template . '/config.php'; | ||||
| 	if (file_exists($file)) { | ||||
| 		require_once $file; | ||||
| 	} else { | ||||
| 		echo 'Cannot find template config.php file.'; | ||||
| 		return; | ||||
| 	} | ||||
| 	if (!isset($config['menu_categories'])) { | ||||
| 		echo "No menu categories set in template config.php.<br/>This template doesn't support dynamic menus."; | ||||
| 		return; | ||||
| 	} | ||||
|  | ||||
| 	$title = 'Menus - ' . $template; | ||||
| 	?> | ||||
| 	<div align="center" class="text-center"> | ||||
| 		<p class="note">You are editing: <?= $template ?><br/><br/> | ||||
| 			Hint: You can drag menu items.<br/> | ||||
| 			Hint: Add links to external sites using: <b>http://</b> or <b>https://</b> prefix.<br/> | ||||
| 			Not all templates support blank and colorful links. | ||||
| 		</p> | ||||
| 	</div> | ||||
| 	<?php | ||||
| 	$menus = array(); | ||||
| 	$menus_db = $db->query('SELECT `name`, `link`, `blank`, `color`, `category`, `ordering` FROM `' . TABLE_PREFIX . 'menu` WHERE `enabled` = 1 AND `template` = ' . $db->quote($template) . ' ORDER BY `ordering` ASC;')->fetchAll(); | ||||
| 	foreach ($menus_db as $menu) { | ||||
| 		$menus[$menu['category']][] = array('name' => $menu['name'], 'link' => $menu['link'], 'blank' => $menu['blank'], 'color' => $menu['color'], 'ordering' => $menu['ordering']); | ||||
| 	} | ||||
| 	$last_id = array(); | ||||
| 	?> | ||||
| 	<form method="post" id="menus-form" action="?p=menus"> | ||||
| 		<input type="hidden" name="template" value="<?php echo $template ?>"/> | ||||
| 		<div class="row"> | ||||
| 			<?php foreach ($config['menu_categories'] as $id => $cat): ?> | ||||
| 				<div class="col-md-12 col-lg-6"> | ||||
| 					<div class="card card-info card-outline"> | ||||
| 						<div class="card-header"> | ||||
| 							<h5 class="m-0"><?php echo $cat['name'] ?> <i class="far fa-plus-square add-button" id="add-button-<?php echo $id ?>"></i></h5> | ||||
| 						</div> | ||||
| 						<div class="card-body"> | ||||
| 							<ul class="sortable" id="sortable-<?php echo $id ?>"> | ||||
| 								<?php | ||||
| 								if (isset($menus[$id])) { | ||||
| 									foreach ($menus[$id] as $i => $menu): | ||||
| 										?> | ||||
| 										<li class="ui-state-default" id="list-<?php echo $id ?>-<?php echo $i ?>"><label>Name:</label> <input type="text" name="menu[<?php echo $id ?>][]" value="<?php echo escapeHtml($menu['name']); ?>"/> | ||||
| 											<label>Link:</label> <input type="text" name="menu_link[<?php echo $id ?>][]" value="<?php echo $menu['link'] ?>"/> | ||||
| 											<input type="hidden" name="menu_blank[<?php echo $id ?>][]" value="0"/> | ||||
| 											<label><input class="blank-checkbox" type="checkbox" <?php echo($menu['blank'] == 1 ? 'checked' : '') ?>/><span title="Open in New Window">New Window</span></label> | ||||
| 											<input class="color-picker" type="text" name="menu_color[<?php echo $id ?>][]" value="#<?php echo $menu['color'] ?>"/> | ||||
| 											<a class="remove-button" id="remove-button-<?php echo $id ?>-<?php echo $i ?>"><i class="fas fa-trash"></a></i></li> | ||||
| 										<?php $last_id[$id] = $i; | ||||
| 									endforeach; | ||||
| 								} ?> | ||||
| 							</ul> | ||||
| 						</div> | ||||
| 					</div> | ||||
| 				</div> | ||||
| 			<?php endforeach ?> | ||||
| 		</div> | ||||
| 		<div class="row pb-2"> | ||||
| 			<div class="col-md-12"> | ||||
| 				<button type="submit" class="btn btn-info"><i class="fas fa-update"></i> Save</button> | ||||
| 				<?php | ||||
| 				echo '<button type="button" class="btn btn-danger float-right" value="Cancel" onclick="window.location = \'' . ADMIN_URL . '?p=menus\';"><i class="fas fa-cancel"></i> Cancel</button>'; | ||||
| 				?> | ||||
| 			</div> | ||||
| 		</div> | ||||
| 	</form> | ||||
| 	<?php | ||||
| 	$twig->display('admin.menus.js.html.twig', array( | ||||
| 		'menus' => $menus, | ||||
| 		'last_id' => $last_id | ||||
| 	)); | ||||
| 	?> | ||||
| 	<?php | ||||
| } else { | ||||
| 	$templates = $db->query('SELECT `template` FROM `' . TABLE_PREFIX . 'menu` GROUP BY `template`;')->fetchAll(); | ||||
| 	foreach ($templates as $key => $value) { | ||||
| 		$file = TEMPLATES . $value['template'] . '/config.php'; | ||||
| 		if (!file_exists($file)) { | ||||
| 			unset($templates[$key]); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	$twig->display('admin.menus.form.html.twig', array( | ||||
| 		'templates' => $templates | ||||
| 	)); | ||||
| } | ||||
							
								
								
									
										6
									
								
								admin/pages/modules/balance.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,6 @@ | ||||
| <?php | ||||
| $balance = ($db->hasColumn('players', 'balance') ? $db->query('SELECT `balance`, `id`, `name`,`level` FROM `players` ORDER BY `balance` DESC LIMIT 10;') : 0); | ||||
|  | ||||
| $twig->display('balance.html.twig', array( | ||||
| 	'balance' => $balance | ||||
| )); | ||||
							
								
								
									
										6
									
								
								admin/pages/modules/coins.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,6 @@ | ||||
| <?php | ||||
| $coins = ($db->hasColumn('accounts', 'coins') ?  $db->query('SELECT `coins`, `' . (USE_ACCOUNT_NAME ? 'name' : 'id') . '` as `name` FROM `accounts` ORDER BY `coins` DESC LIMIT 10;') : 0); | ||||
|  | ||||
| $twig->display('coins.html.twig', array( | ||||
| 	'coins' => $coins | ||||
| )); | ||||
							
								
								
									
										6
									
								
								admin/pages/modules/created.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,6 @@ | ||||
| <?php | ||||
| $players = ($db->hasColumn('accounts', 'created') ? $db->query('SELECT `created`, `' . (USE_ACCOUNT_NAME ? 'name' : 'id') . '` as `name` FROM `accounts` ORDER BY `created` DESC LIMIT 10;') : 0); | ||||
|  | ||||
| $twig->display('created.html.twig', array( | ||||
| 	'players' => $players, | ||||
| )); | ||||
							
								
								
									
										5
									
								
								admin/pages/modules/lastlogin.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,5 @@ | ||||
| <?php | ||||
| $players = ($db->hasColumn('players', 'lastlogin') ? $db->query('SELECT name, level, lastlogin FROM players ORDER BY lastlogin DESC LIMIT 10;') : 0); | ||||
| $twig->display('lastlogin.html.twig', array( | ||||
| 	'players' => $players, | ||||
| )); | ||||
							
								
								
									
										6
									
								
								admin/pages/modules/points.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,6 @@ | ||||
| <?php | ||||
| $points = ($db->hasColumn('accounts', 'premium_points') ? $db->query('SELECT `premium_points`, `' . (USE_ACCOUNT_NAME ? 'name' : 'id') . '` as `name` FROM `accounts` ORDER BY `premium_points` DESC LIMIT 10;') : 0); | ||||
|  | ||||
| $twig->display('points.html.twig', array( | ||||
| 	'points' => $points, | ||||
| )); | ||||
							
								
								
									
										46
									
								
								admin/pages/modules/server_status.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,46 @@ | ||||
| <?php | ||||
| defined('MYAAC') or die('Direct access not allowed!'); | ||||
| if (isset($status)) { | ||||
|  | ||||
| 	$error_icon = '<i class="fas fa-exclamation-circle text-danger"></i>'; ?> | ||||
| 	<div class=" col-md-6 col-lg-6"> | ||||
| 		<div class="card card-info card-outline"> | ||||
| 			<div class="card-header border-bottom-0"> | ||||
| 				<span class="font-weight-bold m-0">Server Status</span> <span class="float-right small"><b>Last checked</b>: <?php echo(isset($status['lastCheck']) ? date("l, d.m.Y H:i:s", $status['lastCheck']) : $error_icon); ?></span> | ||||
| 			</div> | ||||
| 			<div class="card-body p-0 "> | ||||
| 				<table class="table"> | ||||
| 					<tbody> | ||||
| 					<tr> | ||||
| 						<th width="30%">Server</th> | ||||
| 						<td><?php echo(isset($status['server']) & isset($status['serverVersion']) ? $status['server'] . ' x ' . $status['serverVersion'] : $error_icon) ?></td> | ||||
|  | ||||
| 					</tr> | ||||
| 					<tr> | ||||
| 						<th>Client</th> | ||||
| 						<td><?php echo(isset($status['clientVersion']) ? $status['clientVersion'] : $error_icon) ?></td> | ||||
| 					</tr> | ||||
| 					<tr> | ||||
| 						<th>Map</th> | ||||
| 						<td> | ||||
| 							<?php if (isset($status['mapName']) & isset($status['mapAuthor']) & isset($status['mapWidth']) & isset($status['mapHeight'])) { | ||||
| 								echo $status['mapName'] . ' by <b>' . $status['mapAuthor'] . '</b><br/>' . $status['mapWidth'] . ' x ' . $status['mapHeight']; | ||||
| 							} else { | ||||
| 								echo $error_icon; | ||||
| 							} ?> | ||||
| 						</td> | ||||
| 					</tr> | ||||
| 					<tr> | ||||
| 						<th>Monsters</th> | ||||
| 						<td><?php echo (isset($status['monsters']) ? $status['monsters'] : $error_icon); ?></td> | ||||
| 					</tr> | ||||
| 					<tr> | ||||
| 						<th>MOTD:</th> | ||||
| 						<td><?php echo(isset($status['motd']) ? $status['motd'] : $error_icon); ?></td> | ||||
| 					</tr> | ||||
| 					</tbody> | ||||
| 				</table> | ||||
| 			</div> | ||||
| 		</div> | ||||
| 	</div> | ||||
| <?php } ?> | ||||
							
								
								
									
										12
									
								
								admin/pages/modules/statistics.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,12 @@ | ||||
| <?php | ||||
| defined('MYAAC') or die('Direct access not allowed!'); | ||||
| $count = $db->query('SELECT | ||||
|   (SELECT COUNT(*) FROM `accounts`) as total_accounts,  | ||||
|   (SELECT COUNT(*) FROM `players`) as total_players, | ||||
|   (SELECT COUNT(*) FROM `guilds`) as total_guilds, | ||||
|   (SELECT COUNT(*) FROM `' . TABLE_PREFIX . 'monsters`) as total_monsters, | ||||
|   (SELECT COUNT(*) FROM `houses`) as total_houses;')->fetch(); | ||||
|  | ||||
| $twig->display('statistics.html.twig', array( | ||||
| 	'count' => $count, | ||||
| )); | ||||
							
								
								
									
										31
									
								
								admin/pages/modules/templates/balance.html.twig
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,31 @@ | ||||
| {% if balance is iterable %} | ||||
| 	<div class=" col-md-6 col-lg-3"> | ||||
| 		<div class="card card-info card-outline"> | ||||
| 			<div class="card-header"> | ||||
| 				<h5 class="m-0">Top 10 - Balance</h5> | ||||
| 			</div> | ||||
| 			<div class="card-body p-0"> | ||||
| 				<table class="table table-striped table-condensed"> | ||||
| 					<thead> | ||||
| 					<tr> | ||||
| 						<th>#</th> | ||||
| 						<th>Player</th> | ||||
| 						<th>Balance</th> | ||||
| 					</tr> | ||||
| 					</thead> | ||||
| 					<tbody> | ||||
| 					{% set i = 0 %} | ||||
| 					{% for result in balance %} | ||||
| 						{% set i = i + 1 %} | ||||
| 						<tr> | ||||
| 							<th>{{ i }}</th> | ||||
| 							<td><a href="?p=players&search_name={{ result.name }}">{{ result.name }}</a></td> | ||||
| 							<td>{{ result.balance }}</td> | ||||
| 						</tr> | ||||
| 					{% endfor %} | ||||
| 					</tbody> | ||||
| 				</table> | ||||
| 			</div> | ||||
| 		</div> | ||||
| 	</div> | ||||
| {% endif %} | ||||
							
								
								
									
										31
									
								
								admin/pages/modules/templates/coins.html.twig
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,31 @@ | ||||
| {% if coins is iterable %} | ||||
| 	<div class=" col-md-6 col-lg-3"> | ||||
| 		<div class="card card-info card-outline"> | ||||
| 			<div class="card-header"> | ||||
| 				<h5 class="m-0">Top 10 - Most coins</h5> | ||||
| 			</div> | ||||
| 			<div class="card-body p-0"> | ||||
| 				<table class="table table-striped table-condensed"> | ||||
| 					<thead> | ||||
| 					<tr> | ||||
| 						<th>#</th> | ||||
| 						<th>Account</th> | ||||
| 						<th>Tibia coins</th> | ||||
| 					</tr> | ||||
| 					</thead> | ||||
| 					<tbody> | ||||
| 					{% set i = 0 %} | ||||
| 					{% for result in coins %} | ||||
| 						{% set i = i + 1 %} | ||||
| 						<tr> | ||||
| 							<th>{{ i }}</th> | ||||
| 							<td><a href="?p=accounts&search_name={{ result.name }}">{{ result.name }}</a></td> | ||||
| 							<td>{{ result.coins }}</td> | ||||
| 						</tr> | ||||
| 					{% endfor %} | ||||
| 					</tbody> | ||||
| 				</table> | ||||
| 			</div> | ||||
| 		</div> | ||||
| 	</div> | ||||
| {% endif %} | ||||
							
								
								
									
										31
									
								
								admin/pages/modules/templates/created.html.twig
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,31 @@ | ||||
| {% if players is iterable %} | ||||
| 	<div class=" col-md-6 col-lg-3"> | ||||
| 		<div class="card card-info card-outline"> | ||||
| 			<div class="card-header"> | ||||
| 				<h5 class="m-0">Last 10 created</h5> | ||||
| 			</div> | ||||
| 			<div class="card-body p-0"> | ||||
| 				<table class="table table-striped table-condensed"> | ||||
| 					<thead> | ||||
| 					<tr> | ||||
| 						<th>#</th> | ||||
| 						<th>Account</th> | ||||
| 						<th>Creation Date</th> | ||||
| 					</tr> | ||||
| 					</thead> | ||||
| 					<tbody> | ||||
| 					{% set i = 0 %} | ||||
| 					{% for result in players %} | ||||
| 						{% set i = i + 1 %} | ||||
| 						<tr> | ||||
| 							<th>{{ i }}</th> | ||||
| 							<td><a href="?p=accounts&search_name={{ result.name }}">{{ result.name }}</a></td> | ||||
| 							<td>{{ result.created|date("M d Y, H:i:s") }}</td> | ||||
| 						</tr> | ||||
| 					{% endfor %} | ||||
| 					</tbody> | ||||
| 				</table> | ||||
| 			</div> | ||||
| 		</div> | ||||
| 	</div> | ||||
| {% endif %} | ||||
							
								
								
									
										31
									
								
								admin/pages/modules/templates/lastlogin.html.twig
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,31 @@ | ||||
| {% if players is iterable %} | ||||
| 	<div class=" col-md-6 col-lg-3"> | ||||
| 		<div class="card card-info card-outline"> | ||||
| 			<div class="card-header"> | ||||
| 				<h5 class="m-0">Last 10 logins</h5> | ||||
| 			</div> | ||||
| 			<div class="card-body p-0"> | ||||
| 				<table class="table table-striped table-condensed"> | ||||
| 					<thead> | ||||
| 					<tr> | ||||
| 						<th>#</th> | ||||
| 						<th>Player</th> | ||||
| 						<th>Login Date</th> | ||||
| 					</tr> | ||||
| 					</thead> | ||||
| 					<tbody> | ||||
| 					{% set i = 0 %} | ||||
| 					{% for result in players %} | ||||
| 						{% set i = i + 1 %} | ||||
| 						<tr> | ||||
| 							<th>{{ i }}</th> | ||||
| 							<td><a href="?p=players&search_name={{ result.name }}">{{ result.name }}</a></td> | ||||
| 							<td>{{ result.lastlogin|date("M d Y, H:i:s") }}</td> | ||||
| 						</tr> | ||||
| 					{% endfor %} | ||||
| 					</tbody> | ||||
| 				</table> | ||||
| 			</div> | ||||
| 		</div> | ||||
| 	</div> | ||||
| {% endif %} | ||||
							
								
								
									
										31
									
								
								admin/pages/modules/templates/points.html.twig
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,31 @@ | ||||
| {% if points is iterable %} | ||||
| 	<div class=" col-md-6 col-lg-3"> | ||||
| 		<div class="card card-info card-outline"> | ||||
| 			<div class="card-header"> | ||||
| 				<h5 class="m-0">Top 10 - Most premium points</h5> | ||||
| 			</div> | ||||
| 			<div class="card-body p-0"> | ||||
| 				<table class="table table-striped table-condensed"> | ||||
| 					<thead> | ||||
| 					<tr> | ||||
| 						<th>#</th> | ||||
| 						<th>Account</th> | ||||
| 						<th>Premium points</th> | ||||
| 					</tr> | ||||
| 					</thead> | ||||
| 					<tbody> | ||||
| 					{% set i = 0 %} | ||||
| 					{% for result in points %} | ||||
| 						{% set i = i + 1 %} | ||||
| 						<tr> | ||||
| 							<th>{{ i }}</th> | ||||
| 							<td><a href="?p=accounts&search_name={{ result.name }}">{{ result.name }}</a></td> | ||||
| 							<td>{{ result.premium_points }}</td> | ||||
| 						</tr> | ||||
| 					{% endfor %} | ||||
| 					</tbody> | ||||
| 				</table> | ||||
| 			</div> | ||||
| 		</div> | ||||
| 	</div> | ||||
| {% endif %} | ||||
							
								
								
									
										45
									
								
								admin/pages/modules/templates/statistics.html.twig
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,45 @@ | ||||
| <div class="col"> | ||||
| 	<div class="info-box"> | ||||
| 		<span class="info-box-icon bg-info elevation-1"><i class="fas fa-user-plus"></i></span> | ||||
| 		<div class="info-box-content"> | ||||
| 			<span class="info-box-text">Accounts:</span> | ||||
| 			<span class="info-box-number">{{ count.total_accounts }}</span> | ||||
| 		</div> | ||||
| 	</div> | ||||
| </div> | ||||
| <div class="col"> | ||||
| 	<div class="info-box"> | ||||
| 		<span class="info-box-icon bg-red elevation-1"><i class="fas fa-user-plus"></i></span> | ||||
| 		<div class="info-box-content"> | ||||
| 			<span class="info-box-text">Players:</span> | ||||
| 			<span class="info-box-number">{{ count.total_players }}</span> | ||||
| 		</div> | ||||
| 	</div> | ||||
| </div> | ||||
| <div class="col"> | ||||
| 	<div class="info-box"> | ||||
| 		<span class="info-box-icon bg-teal elevation-1"><i class="fas fa-pastafarianism"></i></span> | ||||
| 		<div class="info-box-content"> | ||||
| 			<span class="info-box-text">Monsters:</span> | ||||
| 			<span class="info-box-number">{{ count.total_monsters }}</span> | ||||
| 		</div> | ||||
| 	</div> | ||||
| </div> | ||||
| <div class="col"> | ||||
| 	<div class="info-box"> | ||||
| 		<span class="info-box-icon bg-green elevation-1"><i class="fas fa-chart-pie"></i></span> | ||||
| 		<div class="info-box-content"> | ||||
| 			<span class="info-box-text">Guilds:</span> | ||||
| 			<span class="info-box-number">{{ count.total_guilds }}</span> | ||||
| 		</div> | ||||
| 	</div> | ||||
| </div> | ||||
| <div class="col"> | ||||
| 	<div class="info-box"> | ||||
| 		<span class="info-box-icon bg-yellow elevation-1"><i class="fas fa-home"></i></span> | ||||
| 		<div class="info-box-content"> | ||||
| 			<span class="info-box-text">Houses:</span> | ||||
| 			<span class="info-box-number">{{ count.total_houses }}</span> | ||||
| 		</div> | ||||
| 	</div> | ||||
| </div> | ||||
							
								
								
									
										39
									
								
								admin/pages/modules/templates/web_status.twig
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,39 @@ | ||||
| <div class="col-12 col-md-6"> | ||||
| 	<div class="card card-warning card-outline"> | ||||
| 		<form action="?p=dashboard&maintenance" method="post" class="form-horizontal"> | ||||
| 			<div class="card-header"> | ||||
| 				<span class="m-0">Website Status<span class="float-right"> | ||||
| 				<div class="custom-control custom-switch custom-switch-off-danger custom-switch-on-success"> | ||||
| 					<input type="checkbox" class="custom-control-input" name="status" id="status" value="true" {% if not is_closed %} checked{% endif %}> | ||||
| 					<label id="status-label" class="custom-control-label" for="status"> {% if is_closed %}Closed{% else %}Open{% endif %}</label> | ||||
| 				</div></span> | ||||
| 				</span> | ||||
| 			</div> | ||||
| 			<div class="card-body p-2"> | ||||
| 				<div class="col-sm-12"> | ||||
| 					<label for="message" class="col-form-label">Maintenance Message</label> | ||||
| 					<textarea name="message" class="form-control" cols="40" rows="3" maxlength="255" placeholder="Enter ...">{{ closed_message }}</textarea> | ||||
| 					<small>(only visible if closed)</small> | ||||
| 				</div> | ||||
| 			</div> | ||||
| 			<div class="card-footer"> | ||||
| 				<button type="submit" class="btn btn-info"><i class="far fa-update"></i> Update</button> | ||||
| 				<a href="?p=dashboard&clear_cache" onclick="return confirm('Are you sure?');" class="float-right"> | ||||
| 					<span class="btn btn-danger"><i class="fas fa-clear"></i>Clear cache</span> | ||||
| 				</a> | ||||
| 			</div> | ||||
| 		</form> | ||||
| 	</div> | ||||
| </div> | ||||
|  | ||||
| <script> | ||||
| 	$(function() { | ||||
| 		$("#status").change(function() { | ||||
| 			$statusLabel = $("#status-label"); | ||||
| 			$statusLabel.html("Closed"); | ||||
| 			if ($(this).is(':checked')) { | ||||
| 				$statusLabel.html("Open"); | ||||
| 			} | ||||
| 		}); | ||||
| 	}); | ||||
| </script> | ||||
							
								
								
									
										10
									
								
								admin/pages/modules/web_status.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,10 @@ | ||||
| <?php | ||||
| defined('MYAAC') or die('Direct access not allowed!'); | ||||
|  | ||||
| $twig->display('web_status.twig', array( | ||||
| 	'is_closed' => $is_closed, | ||||
| 	'closed_message' => $closed_message, | ||||
| 	'status' => $status, | ||||
| 	'account_type' => USE_ACCOUNT_NAME ? 'name' : 'number' | ||||
| )); | ||||
| ?> | ||||
							
								
								
									
										155
									
								
								admin/pages/news.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,155 @@ | ||||
| <?php | ||||
| /** | ||||
|  * Pages | ||||
|  * | ||||
|  * @package   MyAAC | ||||
|  * @author    Slawkens <slawkens@gmail.com> | ||||
|  * @copyright 2019 MyAAC | ||||
|  * @link      https://my-aac.org | ||||
|  */ | ||||
| defined('MYAAC') or die('Direct access not allowed!'); | ||||
|  | ||||
| require_once LIBS . 'forum.php'; | ||||
| require_once LIBS . 'news.php'; | ||||
|  | ||||
| $title = 'News Panel'; | ||||
| $use_datatable = true; | ||||
|  | ||||
| if (!hasFlag(FLAG_CONTENT_PAGES) && !superAdmin()) { | ||||
| 	echo 'Access denied.'; | ||||
| 	return; | ||||
| } | ||||
|  | ||||
| header('X-XSS-Protection:0'); | ||||
|  | ||||
| // some constants, used mainly by database (cannot by modified without schema changes) | ||||
| define('NEWS_TITLE_LIMIT', 100); | ||||
| define('NEWS_BODY_LIMIT', 65535); // maximum news body length | ||||
| define('ARTICLE_TEXT_LIMIT', 300); | ||||
| define('ARTICLE_IMAGE_LIMIT', 100); | ||||
|  | ||||
| $name = $p_title = ''; | ||||
| if(!empty($action)) | ||||
| { | ||||
| 	$id = isset($_REQUEST['id']) ? $_REQUEST['id'] : null; | ||||
| 	$p_title = isset($_REQUEST['title']) ? $_REQUEST['title'] : null; | ||||
| 	$body = isset($_REQUEST['body']) ? stripslashes($_REQUEST['body']) : null; | ||||
| 	$comments = isset($_REQUEST['comments']) ? $_REQUEST['comments'] : null; | ||||
| 	$type = isset($_REQUEST['type']) ? (int)$_REQUEST['type'] : null; | ||||
| 	$category = isset($_REQUEST['category']) ? (int)$_REQUEST['category'] : null; | ||||
| 	$player_id = isset($_REQUEST['player_id']) ? (int)$_REQUEST['player_id'] : null; | ||||
| 	$article_text = isset($_REQUEST['article_text']) ? $_REQUEST['article_text'] : null; | ||||
| 	$article_image = isset($_REQUEST['article_image']) ? $_REQUEST['article_image'] : null; | ||||
| 	$forum_section = isset($_REQUEST['forum_section']) ? $_REQUEST['forum_section'] : null; | ||||
| 	$errors = array(); | ||||
|  | ||||
| 	if($action == 'new') { | ||||
| 		if(isset($forum_section) && $forum_section != '-1') { | ||||
| 			$forum_add = Forum::add_thread($p_title, $body, $forum_section, $player_id, $account_logged->getId(), $errors); | ||||
| 		} | ||||
|  | ||||
| 		if(isset($p_title) && News::add($p_title, $body, $type, $category, $player_id, isset($forum_add) && $forum_add != 0 ? $forum_add : 0, $article_text, $article_image, $errors)) { | ||||
| 			$p_title = $body = $comments = $article_text = $article_image = ''; | ||||
| 			$type = $category = $player_id = 0; | ||||
|  | ||||
| 			success("Added successful."); | ||||
| 		} | ||||
| 	} | ||||
| 	else if($action == 'delete') { | ||||
| 		News::delete($id, $errors); | ||||
| 		success("Deleted successful."); | ||||
| 	} | ||||
| 	else if($action == 'edit') | ||||
| 	{ | ||||
| 		if(isset($id) && !isset($p_title)) { | ||||
| 			$news = News::get($id); | ||||
| 			$p_title = $news['title']; | ||||
| 			$body = $news['body']; | ||||
| 			$comments = $news['comments']; | ||||
| 			$type = $news['type']; | ||||
| 			$category = $news['category']; | ||||
| 			$player_id = $news['player_id']; | ||||
| 			$article_text = $news['article_text']; | ||||
| 			$article_image = $news['article_image']; | ||||
| 		} | ||||
| 		else { | ||||
| 			if(News::update($id, $p_title, $body, $type, $category, $player_id, $forum_section, $article_text, $article_image, $errors)) { | ||||
| 				// update forum thread if exists | ||||
| 				if(isset($forum_section) && Validator::number($forum_section)) { | ||||
| 					$db->query("UPDATE `" . TABLE_PREFIX . "forum` SET `author_guid` = ".(int) $player_id.", `post_text` = ".$db->quote($body).", `post_topic` = ".$db->quote($p_title).", `edit_date` = " . time() . " WHERE `id` = " . $db->quote($forum_section)); | ||||
| 				} | ||||
|  | ||||
| 				$action = $p_title = $body = $comments = $article_text = $article_image = ''; | ||||
| 				$type = $category = $player_id = 0; | ||||
|  | ||||
| 				success("Updated successful."); | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	else if($action == 'hide') { | ||||
| 		News::toggleHidden($id, $errors, $status); | ||||
| 		success(($status == 1 ? 'Show' : 'Hide') . " successful."); | ||||
| 	} | ||||
|  | ||||
| 	if(!empty($errors)) | ||||
| 		error(implode(", ", $errors)); | ||||
| } | ||||
|  | ||||
| $categories = array(); | ||||
| foreach($db->query('SELECT `id`, `name`, `icon_id` FROM `' . TABLE_PREFIX . 'news_categories` WHERE `hidden` != 1') as $cat) | ||||
| { | ||||
| 	$categories[$cat['id']] = array( | ||||
| 		'name' => $cat['name'], | ||||
| 		'icon_id' => $cat['icon_id'] | ||||
| 	); | ||||
| } | ||||
|  | ||||
| if($action == 'edit' || $action == 'new') { | ||||
| 	if($action == 'edit') { | ||||
| 		$player = new OTS_Player(); | ||||
| 		$player->load($player_id); | ||||
| 	} | ||||
|  | ||||
| 	$account_players = $account_logged->getPlayersList(); | ||||
| 	$account_players->orderBy('group_id', POT::ORDER_DESC); | ||||
| 	$twig->display('admin.news.form.html.twig', array( | ||||
| 		'action' => $action, | ||||
| 		'news_link' => getLink(PAGE), | ||||
| 		'news_link_form' => '?p=news&action=' . ($action == 'edit' ? 'edit' : 'new'), | ||||
| 		'news_id' => $id ?? null, | ||||
| 		'title' => $p_title ?? '', | ||||
| 		'body' => isset($body) ? escapeHtml($body) : '', | ||||
| 		'type' => $type ?? null, | ||||
| 		'player' => isset($player) && $player->isLoaded() ? $player : null, | ||||
| 		'player_id' => $player_id ?? null, | ||||
| 		'account_players' => $account_players, | ||||
| 		'category' => $category ?? 0, | ||||
| 		'categories' => $categories, | ||||
| 		'forum_boards' => getForumBoards(), | ||||
| 		'forum_section' => $forum_section ?? null, | ||||
| 		'comments' => $comments ?? null, | ||||
| 		'article_text' => $article_text ?? null, | ||||
| 		'article_image' => $article_image ?? null | ||||
| 	)); | ||||
| } | ||||
|  | ||||
| $query = $db->query('SELECT * FROM ' . $db->tableName(TABLE_PREFIX . 'news')); | ||||
| $newses = array(); | ||||
| foreach ($query as $_news) { | ||||
| 	$_player = new OTS_Player(); | ||||
| 	$_player->load($_news['player_id']); | ||||
|  | ||||
| 	$newses[$_news['type']][] = array( | ||||
| 		'id' => $_news['id'], | ||||
| 		'hidden' => $_news['hidden'], | ||||
| 		'archive_link' => getLink('news') . '/archive/' . $_news['id'], | ||||
| 		'title' => $_news['title'], | ||||
| 		'date' => $_news['date'], | ||||
| 		'player_name' => isset($_player) && $_player->isLoaded() ? $_player->getName() : '', | ||||
| 		'player_link' => isset($_player) && $_player->isLoaded() ? getPlayerLink($_player->getName(), false) : '', | ||||
| 	); | ||||
| } | ||||
|  | ||||
| $twig->display('admin.news.html.twig', array( | ||||
| 	'newses' => $newses | ||||
| )); | ||||
| @@ -4,31 +4,27 @@ | ||||
|  * | ||||
|  * @package   MyAAC | ||||
|  * @author    Slawkens <slawkens@gmail.com> | ||||
|  * @copyright 2017 MyAAC | ||||
|  * @version   0.3.0 | ||||
|  * @link      http://my-aac.org | ||||
|  * @copyright 2019 MyAAC | ||||
|  * @link      https://my-aac.org | ||||
|  */ | ||||
| defined('MYAAC') or die('Direct access not allowed!'); | ||||
| $title = 'Notepad'; | ||||
| 
 | ||||
| $notepad_content = Notepad::get($account_logged->getId()); | ||||
| if(isset($_POST['content'])) | ||||
| { | ||||
| if (isset($_POST['content'])) { | ||||
| 	$_content = html_entity_decode(stripslashes($_POST['content'])); | ||||
| 	if(!$notepad_content) | ||||
| 	if (!$notepad_content) | ||||
| 		Notepad::create($account_logged->getId(), $_content); | ||||
| 	else | ||||
| 		Notepad::update($account_logged->getId(), $_content); | ||||
| 
 | ||||
| 	echo '<div class="success" style="text-align: center;">Saved at ' . date('g:i A') . '</div>'; | ||||
| } | ||||
| else | ||||
| { | ||||
| 	if($notepad_content !== false) | ||||
| 	echo '<div class="success" style="text-align: center;">Saved at ' . date('H:i') . '</div>'; | ||||
| } else { | ||||
| 	if ($notepad_content !== false) | ||||
| 		$_content = $notepad_content; | ||||
| } | ||||
| 
 | ||||
| echo $twig->render('admin.notepad.html', array('content' => isset($_content) ? $_content : null)); | ||||
| $twig->display('admin.notepad.html.twig', array('content' => isset($_content) ? $_content : null)); | ||||
| 
 | ||||
| class Notepad | ||||
| { | ||||
| @@ -36,7 +32,7 @@ class Notepad | ||||
| 	{ | ||||
| 		global $db; | ||||
| 		$query = $db->select(TABLE_PREFIX . 'notepad', array('account_id' => $account_id)); | ||||
| 		if($query !== false) | ||||
| 		if ($query !== false) | ||||
| 			return $query['content']; | ||||
| 
 | ||||
| 		return false; | ||||
| @@ -53,4 +49,4 @@ class Notepad | ||||
| 		global $db; | ||||
| 		$db->update(TABLE_PREFIX . 'notepad', array('content' => $content), array('account_id' => $account_id)); | ||||
| 	} | ||||
| } | ||||
| } | ||||
							
								
								
									
										14
									
								
								admin/pages/open_source.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,14 @@ | ||||
| <?php | ||||
| /** | ||||
|  * Open Source libraries | ||||
|  * | ||||
|  * @package   MyAAC | ||||
|  * @author    Slawkens <slawkens@gmail.com> | ||||
|  * @copyright 2023 MyAAC | ||||
|  * @link      https://my-aac.org | ||||
|  */ | ||||
| defined('MYAAC') or die('Direct access not allowed!'); | ||||
|  | ||||
| $title = 'Open Source'; | ||||
|  | ||||
| $twig->display('admin.open_source.html.twig'); | ||||
							
								
								
									
										262
									
								
								admin/pages/pages.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,262 @@ | ||||
| <?php | ||||
| /** | ||||
|  * Pages | ||||
|  * | ||||
|  * @package   MyAAC | ||||
|  * @author    Slawkens <slawkens@gmail.com> | ||||
|  * @copyright 2019 MyAAC | ||||
|  * @link      https://my-aac.org | ||||
|  */ | ||||
| defined('MYAAC') or die('Direct access not allowed!'); | ||||
| $title = 'Pages'; | ||||
| $use_datatable = true; | ||||
|  | ||||
| if (!hasFlag(FLAG_CONTENT_PAGES) && !superAdmin()) { | ||||
| 	echo 'Access denied.'; | ||||
| 	return; | ||||
| } | ||||
|  | ||||
| header('X-XSS-Protection:0'); | ||||
|  | ||||
| $name = $p_title = null; | ||||
| $groups = new OTS_Groups_List(); | ||||
|  | ||||
| $php = false; | ||||
| $enable_tinymce = true; | ||||
| $access = 0; | ||||
|  | ||||
| // some constants, used mainly by database (cannot by modified without schema changes) | ||||
| define('PAGE_TITLE_LIMIT', 30); | ||||
| define('PAGE_NAME_LIMIT', 30); | ||||
| define('PAGE_BODY_LIMIT', 65535); // maximum page body length | ||||
|  | ||||
| if (!empty($action)) { | ||||
| 	if ($action == 'delete' || $action == 'edit' || $action == 'hide') | ||||
| 		$id = $_REQUEST['id']; | ||||
|  | ||||
| 	if (isset($_REQUEST['name'])) | ||||
| 		$name = $_REQUEST['name']; | ||||
|  | ||||
| 	if (isset($_REQUEST['title'])) | ||||
| 		$p_title = $_REQUEST['title']; | ||||
|  | ||||
| 	$php = isset($_REQUEST['php']) && $_REQUEST['php'] == 1; | ||||
| 	$enable_tinymce = isset($_REQUEST['enable_tinymce']) && $_REQUEST['enable_tinymce'] == 1; | ||||
| 	if ($php) | ||||
| 		$body = $_REQUEST['body']; | ||||
| 	else if (isset($_REQUEST['body'])) { | ||||
| 		//$body = $_REQUEST['body']; | ||||
| 		$body = html_entity_decode(stripslashes($_REQUEST['body'])); | ||||
| 	} | ||||
|  | ||||
| 	if (isset($_REQUEST['access'])) | ||||
| 		$access = $_REQUEST['access']; | ||||
|  | ||||
| 	$errors = array(); | ||||
| 	$player_id = 1; | ||||
|  | ||||
| 	if ($action == 'new') { | ||||
| 		if (isset($p_title) && Pages::add($name, $p_title, $body, $player_id, $php, $enable_tinymce, $access, $errors)) { | ||||
| 			$name = $p_title = $body = ''; | ||||
| 			$player_id = $access = 0; | ||||
| 			$php = false; | ||||
| 			$enable_tinymce = true; | ||||
| 			success('Added successful.'); | ||||
| 		} | ||||
| 	} else if ($action == 'delete') { | ||||
| 		if (Pages::delete($id, $errors)) | ||||
| 			success('Page with id ' . $id . ' has been deleted'); | ||||
| 	} else if ($action == 'edit') { | ||||
| 		if (isset($id) && !isset($_REQUEST['name'])) { | ||||
| 			$_page = Pages::get($id); | ||||
| 			$name = $_page['name']; | ||||
| 			$p_title = $_page['title']; | ||||
| 			$body = $_page['body']; | ||||
| 			$php = $_page['php'] == '1'; | ||||
| 			$enable_tinymce = $_page['enable_tinymce'] == '1'; | ||||
| 			$access = $_page['access']; | ||||
| 		} else { | ||||
| 			if(Pages::update($id, $name, $p_title, $body, $player_id, $php, $enable_tinymce, $access, $errors)) { | ||||
| 				$action = $name = $p_title = $body = ''; | ||||
| 				$player_id = 1; | ||||
| 				$access = 0; | ||||
| 				$php = false; | ||||
| 				$enable_tinymce = true; | ||||
| 				success('Updated successful.'); | ||||
| 			} | ||||
| 		} | ||||
| 	} else if ($action == 'hide') { | ||||
| 		Pages::toggleHidden($id, $errors, $status); | ||||
| 		success(($status == 1 ? 'Show' : 'Hide') . ' successful.'); | ||||
| 	} | ||||
|  | ||||
| 	if (!empty($errors)) | ||||
| 		error(implode(", ", $errors)); | ||||
| } | ||||
|  | ||||
| $query = | ||||
| 	$db->query('SELECT * FROM ' . $db->tableName(TABLE_PREFIX . 'pages')); | ||||
|  | ||||
| $pages = array(); | ||||
| foreach ($query as $_page) { | ||||
| 	$pages[] = array( | ||||
| 		'link' => getFullLink($_page['name'], $_page['name'], true), | ||||
| 		'title' => substr($_page['title'], 0, 20), | ||||
| 		'php' => $_page['php'] == '1', | ||||
| 		'id' => $_page['id'], | ||||
| 		'hidden' => $_page['hidden'] | ||||
| 	); | ||||
| } | ||||
|  | ||||
| $twig->display('admin.pages.form.html.twig', array( | ||||
| 	'action' => $action, | ||||
| 	'id' => $action == 'edit' ? $id : null, | ||||
| 	'name' => $name, | ||||
| 	'title' => $p_title, | ||||
| 	'php' => $php, | ||||
| 	'enable_tinymce' => $enable_tinymce, | ||||
| 	'body' => isset($body) ? escapeHtml($body) : '', | ||||
| 	'groups' => $groups->getGroups(), | ||||
| 	'access' => $access | ||||
| )); | ||||
|  | ||||
| $twig->display('admin.pages.html.twig', array( | ||||
| 	'pages' => $pages | ||||
| )); | ||||
|  | ||||
| class Pages | ||||
| { | ||||
| 	static public function verify($name, $title, $body, $player_id, $php, $enable_tinymce, $access, &$errors) | ||||
| 	{ | ||||
| 		if(!isset($title[0]) || !isset($body[0])) { | ||||
| 			$errors[] = 'Please fill all inputs.'; | ||||
| 			return false; | ||||
| 		} | ||||
| 		if(strlen($name) > PAGE_NAME_LIMIT) { | ||||
| 			$errors[] = 'Page name cannot be longer than ' . PAGE_NAME_LIMIT . ' characters.'; | ||||
| 			return false; | ||||
| 		} | ||||
| 		if(strlen($title) > PAGE_TITLE_LIMIT) { | ||||
| 			$errors[] = 'Page title cannot be longer than ' . PAGE_TITLE_LIMIT . ' characters.'; | ||||
| 			return false; | ||||
| 		} | ||||
| 		if(strlen($body) > PAGE_BODY_LIMIT) { | ||||
| 			$errors[] = 'Page content cannot be longer than ' . PAGE_BODY_LIMIT . ' characters.'; | ||||
| 			return false; | ||||
| 		} | ||||
| 		if(!isset($player_id) || $player_id == 0) { | ||||
| 			$errors[] = 'Player ID is wrong.'; | ||||
| 			return false; | ||||
| 		} | ||||
| 		if(!isset($php) || ($php != 0 && $php != 1)) { | ||||
| 			$errors[] = 'Enable PHP is wrong.'; | ||||
| 			return false; | ||||
| 		} | ||||
| 		if ($php == 1 && !getBoolean(config('admin_pages_php_enable'))) { | ||||
| 			$errors[] = 'PHP pages disabled on this server. To enable go to config.php and change admin_pages_php_enable to "yes".'; | ||||
| 			return false; | ||||
| 		} | ||||
| 		if(!isset($enable_tinymce) || ($enable_tinymce != 0 && $enable_tinymce != 1)) { | ||||
| 			$errors[] = 'Enable TinyMCE is wrong.'; | ||||
| 			return false; | ||||
| 		} | ||||
| 		if(!isset($access) || $access < 0 || $access > PHP_INT_MAX) { | ||||
| 			$errors[] = 'Access is wrong.'; | ||||
| 			return false; | ||||
| 		} | ||||
|  | ||||
| 		return true; | ||||
| 	} | ||||
|  | ||||
| 	static public function get($id) | ||||
| 	{ | ||||
| 		global $db; | ||||
| 		$query = $db->select(TABLE_PREFIX . 'pages', array('id' => $id)); | ||||
| 		if ($query !== false) | ||||
| 			return $query; | ||||
|  | ||||
| 		return false; | ||||
| 	} | ||||
|  | ||||
| 	static public function add($name, $title, $body, $player_id, $php, $enable_tinymce, $access, &$errors) | ||||
| 	{ | ||||
| 		if(!self::verify($name, $title, $body, $player_id, $php, $enable_tinymce, $access, $errors)) { | ||||
| 			return false; | ||||
| 		} | ||||
|  | ||||
| 		global $db; | ||||
| 		$query = $db->select(TABLE_PREFIX . 'pages', array('name' => $name)); | ||||
| 		if ($query === false) | ||||
| 			$db->insert(TABLE_PREFIX . 'pages', | ||||
| 				array( | ||||
| 					'name' => $name, | ||||
| 					'title' => $title, | ||||
| 					'body' => $body, | ||||
| 					'player_id' => $player_id, | ||||
| 					'php' => $php ? '1' : '0', | ||||
| 					'enable_tinymce' => $enable_tinymce ? '1' : '0', | ||||
| 					'access' => $access | ||||
| 				) | ||||
| 			); | ||||
| 		else | ||||
| 			$errors[] = 'Page with this link already exists.'; | ||||
|  | ||||
| 		return !count($errors); | ||||
| 	} | ||||
|  | ||||
| 	static public function update($id, $name, $title, $body, $player_id, $php, $enable_tinymce, $access, &$errors) | ||||
| 	{ | ||||
| 		if(!self::verify($name, $title, $body, $player_id, $php, $enable_tinymce, $access, $errors)) { | ||||
| 			return false; | ||||
| 		} | ||||
|  | ||||
| 		global $db; | ||||
| 		$db->update(TABLE_PREFIX . 'pages', | ||||
| 			array( | ||||
| 				'name' => $name, | ||||
| 				'title' => $title, | ||||
| 				'body' => $body, | ||||
| 				'player_id' => $player_id, | ||||
| 				'php' => $php ? '1' : '0', | ||||
| 				'enable_tinymce' => $enable_tinymce ? '1' : '0', | ||||
| 				'access' => $access | ||||
| 			), | ||||
| 			array('id' => $id)); | ||||
|  | ||||
| 		return true; | ||||
| 	} | ||||
|  | ||||
| 	static public function delete($id, &$errors) | ||||
| 	{ | ||||
| 		global $db; | ||||
| 		if (isset($id)) { | ||||
| 			if ($db->select(TABLE_PREFIX . 'pages', array('id' => $id)) !== false) | ||||
| 				$db->delete(TABLE_PREFIX . 'pages', array('id' => $id)); | ||||
| 			else | ||||
| 				$errors[] = 'Page with id ' . $id . ' does not exists.'; | ||||
| 		} else | ||||
| 			$errors[] = 'id not set'; | ||||
|  | ||||
| 		return !count($errors); | ||||
| 	} | ||||
|  | ||||
| 	static public function toggleHidden($id, &$errors, &$status) | ||||
| 	{ | ||||
| 		global $db; | ||||
| 		if (isset($id)) { | ||||
| 			$query = $db->select(TABLE_PREFIX . 'pages', array('id' => $id)); | ||||
| 			if ($query !== false) { | ||||
| 				$db->update(TABLE_PREFIX . 'pages', array('hidden' => ($query['hidden'] == 1 ? 0 : 1)), array('id' => $id)); | ||||
| 				$status = $query['hidden']; | ||||
| 			} | ||||
| 			else { | ||||
| 				$errors[] = 'Page with id ' . $id . ' does not exists.'; | ||||
| 			} | ||||
| 		} else | ||||
| 			$errors[] = 'id not set'; | ||||
|  | ||||
| 		return !count($errors); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| ?> | ||||
							
								
								
									
										19
									
								
								admin/pages/phpinfo.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,19 @@ | ||||
| <?php | ||||
| /** | ||||
|  * PHP Info | ||||
|  * | ||||
|  * @package   MyAAC | ||||
|  * @author    Slawkens <slawkens@gmail.com> | ||||
|  * @copyright 2019 MyAAC | ||||
|  * @link      https://my-aac.org | ||||
|  */ | ||||
| defined('MYAAC') or die('Direct access not allowed!'); | ||||
| $title = 'PHP Info'; | ||||
|  | ||||
| if (!function_exists('phpinfo')) { ?> | ||||
| 	<b>phpinfo()</b> function is disabled in your webserver config.<br/> | ||||
| 	You can enable it by editing <b>php.ini</b> file. | ||||
| 	<?php return; | ||||
| } | ||||
| ?> | ||||
| <iframe src="<?php echo ADMIN_URL; ?>tools/phpinfo.php" width="1024" height="550"></iframe> | ||||
							
								
								
									
										908
									
								
								admin/pages/players.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,908 @@ | ||||
| <?php | ||||
| /** | ||||
|  * Players editor | ||||
|  * | ||||
|  * @package   MyAAC | ||||
|  * @author    Slawkens <slawkens@gmail.com> | ||||
|  * @copyright 2019 MyAAC | ||||
|  * @link      https://my-aac.org | ||||
|  */ | ||||
| defined('MYAAC') or die('Direct access not allowed!'); | ||||
|  | ||||
| $title = 'Player editor'; | ||||
| $player_base = ADMIN_URL . '?p=players'; | ||||
|  | ||||
| $use_datatable = true; | ||||
| require_once LIBS . 'forum.php'; | ||||
|  | ||||
| $skills = array( | ||||
| 	POT::SKILL_FIST => array('Fist fighting', 'fist'), | ||||
| 	POT::SKILL_CLUB => array('Club fighting', 'club'), | ||||
| 	POT::SKILL_SWORD => array('Sword fighting', 'sword'), | ||||
| 	POT::SKILL_AXE => array('Axe fighting', 'axe'), | ||||
| 	POT::SKILL_DIST => array('Distance fighting', 'dist'), | ||||
| 	POT::SKILL_SHIELD => array('Shielding', 'shield'), | ||||
| 	POT::SKILL_FISH => array('Fishing', 'fish') | ||||
| ); | ||||
|  | ||||
| $hasBlessingsColumn = $db->hasColumn('players', 'blessings'); | ||||
| $hasBlessingColumn = $db->hasColumn('players', 'blessings1'); | ||||
| $hasLookAddons = $db->hasColumn('players', 'lookaddons'); | ||||
|  | ||||
| $skull_type = array("None", "Yellow", "Green", "White", "Red", "Black", "Orange"); | ||||
| ?> | ||||
|  | ||||
| <link rel="stylesheet" type="text/css" href="<?php echo BASE_URL; ?>tools/css/jquery.datetimepicker.css"/ > | ||||
| <script src="<?php echo BASE_URL; ?>tools/js/jquery.datetimepicker.js"></script> | ||||
|  | ||||
| <?php | ||||
| $id = 0; | ||||
| $search_player = ''; | ||||
| if (isset($_REQUEST['id'])) | ||||
| 	$id = (int)$_REQUEST['id']; | ||||
| else if (isset($_REQUEST['search'])) { | ||||
| 	$search_player = $_REQUEST['search']; | ||||
| 	if (strlen($search_player) < 3 && !Validator::number($search_player)) { | ||||
| 		echo_error('Player name is too short.'); | ||||
| 	} else { | ||||
| 		$query = $db->query('SELECT `id` FROM `players` WHERE `name` = ' . $db->quote($search_player)); | ||||
| 		if ($query->rowCount() == 1) { | ||||
| 			$query = $query->fetch(); | ||||
| 			$id = (int)$query['id']; | ||||
| 		} else { | ||||
| 			$query = $db->query('SELECT `id`, `name` FROM `players` WHERE `name` LIKE ' . $db->quote('%' . $search_player . '%')); | ||||
| 			if ($query->rowCount() > 0 && $query->rowCount() <= 10) { | ||||
| 				$str_construct = 'Do you mean?<ul>'; | ||||
| 				foreach ($query as $row) | ||||
| 					$str_construct .= '<li><a href="' . $player_base . '&id=' . $row['id'] . '">' . $row['name'] . '</a></li>'; | ||||
| 				$str_construct .= '</ul>'; | ||||
| 				echo_error($str_construct); | ||||
| 			} else if ($query->rowCount() > 10) | ||||
| 				echo_error('Specified name resulted with too many players.'); | ||||
| 			else | ||||
| 				echo_error('No entries found.'); | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| ?> | ||||
| <div class="row"> | ||||
| 	<?php | ||||
| 	$groups = new OTS_Groups_List(); | ||||
| 	if ($id > 0) { | ||||
| 		$player = new OTS_Player(); | ||||
| 		$player->load($id); | ||||
|  | ||||
| 		if (isset($player) && $player->isLoaded() && isset($_POST['save'])) {// we want to save | ||||
| 			$error = false; | ||||
|  | ||||
| 			if ($player->isOnline()) | ||||
| 				echo_error('This player is actually online. You can\'t edit online players.'); | ||||
|  | ||||
| 			$name = $_POST['name']; | ||||
| 			$_error = ''; | ||||
| 			if (!Validator::characterName($name)) | ||||
| 				echo_error(Validator::getLastError()); | ||||
|  | ||||
| 			//if(!Validator::newCharacterName($name) | ||||
| 			//	echo_error(Validator::getLastError()); | ||||
|  | ||||
| 			$player_db = new OTS_Player(); | ||||
| 			$player_db->find($name); | ||||
| 			if ($player_db->isLoaded() && $player->getName() != $name) | ||||
| 				echo_error('This name is already used. Please choose another name!'); | ||||
|  | ||||
| 			$account_id = $_POST['account_id']; | ||||
| 			verify_number($account_id, 'Account id', 11); | ||||
|  | ||||
| 			$account_db = new OTS_Account(); | ||||
| 			$account_db->load($account_id); | ||||
| 			if (!$account_db->isLoaded()) | ||||
| 				echo_error('Account with this id doesn\'t exist.'); | ||||
|  | ||||
| 			$group = $_POST['group']; | ||||
| 			if ($groups->getGroup($group) == false) | ||||
| 				echo_error('Group with this id doesn\'t exist'); | ||||
|  | ||||
| 			$level = $_POST['level']; | ||||
| 			verify_number($level, 'Level', 11); | ||||
|  | ||||
| 			$experience = $_POST['experience']; | ||||
| 			verify_number($experience, 'Experience', 20); | ||||
|  | ||||
| 			$vocation = $_POST['vocation']; | ||||
| 			verify_number($vocation, 'Vocation id', 11); | ||||
|  | ||||
| 			if (!isset($config['vocations'][$vocation])) { | ||||
| 				echo_error("Vocation with this id doesn't exist."); | ||||
| 			} | ||||
|  | ||||
| 			// health | ||||
| 			$health = $_POST['health']; | ||||
| 			verify_number($health, 'Health', 11); | ||||
| 			$health_max = $_POST['health_max']; | ||||
| 			verify_number($health_max, 'Health max', 11); | ||||
|  | ||||
| 			// mana | ||||
| 			$magic_level = $_POST['magic_level']; | ||||
| 			verify_number($magic_level, 'Magic_level', 11); | ||||
| 			$mana = $_POST['mana']; | ||||
| 			verify_number($mana, 'Mana', 11); | ||||
| 			$mana_max = $_POST['mana_max']; | ||||
| 			verify_number($mana_max, 'Mana max', 11); | ||||
| 			$mana_spent = $_POST['mana_spent']; | ||||
| 			verify_number($mana_spent, 'Mana spent', 11); | ||||
|  | ||||
| 			// look | ||||
| 			$look_body = $_POST['look_body']; | ||||
| 			verify_number($look_body, 'Look body', 11); | ||||
| 			$look_feet = $_POST['look_feet']; | ||||
| 			verify_number($look_feet, 'Look feet', 11); | ||||
| 			$look_head = $_POST['look_head']; | ||||
| 			verify_number($look_head, 'Look head', 11); | ||||
| 			$look_legs = $_POST['look_legs']; | ||||
| 			verify_number($look_legs, 'Look legs', 11); | ||||
| 			$look_type = $_POST['look_type']; | ||||
| 			verify_number($look_type, 'Look type', 11); | ||||
| 			if ($hasLookAddons) { | ||||
| 				$look_addons = $_POST['look_addons']; | ||||
| 				verify_number($look_addons, 'Look addons', 11); | ||||
| 			} | ||||
|  | ||||
| 			// pos | ||||
| 			$pos_x = $_POST['pos_x']; | ||||
| 			verify_number($pos_x, 'Position x', 11); | ||||
| 			$pos_y = $_POST['pos_y']; | ||||
| 			verify_number($pos_y, 'Position y', 11); | ||||
| 			$pos_z = $_POST['pos_z']; | ||||
| 			verify_number($pos_z, 'Position z', 11); | ||||
|  | ||||
| 			$soul = $_POST['soul']; | ||||
| 			verify_number($soul, 'Soul', 10); | ||||
|  | ||||
| 			$town = $_POST['town']; | ||||
| 			verify_number($town, 'Town', 11); | ||||
|  | ||||
| 			$capacity = $_POST['capacity']; | ||||
| 			verify_number($capacity, 'Capacity', 11); | ||||
| 			$sex = $_POST['sex']; | ||||
| 			verify_number($sex, 'Sex', 1); | ||||
|  | ||||
| 			$lastlogin = strtotime($_POST['lastlogin']); | ||||
| 			verify_number($lastlogin, 'Last login', 20); | ||||
| 			$lastlogout = strtotime($_POST['lastlogout']); | ||||
| 			verify_number($lastlogout, 'Last logout', 20); | ||||
|  | ||||
| 			$skull = $_POST['skull']; | ||||
| 			verify_number($skull, 'Skull', 1); | ||||
| 			$skull_time = $_POST['skull_time']; | ||||
| 			verify_number($skull_time, 'Skull time', 11); | ||||
|  | ||||
| 			if ($db->hasColumn('players', 'loss_experience')) { | ||||
| 				$loss_experience = $_POST['loss_experience']; | ||||
| 				verify_number($loss_experience, 'Loss experience', 11); | ||||
| 				$loss_mana = $_POST['loss_mana']; | ||||
| 				verify_number($loss_mana, 'Loss mana', 11); | ||||
| 				$loss_skills = $_POST['loss_skills']; | ||||
| 				verify_number($loss_skills, 'Loss skills', 11); | ||||
| 				$loss_containers = $_POST['loss_containers']; | ||||
| 				verify_number($loss_containers, 'Loss loss_containers', 11); | ||||
| 				$loss_items = $_POST['loss_items']; | ||||
| 				verify_number($loss_items, 'Loss items', 11); | ||||
| 			} | ||||
| 			if ($db->hasColumn('players', 'offlinetraining_time')) { | ||||
| 				$offlinetraining = $_POST['offlinetraining']; | ||||
| 				verify_number($offlinetraining, 'Offline Training time', 11); | ||||
| 			} | ||||
|  | ||||
| 			if ($hasBlessingsColumn) { | ||||
| 				$blessings = $_POST['blessings']; | ||||
| 				verify_number($blessings, 'Blessings', 2); | ||||
| 			} | ||||
|  | ||||
| 			$balance = $_POST['balance']; | ||||
| 			verify_number($balance, 'Balance', 20); | ||||
| 			if ($db->hasColumn('players', 'stamina')) { | ||||
| 				$stamina = $_POST['stamina']; | ||||
| 				verify_number($stamina, 'Stamina', 20); | ||||
| 			} | ||||
|  | ||||
| 			$deleted = (isset($_POST['deleted']) && $_POST['deleted'] == 'true'); | ||||
| 			$hidden = (isset($_POST['hidden']) && $_POST['hidden'] == 'true'); | ||||
|  | ||||
| 			$created = strtotime($_POST['created']); | ||||
| 			verify_number($created, 'Created', 11); | ||||
|  | ||||
| 			$comment = isset($_POST['comment']) ? htmlspecialchars(stripslashes(substr($_POST['comment'], 0, 2000))) : NULL; | ||||
|  | ||||
| 			foreach ($_POST['skills'] as $skill => $value) | ||||
| 				verify_number($value, $skills[$skill][0], 10); | ||||
| 			foreach ($_POST['skills_tries'] as $skill => $value) | ||||
| 				verify_number($value, $skills[$skill][0] . ' tries', 10); | ||||
|  | ||||
| 			if ($hasBlessingColumn) { | ||||
| 				$bless_count = $_POST['blesscount']; | ||||
| 				for ($i = 1; $i <= $bless_count; $i++) { | ||||
| 					$a = 'blessing' . $i; | ||||
| 					${'blessing' . $i} = (isset($_POST[$a]) && $_POST[$a] == 'true'); | ||||
| 				} | ||||
| 			} | ||||
|  | ||||
| 			if (!$error) { | ||||
| 				$player->setName($name); | ||||
| 				$player->setAccount($account_db); | ||||
| 				$player->setGroup($groups->getGroup($group)); | ||||
| 				$player->setLevel($level); | ||||
| 				$player->setExperience($experience); | ||||
| 				$player->setVocation($vocation); | ||||
| 				$player->setHealth($health); | ||||
| 				$player->setHealthMax($health_max); | ||||
| 				$player->setMagLevel($magic_level); | ||||
| 				$player->setMana($mana); | ||||
| 				$player->setManaMax($mana_max); | ||||
| 				$player->setManaSpent($mana_spent); | ||||
| 				$player->setLookBody($look_body); | ||||
| 				$player->setLookFeet($look_feet); | ||||
| 				$player->setLookHead($look_head); | ||||
| 				$player->setLookLegs($look_legs); | ||||
| 				$player->setLookType($look_type); | ||||
| 				if ($hasLookAddons) | ||||
| 					$player->setLookAddons($look_addons); | ||||
| 				if ($db->hasColumn('players', 'offlinetraining_time')) | ||||
| 					$player->setCustomField('offlinetraining_time', $offlinetraining); | ||||
| 				$player->setPosX($pos_x); | ||||
| 				$player->setPosY($pos_y); | ||||
| 				$player->setPosZ($pos_z); | ||||
| 				$player->setSoul($soul); | ||||
| 				$player->setTownId($town); | ||||
| 				$player->setCap($capacity); | ||||
| 				$player->setSex($sex); | ||||
| 				$player->setLastLogin($lastlogin); | ||||
| 				$player->setLastLogout($lastlogout); | ||||
| 				//$player->setLastIP(ip2long($lastip)); | ||||
| 				$player->setSkull($skull); | ||||
| 				$player->setSkullTime($skull_time); | ||||
| 				if ($db->hasColumn('players', 'loss_experience')) { | ||||
| 					$player->setLossExperience($loss_experience); | ||||
| 					$player->setLossMana($loss_mana); | ||||
| 					$player->setLossSkills($loss_skills); | ||||
| 					$player->setLossContainers($loss_containers); | ||||
| 					$player->setLossItems($loss_items); | ||||
| 				} | ||||
| 				if ($db->hasColumn('players', 'blessings')) | ||||
| 					$player->setBlessings($blessings); | ||||
|  | ||||
| 				if ($hasBlessingColumn) { | ||||
| 					for ($i = 1; $i <= $bless_count; $i++) { | ||||
| 						$a = 'blessing' . $i; | ||||
| 						$player->setCustomField('blessings' . $i, ${'blessing' . $i} ? '1' : '0'); | ||||
| 					} | ||||
| 				} | ||||
| 				$player->setBalance($balance); | ||||
| 				if ($db->hasColumn('players', 'stamina')) | ||||
| 					$player->setStamina($stamina); | ||||
| 				if ($db->hasColumn('players', 'deletion')) | ||||
| 					$player->setCustomField('deletion', $deleted ? '1' : '0'); | ||||
| 				else | ||||
| 					$player->setCustomField('deleted', $deleted ? '1' : '0'); | ||||
| 				$player->setCustomField('hidden', $hidden ? '1' : '0'); | ||||
| 				$player->setCustomField('created', $created); | ||||
| 				if (isset($comment)) | ||||
| 					$player->setCustomField('comment', $comment); | ||||
|  | ||||
| 				foreach ($_POST['skills'] as $skill => $value) { | ||||
| 					$player->setSkill($skill, $value); | ||||
| 				} | ||||
| 				foreach ($_POST['skills_tries'] as $skill => $value) { | ||||
| 					$player->setSkillTries($skill, $value); | ||||
| 				} | ||||
| 				$player->save(); | ||||
| 				echo_success('Player saved at: ' . date('G:i')); | ||||
| 				$player->load($id); | ||||
| 			} | ||||
| 		} | ||||
| 	} else if ($id == 0) { | ||||
| 		$players_db = $db->query('SELECT `id`, `name`, `level` FROM `players` ORDER BY `id` asc'); | ||||
| 		?> | ||||
| 		<div class="col-12 col-sm-12 col-lg-10"> | ||||
| 			<div class="card card-info card-outline"> | ||||
| 				<div class="card-header"> | ||||
| 					<h5 class="m-0">Players</h5> | ||||
| 				</div> | ||||
| 				<div class="card-body"> | ||||
| 					<table class="player_datatable table table-striped table-bordered table-responsive d-md-table"> | ||||
| 						<thead> | ||||
| 						<tr> | ||||
| 							<th>ID</th> | ||||
| 							<th>Name</th> | ||||
| 							<th>Level</th> | ||||
| 							<th style="width: 40px">Edit</th> | ||||
| 						</tr> | ||||
| 						</thead> | ||||
| 						<tbody> | ||||
| 						<?php foreach ($players_db as $player_db): ?> | ||||
| 							<tr> | ||||
| 								<th><?php echo $player_db['id']; ?></th> | ||||
| 								<td><?php echo $player_db['name']; ?></a></td> | ||||
| 								<td><?php echo $player_db['level']; ?></a></td> | ||||
|  | ||||
| 								<td><a href="?p=players&id=<?php echo $player_db['id']; ?>" class="btn btn-success btn-sm" title="Edit"> | ||||
| 										<i class="fas fa-pencil-alt"></i> | ||||
| 									</a> | ||||
| 								</td> | ||||
| 							</tr> | ||||
| 						<?php endforeach; ?> | ||||
| 						</tbody> | ||||
| 					</table> | ||||
| 				</div> | ||||
| 			</div> | ||||
| 		</div> | ||||
| 	<?php } ?> | ||||
|  | ||||
| 	<?php | ||||
| 	if (isset($player) && $player->isLoaded()) { | ||||
| 		$account = $player->getAccount(); | ||||
| 		?> | ||||
| 		<div class="col-12 col-sm-12 col-lg-10"> | ||||
| 			<div class="card card-primary card-outline card-outline-tabs"> | ||||
| 				<div class="card-header p-0 border-bottom-0"> | ||||
| 					<ul class="nav nav-tabs" id="tabs-tab" role="tablist"> | ||||
| 						<li class="nav-item"> | ||||
| 							<a class="nav-link active" id="tabs-home-tab" data-toggle="pill" href="#tabs-home">Player</a> | ||||
| 						</li> | ||||
| 						<li class="nav-item"> | ||||
| 							<a class="nav-link" id="tabs-home-tab" data-toggle="pill" href="#tabs-stats">Stats</a> | ||||
| 						</li> | ||||
| 						<li class="nav-item"> | ||||
| 							<a class="nav-link" id="tabs-home-tab" data-toggle="pill" href="#tabs-skills">Skills</a> | ||||
| 						</li> | ||||
| 						<li class="nav-item"> | ||||
| 							<a class="nav-link" id="tabs-home-tab" data-toggle="pill" href="#tabs-pos">Pos/Look</a> | ||||
| 						</li> | ||||
| 						<li class="nav-item"> | ||||
| 							<a class="nav-link" id="tabs-home-tab" data-toggle="pill" href="#tabs-misc">Misc</a> | ||||
| 						</li> | ||||
| 						<li class="nav-item"> | ||||
| 							<a class="nav-link" id="tabs-posts-tab" data-toggle="pill" href="#tabs-posts">Posts</a> | ||||
| 						</li> | ||||
| 						<li class="nav-item"> | ||||
| 							<a class="nav-link" id="tabs-chars-tab" data-toggle="pill" href="#tabs-chars">Characters</a> | ||||
| 						</li> | ||||
| 					</ul> | ||||
| 				</div> | ||||
| 				<form action="<?php echo $player_base . ((isset($id) && $id > 0) ? '&id=' . $id : ''); ?>" method="post"> | ||||
| 					<div class="card-body"> | ||||
| 						<div class="tab-content" id="tabs-tabContent"> | ||||
| 							<div class="tab-pane fade active show" id="tabs-home"> | ||||
| 								<div class="form-group row"> | ||||
| 									<div class="col-12 col-sm-12 col-lg-6"> | ||||
| 										<label for="name" class="control-label">Name</label> | ||||
| 										<input type="text" class="form-control" id="name" name="name" autocomplete="off" value="<?php echo $player->getName(); ?>"/> | ||||
| 									</div> | ||||
| 									<div class="col-12 col-sm-12 col-lg-6"> | ||||
| 										<label for="account_id">Account id:</label> | ||||
| 										<input type="text" class="form-control" id="account_id" name="account_id" autocomplete="off" size="8" maxlength="11" value="<?php echo $account->getId(); ?>"/> | ||||
| 									</div> | ||||
| 								</div> | ||||
| 								<div class="form-group row"> | ||||
| 									<div class="col-12 col-sm-12 col-lg-6"> | ||||
| 										<label for="group">Group:</label> | ||||
| 										<select name="group" id="group" class="form-control custom-select"> | ||||
| 											<?php foreach ($groups->getGroups() as $id => $group): ?> | ||||
| 												<option value="<?php echo $id; ?>" <?php echo($player->getGroup()->getId() == $id ? 'selected' : ''); ?>><?php echo $group->getName(); ?></option> | ||||
| 											<?php endforeach; ?> | ||||
| 										</select> | ||||
| 									</div> | ||||
| 									<div class="col-12 col-sm-12 col-lg-6"> | ||||
| 										<label for="vocation">Vocation</label> | ||||
| 										<select name="vocation" id="vocation" class="form-control custom-select"> | ||||
| 											<?php | ||||
| 											foreach ($config['vocations'] as $id => $name) { | ||||
| 												echo '<option value=' . $id . ($id == $player->getVocation() ? ' selected' : '') . '>' . $name . '</option>'; | ||||
| 											} | ||||
| 											?> | ||||
| 										</select> | ||||
| 									</div> | ||||
| 								</div> | ||||
| 								<div class="form-group row"> | ||||
| 									<div class="col-12 col-sm-12 col-lg-6"> | ||||
| 										<label for="sex">Sex:</label> | ||||
| 										<select name="sex" id="sex" class="form-control custom-select">> | ||||
| 											<?php foreach ($config['genders'] as $id => $sex): ?> | ||||
| 												<option value="<?php echo $id; ?>" <?php echo($player->getSex() == $id ? 'selected' : ''); ?>><?php echo strtolower($sex); ?></option> | ||||
| 											<?php endforeach; ?> | ||||
| 										</select> | ||||
| 									</div> | ||||
| 									<div class="col-12 col-sm-12 col-lg-6"> | ||||
| 										<label for="town">Town:</label> | ||||
| 										<select name="town" id="town" class="form-control"> | ||||
| 											<?php | ||||
| 											$configTowns = config('towns'); | ||||
| 											if (!isset($configTowns[$player->getTownId()])) { | ||||
| 												$configTowns[$player->getTownId()] = 'Unknown Town'; | ||||
| 											} | ||||
|  | ||||
| 											foreach ($configTowns as $id => $town): ?> | ||||
| 												<option value="<?php echo $id; ?>" <?php echo($player->getTownId() == $id ? 'selected' : ''); ?>><?php echo $town; ?></option> | ||||
| 											<?php endforeach; ?> | ||||
| 										</select> | ||||
| 									</div> | ||||
| 								</div> | ||||
| 								<div class="form-group row"> | ||||
| 									<div class="col-12 col-sm-12 col-lg-6"> | ||||
| 										<label for="skull">Skull:</label> | ||||
| 										<select name="skull" id="skull" class="form-control custom-select"> | ||||
| 											<?php | ||||
|  | ||||
| 											foreach ($skull_type as $id => $s_name) { | ||||
| 												echo '<option value=' . $id . ($id == $player->getSkull() ? ' selected' : '') . '>' . $s_name . '</option>'; | ||||
| 											} | ||||
| 											?> | ||||
| 										</select> | ||||
| 									</div> | ||||
| 									<div class="col-12 col-sm-12 col-lg-6"> | ||||
| 										<label for="skull_time">Skull time:</label> | ||||
| 										<input type="text" class="form-control" id="skull_time" name="skull_time" | ||||
| 											   autocomplete="off" maxlength="11" | ||||
| 											   value="<?php echo $player->getSkullTime(); ?>"/> | ||||
| 									</div> | ||||
| 								</div> | ||||
| 								<div class="form-group row"> | ||||
| 									<?php if ($hasBlessingColumn): | ||||
| 										$bless_count = $player->countBlessings(); | ||||
| 										$bless = $player->checkBlessings($bless_count); ?> | ||||
| 										<input type="hidden" name="blesscount" value="<?php echo $bless_count; ?>"/> | ||||
| 										<div class="col-12 col-sm-12 col-lg-6"> | ||||
| 											<label>Blessings:</label><br/> | ||||
| 											<?php for ($i = 1; $i <= $bless_count; $i++): ?> | ||||
| 												<label><input class="" type="checkbox" name="blessing<?php echo $i; ?>" id="blessing<?php echo $i; ?>" value="true"<?php echo(($bless[$i - 1] == 1) ? ' checked' : '') ?>/><?php echo $i; ?></label> | ||||
| 											<?php endfor ?> | ||||
| 										</div> | ||||
| 									<?php endif; ?> | ||||
| 									<?php if ($hasBlessingsColumn): ?> | ||||
| 										<div class="col-12 col-sm-12 col-lg-6"> | ||||
| 											<label for="blessings">Blessings:</label> | ||||
| 											<input type="text" class="form-control" id="blessings" name="blessings" autocomplete="off" maxlength="11" value="<?php echo $player->getBlessings(); ?>"/> | ||||
| 										</div> | ||||
| 									<?php endif; ?> | ||||
| 									<div class="col-12 col-sm-12 col-lg-6"> | ||||
| 										<label for="balance" class="control-label">Bank Balance:</label> | ||||
| 										<input type="text" class="form-control" id="balance" name="balance" autocomplete="off" maxlength="20" value="<?php echo $player->getBalance(); ?>"/> | ||||
| 									</div> | ||||
| 								</div> | ||||
| 								<div class="form-group row"> | ||||
| 									<div class="col-12 col-sm-12 col-lg-6"> | ||||
| 										<div class="custom-control custom-switch custom-switch-on-danger"> | ||||
| 											<input type="checkbox" class="custom-control-input" name="deleted" id="deleted" value="true" <?php echo($player->getCustomField($db->hasColumn('players', 'deletion') ? 'deletion' : 'deleted') == '1' ? ' checked' : ''); ?>> | ||||
| 											<label class="custom-control-label" for="deleted">Deleted</label> | ||||
| 										</div> | ||||
| 									</div> | ||||
| 									<div class="col-12 col-sm-12 col-lg-6"> | ||||
| 										<div class="custom-control custom-switch custom-switch-on-success"> | ||||
| 											<input type="checkbox" class="custom-control-input" name="hidden" id="hidden" value="true" <?php echo($player->isHidden() ? ' checked' : ''); ?>> | ||||
| 											<label class="custom-control-label" for="hidden">Hidden</label> | ||||
| 										</div> | ||||
| 									</div> | ||||
| 								</div> | ||||
| 							</div> | ||||
| 							<div class="tab-pane fade" id="tabs-stats"> | ||||
| 								<div class="form-group row"> | ||||
| 									<div class="col-12 col-sm-12 col-lg-6"> | ||||
| 										<label for="level" class="control-label">Level:</label> | ||||
| 										<input type="text" class="form-control" id="level" name="level" autocomplete="off" value="<?php echo $player->getLevel(); ?>"/> | ||||
| 									</div> | ||||
| 									<div class="col-12 col-sm-12 col-lg-6"> | ||||
| 										<label for="experience" class="control-label">Experience:</label> | ||||
| 										<input type="text" class="form-control" id="experience" name="experience" autocomplete="off" value="<?php echo $player->getExperience(); ?>"/> | ||||
| 									</div> | ||||
| 								</div> | ||||
| 								<div class="form-group row"> | ||||
| 									<div class="col-12 col-sm-12 col-lg-6"> | ||||
| 										<label for="magic_level" class="control-label">Magic level:</label> | ||||
| 										<input type="text" class="form-control" id="magic_level" name="magic_level" autocomplete="off" size="8" maxlength="11" value="<?php echo $player->getMagLevel(); ?>"/> | ||||
| 									</div> | ||||
| 									<div class="col-12 col-sm-12 col-lg-6"> | ||||
| 										<label for="mana_spent" class="control-label">Mana spent:</label> | ||||
| 										<input type="text" class="form-control" id="mana_spent" name="mana_spent" autocomplete="off" size="3" maxlength="11" value="<?php echo $player->getManaSpent(); ?>"/> | ||||
| 									</div> | ||||
| 								</div> | ||||
| 								<div class="form-group row"> | ||||
| 									<div class="col-12 col-sm-12 col-lg-6"> | ||||
| 										<label for="health" class="control-label">Health:</label> | ||||
| 										<input type="text" class="form-control" id="health" name="health" autocomplete="off" size="5" maxlength="11" value="<?php echo $player->getHealth(); ?>"/> | ||||
| 									</div> | ||||
| 									<div class="col-12 col-sm-12 col-lg-6"> | ||||
| 										<label for="health_max" class="control-label">Health max:</label> | ||||
| 										<input type="text" class="form-control" id="health_max" name="health_max" autocomplete="off" size="5" maxlength="11" value="<?php echo $player->getHealthMax(); ?>"/> | ||||
| 									</div> | ||||
| 								</div> | ||||
| 								<div class="form-group row"> | ||||
| 									<div class="col-12 col-sm-12 col-lg-6"> | ||||
| 										<label for="mana" class="control-label">Mana:</label> | ||||
| 										<input type="text" class="form-control" id="mana" name="mana" autocomplete="off" size="3" maxlength="11" value="<?php echo $player->getMana(); ?>"/> | ||||
| 									</div> | ||||
| 									<div class="col-12 col-sm-12 col-lg-6"> | ||||
| 										<label for="mana_max" class="control-label">Mana max:</label> | ||||
| 										<input type="text" class="form-control" id="mana_max" name="mana_max" autocomplete="off" size="3" maxlength="11" value="<?php echo $player->getManaMax(); ?>"/> | ||||
| 									</div> | ||||
| 								</div> | ||||
| 								<div class="form-group row"> | ||||
| 									<div class="col-12 col-sm-12 col-lg-6"> | ||||
| 										<label for="capacity" class="control-label">Capacity:</label> | ||||
| 										<input type="text" class="form-control" id="capacity" name="capacity" autocomplete="off" size="3" maxlength="11" value="<?php echo $player->getCap(); ?>"/> | ||||
| 									</div> | ||||
| 									<div class="col-12 col-sm-12 col-lg-6"> | ||||
| 										<label for="soul" class="control-label">Soul:</label> | ||||
| 										<input type="text" class="form-control" id="soul" name="soul" autocomplete="off" size="3" maxlength="10" value="<?php echo $player->getSoul(); ?>"/> | ||||
| 									</div> | ||||
| 									<?php if ($db->hasColumn('players', 'stamina')): ?> | ||||
| 										<div class="col-12 col-sm-12 col-lg-6"> | ||||
| 											<label for="stamina" class="control-label">Stamina:</label> | ||||
| 											<input type="text" class="form-control" id="stamina" name="stamina" autocomplete="off" maxlength="20" value="<?php echo $player->getStamina(); ?>"/> | ||||
| 										</div> | ||||
| 									<?php endif; ?> | ||||
| 									<?php if ($db->hasColumn('players', 'offlinetraining_time')): ?> | ||||
| 										<div class="col-12 col-sm-12 col-lg-6"> | ||||
| 											<label for="offlinetraining" class="control-label">Offline Training | ||||
| 												Time:</label> | ||||
| 											<input type="text" class="form-control" id="offlinetraining" name="offlinetraining" autocomplete="off" maxlength="11" value="<?php echo $player->getCustomField('offlinetraining_time'); ?>"/> | ||||
| 										</div> | ||||
| 									<?php endif; ?> | ||||
| 								</div> | ||||
| 							</div> | ||||
| 							<div class="tab-pane fade" id="tabs-skills"> | ||||
| 								<?php | ||||
| 								foreach ($skills as $id => $info) { | ||||
| 									?> | ||||
| 									<div class="form-group row"> | ||||
| 										<div class="col-12 col-sm-12 col-lg-6"> | ||||
| 											<?php echo '<label for="skills[' . $id . ']" class="control-label">' . $info[0] . '</label> | ||||
| 									<input type="text" class="form-control" id="skills[' . $id . ']" name="skills[' . $id . ']" maxlength="10" autocomplete="off" value="' . $player->getSkill($id) . '"/>'; ?> | ||||
| 										</div> | ||||
| 										<div class="col-12 col-sm-12 col-lg-6"> | ||||
| 											<?php echo '<label for="skills_tries[' . $id . ']" class="control-label">' . $info[0] . ' tries</label> | ||||
| 									<input type="text" class="form-control" id="skills_tries[' . $id . ']" name="skills_tries[' . $id . ']" maxlength="10" autocomplete="off" value="' . $player->getSkillTries($id) . '"/>'; ?> | ||||
| 										</div> | ||||
| 									</div> | ||||
| 								<?php } ?> | ||||
| 							</div> | ||||
| 							<div class="tab-pane fade" id="tabs-pos"> | ||||
| 								<?php $outfit = $config['outfit_images_url'] . '?id=' . $player->getLookType() . ($hasLookAddons ? '&addons=' . $player->getLookAddons() : '') . '&head=' . $player->getLookHead() . '&body=' . $player->getLookBody() . '&legs=' . $player->getLookLegs() . '&feet=' . $player->getLookFeet(); ?> | ||||
| 								<div id="imgchar" style="width:64px;height:64px;position:absolute; top:30px; right:30px"> | ||||
| 									<img id="player_outfit" style="margin-left:0;margin-top:0;width:64px;height:64px;" src="<?php echo $outfit; ?>" alt="player outfit"/> | ||||
| 								</div> | ||||
| 								<td>Position:</td> | ||||
| 								<div class="form-group row"> | ||||
| 									<div class="col-12 col-sm-12 col-lg-4"> | ||||
| 										<label for="pos_x" class="control-label">X:</label> | ||||
| 										<input type="text" class="form-control" id="pos_x" name="pos_x" autocomplete="off" maxlength="11" value="<?php echo $player->getPosX(); ?>"/> | ||||
| 									</div> | ||||
| 									<div class="col-12 col-sm-12 col-lg-4"> | ||||
| 										<label for="pos_y" class="control-label">Y:</label> | ||||
| 										<input type="text" class="form-control" id="pos_y" name="pos_y" autocomplete="off" maxlength="11" value="<?php echo $player->getPosY(); ?>"/> | ||||
| 									</div> | ||||
| 									<div class="col-12 col-sm-12 col-lg-4"> | ||||
| 										<label for="pos_z" class="control-label">Z:</label> | ||||
| 										<input type="text" class="form-control" id="pos_z" name="pos_z" autocomplete="off" maxlength="11" value="<?php echo $player->getPosZ(); ?>"/> | ||||
| 									</div> | ||||
| 								</div> | ||||
| 								<td>Look:</td> | ||||
| 								<div class="form-group row"> | ||||
| 									<div class="col-12 col-sm-12 col-lg-3"> | ||||
| 										<label for="look_head" class="control-label">Head: <span id="look_head_val" class="font-weight-bold text-primary"></span></label> | ||||
| 										<input class="custom-range" type="range" min="0" max="132" id="look_head" name="look_head" value="<?php echo $player->getLookHead(); ?>"/> | ||||
| 									</div> | ||||
| 									<div class="col-12 col-sm-12 col-lg-3"> | ||||
| 										<label for="look_body" class="control-label">Body: <span id="look_body_val" class="font-weight-bold text-primary"></span></label> | ||||
| 										<input type="range" min="0" max="132" | ||||
| 											   value="<?php echo $player->getLookBody(); ?>" | ||||
| 											   class="custom-range" id="look_body" name="look_body"> | ||||
| 									</div> | ||||
| 									<div class="col-12 col-sm-12 col-lg-3"> | ||||
| 										<label for="look_legs" class="control-label">Legs: <span id="look_legs_val" class="font-weight-bold text-primary"></span></label> | ||||
| 										<input type="range" min="0" max="132" | ||||
| 											   value="<?php echo $player->getLookLegs(); ?>" | ||||
| 											   class="custom-range" id="look_legs" name="look_legs"> | ||||
| 									</div> | ||||
| 									<div class="col-12 col-sm-12 col-lg-3"> | ||||
| 										<label for="look_feet" class="control-label">Feet: <span id="look_feet_val" class="font-weight-bold text-primary"></span></label> | ||||
| 										<input type="range" min="0" max="132" | ||||
| 											   value="<?php echo $player->getLookBody(); ?>" | ||||
| 											   class="custom-range" id="look_feet" name="look_feet"> | ||||
| 									</div> | ||||
| 								</div> | ||||
| 								<div class="form-group row"> | ||||
| 									<div class="col-12 col-sm-12 col-lg-6"> | ||||
| 										<label for="look_type" class="control-label">Type:</label> | ||||
| 										<?php | ||||
| 										$outfitlist = null; | ||||
| 										$outfitlist = Outfits_loadfromXML(); | ||||
| 										if ($outfitlist) { ?> | ||||
| 											<select name="look_type" id="look_type" class="form-control custom-select"> | ||||
| 												<?php | ||||
| 												foreach ($outfitlist as $id => $outfit) { | ||||
| 													if ($outfit['enabled'] == 'yes') ; | ||||
| 													echo '<option value=' . $outfit['id'] . ($outfit['id'] == $player->getLookType() ? ' selected' : '') . '>' . $outfit['name'] . ' - ' . ($outfit['type'] == 1 ? 'Male' : 'Female') . '</option>'; | ||||
| 												} | ||||
| 												?> | ||||
| 											</select> | ||||
| 										<?php } else { ?> | ||||
| 											<input type="text" class="form-control" id="look_type" name="look_type" autocomplete="off" maxlength="11" value="<?php echo $player->getLookType(); ?>"/> | ||||
| 										<?php } ?> | ||||
| 									</div> | ||||
| 									<?php if ($hasLookAddons): ?> | ||||
| 										<div class="col-12 col-sm-12 col-lg-6"> | ||||
| 											<label for="look_addons" class="control-label">Addons:</label> | ||||
| 											<select name="look_addons" id="look_addons" class="form-control custom-select"> | ||||
| 												<?php | ||||
| 												$addon_type = array("None", "First", "Second", "Both"); | ||||
| 												foreach ($addon_type as $id => $s_name) { | ||||
| 													echo '<option value=' . $id . ($id == $player->getLookAddons() ? ' selected' : '') . '>' . $s_name . '</option>'; | ||||
| 												} | ||||
| 												?> | ||||
| 											</select> | ||||
| 										</div> | ||||
| 									<?php endif; ?> | ||||
| 								</div> | ||||
| 							</div> | ||||
| 							<div class="tab-pane fade" id="tabs-misc"> | ||||
| 								<div class="form-group row"> | ||||
| 									<div class="col-12 col-sm-12 col-lg-6"> | ||||
| 										<label for="created" class="control-label">Created:</label> | ||||
| 										<input type="text" class="form-control" id="created" name="created" | ||||
| 											   autocomplete="off" | ||||
| 											   maxlength="10" | ||||
| 											   value="<?php echo date("M d Y, H:i:s", $player->getCustomField('created')); ?>"/> | ||||
| 									</div> | ||||
| 									<div class="col-12 col-sm-12 col-lg-6"> | ||||
| 										<label for="lastlogin" class="control-label">Last login:</label> | ||||
| 										<input type="text" class="form-control" id="lastlogin" name="lastlogin" autocomplete="off" maxlength="20" value="<?php echo date("M d Y, H:i:s", $player->getLastLogin()); ?>"/> | ||||
| 									</div> | ||||
| 									<div class="col-12 col-sm-12 col-lg-6"> | ||||
| 										<label for="lastlogout" class="control-label">Last logout:</label> | ||||
| 										<input type="text" class="form-control" id="lastlogout" name="lastlogout" autocomplete="off" maxlength="20" value="<?php echo date("M d Y, H:i:s", $player->getLastLogout()); ?>"/> | ||||
| 									</div> | ||||
| 									<div class="col-12 col-sm-12 col-lg-6"> | ||||
| 										<label for="lastip" class="control-label">Last IP:</label> | ||||
| 										<input type="text" class="form-control" id="lastip" name="lastip" autocomplete="off" maxlength="10" value="<?php | ||||
| 										if (strlen($player->getLastIP()) > 11) { | ||||
| 											echo inet_ntop($player->getLastIP()); | ||||
| 										} | ||||
| 										else { | ||||
| 											echo longToIp($player->getLastIP()); | ||||
| 										} | ||||
| 										?>" readonly/> | ||||
| 									</div> | ||||
| 								</div> | ||||
| 								<?php if ($db->hasColumn('players', 'loss_experience')): ?> | ||||
| 									<div class="form-group row"> | ||||
| 										<div class="col-12 col-sm-12 col-lg-6"> | ||||
| 											<label for="loss_experience" class="control-label">Experience | ||||
| 												Loss:</label> | ||||
| 											<input type="text" class="form-control" id="loss_experience" name="loss_experience" autocomplete="off" maxlength="11" value="<?php echo $player->getLossExperience(); ?>"/> | ||||
| 										</div> | ||||
| 										<div class="col-12 col-sm-12 col-lg-6"> | ||||
| 											<label for="loss_mana" class="control-label">Mana Loss:</label> | ||||
| 											<input type="text" class="form-control" id="loss_mana" name="loss_mana" autocomplete="off" maxlength="11" value="<?php echo $player->getLossMana(); ?>"/> | ||||
| 										</div> | ||||
| 										<div class="col-12 col-sm-12 col-lg-6"> | ||||
| 											<label for="loss_skills" class="control-label">Skills Loss:</label> | ||||
| 											<input type="text" class="form-control" id="loss_skills" name="loss_skills" autocomplete="off" maxlength="11" value="<?php echo $player->getLossSkills(); ?>"/> | ||||
| 										</div> | ||||
| 										<div class="col-12 col-sm-12 col-lg-6"> | ||||
| 											<label for="loss_containers" class="control-label">Containers Loss:</label> | ||||
| 											<input type="text" class="form-control" id="loss_containers" name="loss_containers" autocomplete="off" maxlength="11" value="<?php echo $player->getLossContainers(); ?>"/> | ||||
| 										</div> | ||||
| 										<div class="col-12 col-sm-12 col-lg-6"> | ||||
| 											<label for="loss_items" class="control-label">Items Loss:</label> | ||||
| 											<input type="text" class="form-control" id="loss_items" name="loss_items" autocomplete="off" maxlength="11" value="<?php echo $player->getLossItems(); ?>"/> | ||||
| 										</div> | ||||
| 									</div> | ||||
| 								<?php endif; ?> | ||||
| 								<div class="form-group row"> | ||||
| 									<div class="col-12"> | ||||
| 										<label for="comment" class="control-label">Comment:</label> | ||||
| 										<textarea class="form-control" name="comment" rows="10" cols="50" wrap="virtual"><?php echo $player->getCustomField("comment"); ?></textarea> | ||||
| 										<small>[max. length: 2000 chars, 50 lines (ENTERs)]</small> | ||||
| 									</div> | ||||
| 								</div> | ||||
| 							</div> | ||||
| 							<div class="tab-pane fade" id="tabs-posts"> | ||||
| 								<table class="table table-striped table-condensed table-responsive d-md-table"> | ||||
| 									<thead> | ||||
| 									<tr> | ||||
| 										<th class="w-25">Topic</th> | ||||
| 										<th>Content</th> | ||||
| 									</tr> | ||||
| 									</thead> | ||||
| 									<tbody> | ||||
| 									<?php | ||||
| 									$posts = $db->query('SELECT `author_guid`,`section`,`first_post`,`post_text`,`post_date`, `post_topic`,`post_html`,`post_smile`,`' . TABLE_PREFIX . 'forum_boards`.`name` AS `forum_Name` FROM `' . | ||||
| 										TABLE_PREFIX . 'forum` LEFT JOIN `' . TABLE_PREFIX . 'forum_boards` ON `' . | ||||
| 										TABLE_PREFIX . 'forum`.section = `' . TABLE_PREFIX . 'forum_boards`.id WHERE `author_guid` = "' . $player->getId() . '" ORDER BY `post_date` DESC LIMIT 10'); | ||||
| 									if ($posts->rowCount() > 0) { | ||||
| 										$posts = $posts->fetchAll(); | ||||
| 										foreach ($posts as $post) { | ||||
| 											$text = ($post['post_html'] > 0 ? $post['post_text'] : htmlspecialchars($post['post_text'])); | ||||
| 											$post['content'] = ($post['post_html'] > 0 ? $text : Forum::parseBBCode(nl2br($text), $post['post_smile'] == 0)); | ||||
| 											?> | ||||
| 											<tr> | ||||
| 												<th><?php echo htmlspecialchars($post['post_topic']); ?><br/><small><?php echo date('d M y H:i:s', $post['post_date']); ?></small><br/> | ||||
| 													Topic: <a href="<?php echo getForumThreadLink($post['first_post']); ?>" class="link-black text-sm"><i class="fa fa-share margin-r-5"></i> Link</a><br/> | ||||
| 													Forum: <a href="<?php echo getForumBoardLink($post['section']); ?>" class="link-black text-sm"><i class="fa fa-share margin-r-5"></i> <?php echo $post['forum_Name']; ?></a></th> | ||||
| 												<th><?php echo $post['content']; ?></th> | ||||
| 											</tr> | ||||
| 											<?php | ||||
| 										} | ||||
| 										unset($post); | ||||
| 									} else { | ||||
| 										echo '<tr><td colspan="2">This user has no posts</td></tr>'; | ||||
| 									}; ?> | ||||
| 									</tbody> | ||||
| 								</table> | ||||
| 							</div> | ||||
| 							<div class="tab-pane fade" id="tabs-chars"> | ||||
| 								<div class="row"> | ||||
| 									<?php | ||||
| 									if (isset($account) && $account->isLoaded()) { | ||||
| 										$account_players = $account->getPlayersList(); | ||||
| 										$account_players->orderBy('id'); | ||||
| 										if (isset($account_players)) { ?> | ||||
| 											<table class="table table-striped table-condensed table-responsive d-md-table"> | ||||
| 												<thead> | ||||
| 												<tr> | ||||
| 													<th>#</th> | ||||
| 													<th>Name</th> | ||||
| 													<th>Level</th> | ||||
| 													<th>Vocation</th> | ||||
| 													<th style="width: 40px">Edit</th> | ||||
| 												</tr> | ||||
| 												</thead> | ||||
| 												<tbody> | ||||
| 												<?php foreach ($account_players as $i => $player): | ||||
| 													$player_vocation = $player->getVocation(); | ||||
| 													$player_promotion = $player->getPromotion(); | ||||
| 													if (isset($player_promotion)) { | ||||
| 														if ((int)$player_promotion > 0) | ||||
| 															$player_vocation += ($player_promotion * $config['vocations_amount']); | ||||
| 													} | ||||
|  | ||||
| 													if (isset($config['vocations'][$player_vocation])) { | ||||
| 														$vocation_name = $config['vocations'][$player_vocation]; | ||||
| 													} ?> | ||||
| 													<tr> | ||||
| 														<th><?php echo $i; ?></th> | ||||
| 														<td><?php echo $player->getName(); ?></td> | ||||
| 														<td><?php echo $player->getLevel(); ?></td> | ||||
| 														<td><?php echo $vocation_name; ?></td> | ||||
| 														<td><a href="?p=players&id=<?php echo $player->getId() ?>" class=" btn btn-success btn-sm" title="Edit"><i class="fas fa-pencil-alt"></i></a></td> | ||||
| 													</tr> | ||||
| 												<?php endforeach ?> | ||||
| 												</tbody> | ||||
| 											</table> | ||||
| 											<?php | ||||
| 										} | ||||
| 									} ?> | ||||
| 								</div> | ||||
| 							</div> | ||||
| 						</div> | ||||
| 					</div> | ||||
| 					<div class="card-footer text-center"> | ||||
| 						<input type="hidden" name="save" value="yes"/> | ||||
| 						<button type="submit" class="btn btn-info float-left"><i class="fas fa-update"></i> Update</button> | ||||
| 						<a href="<?php echo ADMIN_URL; ?>?p=accounts&id=<?php echo $account->getId(); ?>" class="btn btn-secondary">Edit Account</a> | ||||
| 						<a href="<?php echo ADMIN_URL; ?>?p=players" class="btn btn-danger float-right"><i class="fas fa-cancel"></i> Cancel</a> | ||||
| 					</div> | ||||
| 				</form> | ||||
| 			</div> | ||||
| 		</div> | ||||
|  | ||||
| 		<script type="text/javascript"> | ||||
| 			$('#lastlogin').datetimepicker({format: "M d Y, H:i:s",}); | ||||
| 			$('#lastlogout').datetimepicker({format: "M d Y, H:i:s",}); | ||||
| 			$('#created').datetimepicker({format: "M d Y, H:i:s",}); | ||||
|  | ||||
| 			$(document).ready(function () { | ||||
| 				const $headSpan = $('#look_head_val'); | ||||
| 				const $headvalue = $('#look_head'); | ||||
| 				$headSpan.html($headvalue.val()); | ||||
| 				$headvalue.on('input', () => { | ||||
| 					$headSpan.html($headvalue.val()); | ||||
| 				}); | ||||
| 				$headvalue.on('change', () => { | ||||
| 					updateOutfit(); | ||||
| 				}); | ||||
|  | ||||
| 				const $bodySpan = $('#look_body_val'); | ||||
| 				const $bodyvalue = $('#look_body'); | ||||
| 				$bodySpan.html($bodyvalue.val()); | ||||
| 				$bodyvalue.on('input', () => { | ||||
| 					$bodySpan.html($bodyvalue.val()); | ||||
| 				}); | ||||
| 				$bodyvalue.on('change', () => { | ||||
| 					updateOutfit(); | ||||
| 				}); | ||||
|  | ||||
| 				const $legsSpan = $('#look_legs_val'); | ||||
| 				const $legsvalue = $('#look_legs'); | ||||
| 				$legsSpan.html($legsvalue.val()); | ||||
| 				$legsvalue.on('input', () => { | ||||
| 					$legsSpan.html($legsvalue.val()); | ||||
| 				}); | ||||
| 				$legsvalue.on('change', () => { | ||||
| 					updateOutfit(); | ||||
| 				}); | ||||
|  | ||||
| 				const $feetSpan = $('#look_feet_val'); | ||||
| 				const $feetvalue = $('#look_feet'); | ||||
| 				$feetSpan.html($feetvalue.val()); | ||||
| 				$feetvalue.on('input', () => { | ||||
| 					$feetSpan.html($feetvalue.val()); | ||||
| 				}); | ||||
| 				$feetvalue.on('change', () => { | ||||
| 					updateOutfit(); | ||||
| 				}); | ||||
|  | ||||
| 				const $lookvalue = $('#look_type'); | ||||
| 				$lookvalue.on('change', () => { | ||||
| 					updateOutfit(); | ||||
| 				}); | ||||
|  | ||||
| 				<?php if($hasLookAddons): ?> | ||||
| 				const $addonvalue = $('#look_addons'); | ||||
| 				$('#look_addons').on('change', () => { | ||||
| 					updateOutfit(); | ||||
| 				}); | ||||
| 				<?php endif; ?> | ||||
| 			}); | ||||
|  | ||||
| 			function updateOutfit() { | ||||
| 				const look_head = $('#look_head').val(); | ||||
| 				const look_body = $('#look_body').val(); | ||||
| 				const look_legs = $('#look_legs').val(); | ||||
| 				const look_feet = $('#look_feet').val(); | ||||
| 				const look_type = $('#look_type').val(); | ||||
|  | ||||
| 				let look_addons = ''; | ||||
| 				<?php if($hasLookAddons): ?> | ||||
| 				look_addons = '&addons=' + $('#look_addons').val(); | ||||
| 				<?php endif; ?> | ||||
| 				$("#player_outfit").attr("src", '<?= $config['outfit_images_url']; ?>?id=' + look_type + look_addons + '&head=' + look_head + '&body=' + look_body + '&legs=' + look_legs + '&feet=' + look_feet); | ||||
| 			} | ||||
| 		</script> | ||||
| 	<?php } ?> | ||||
| 	<div class="col-12 col-sm-12 col-lg-2"> | ||||
| 		<div class="card card-info card-outline"> | ||||
| 			<div class="card-header"> | ||||
| 				<h5 class="m-0">Search Player</h5> | ||||
| 			</div> | ||||
| 			<div class="card-body row"> | ||||
| 				<div class="col-6 col-lg-12"> | ||||
| 					<form action="<?php echo $player_base; ?>" method="post"> | ||||
| 						<label for="name">Player Name:</label> | ||||
| 						<div class="input-group input-group-sm"> | ||||
| 							<input type="text" class="form-control" name="search" value="<?php echo $search_player; ?>" maxlength="32" size="32"> | ||||
| 							<span class="input-group-append"><button type="submit" class="btn btn-info btn-flat">Search</button></span> | ||||
| 						</div> | ||||
| 					</form> | ||||
| 				</div> | ||||
| 				<div class="col-6 col-lg-12"> | ||||
| 					<form action="<?php echo $player_base; ?>" method="post"> | ||||
| 						<label for="name">Player ID:</label> | ||||
| 						<div class="input-group input-group-sm"> | ||||
| 							<input type="text" class="form-control" name="id" value="" maxlength="32" size="32"> | ||||
| 							<span class="input-group-append"><button type="submit" class="btn btn-info btn-flat">Search</button></span> | ||||
| 						</div> | ||||
| 					</form> | ||||
| 				</div> | ||||
| 			</div> | ||||
| 		</div> | ||||
| 	</div> | ||||
| </div> | ||||
|  | ||||
| <script> | ||||
| 	$(document).ready(function () { | ||||
| 		$('.player_datatable').DataTable({ | ||||
| 			"order": [[0, "asc"]] | ||||
| 		}); | ||||
| 	}); | ||||
| </script> | ||||
							
								
								
									
										136
									
								
								admin/pages/plugins.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,136 @@ | ||||
| <?php | ||||
| /** | ||||
|  * Plugins | ||||
|  * | ||||
|  * @package   MyAAC | ||||
|  * @author    Slawkens <slawkens@gmail.com> | ||||
|  * @copyright 2019 MyAAC | ||||
|  * @link      https://my-aac.org | ||||
|  */ | ||||
| defined('MYAAC') or die('Direct access not allowed!'); | ||||
| $title = 'Plugin manager'; | ||||
| $use_datatable = true; | ||||
|  | ||||
| require_once LIBS . 'plugins.php'; | ||||
|  | ||||
| if (!getBoolean(config('admin_plugins_manage_enable'))) { | ||||
| 	warning('Plugin installation and management is disabled in config.<br/>If you wish to enable, go to config.php and change <b>admin_plugins_manage_enable</b> to "yes".'); | ||||
| } | ||||
| else { | ||||
| 	$twig->display('admin.plugins.form.html.twig'); | ||||
|  | ||||
| 	if (isset($_REQUEST['uninstall'])) { | ||||
| 		$uninstall = $_REQUEST['uninstall']; | ||||
|  | ||||
| 		if (Plugins::uninstall($uninstall)) { | ||||
| 			success('Successfully uninstalled plugin ' . $uninstall); | ||||
| 		} else { | ||||
| 			error('Error while uninstalling plugin ' . $uninstall . ': ' . Plugins::getError()); | ||||
| 		} | ||||
| 	} else if (isset($_REQUEST['enable'])) { | ||||
| 		$enable = $_REQUEST['enable']; | ||||
| 		if (Plugins::enable($enable)) { | ||||
| 			success('Successfully enabled plugin ' . $enable); | ||||
| 		} else { | ||||
| 			error('Error while enabling plugin ' . $enable . ': ' . Plugins::getError()); | ||||
| 		} | ||||
| 	} else if (isset($_REQUEST['disable'])) { | ||||
| 		$disable = $_REQUEST['disable']; | ||||
| 		if (Plugins::disable($disable)) { | ||||
| 			success('Successfully disabled plugin ' . $disable); | ||||
| 		} else { | ||||
| 			error('Error while disabling plugin ' . $disable . ': ' . Plugins::getError()); | ||||
| 		} | ||||
| 	} else if (isset($_FILES['plugin']['name'])) { | ||||
| 		$file = $_FILES['plugin']; | ||||
| 		$filename = $file['name']; | ||||
| 		$tmp_name = $file['tmp_name']; | ||||
| 		$type = $file['type']; | ||||
|  | ||||
| 		$name = explode('.', $filename); | ||||
| 		$accepted_types = array('application/zip', 'application/x-zip-compressed', 'multipart/x-zip', 'application/x-compressed', 'application/octet-stream', 'application/zip-compressed'); | ||||
|  | ||||
| 		if (isset($file['error'])) { | ||||
| 			$error = 'Error uploading file'; | ||||
| 			switch ($file['error']) { | ||||
| 				case UPLOAD_ERR_OK: | ||||
| 					$error = false; | ||||
| 					break; | ||||
| 				case UPLOAD_ERR_INI_SIZE: | ||||
| 				case UPLOAD_ERR_FORM_SIZE: | ||||
| 					$error .= ' - file too large (limit of ' . ini_get('upload_max_filesize') . ' bytes). You can enlarge the limits by changing "upload_max_filesize" in php.ini'; | ||||
| 					break; | ||||
| 				case UPLOAD_ERR_PARTIAL: | ||||
| 					$error .= ' - file upload was not completed.'; | ||||
| 					break; | ||||
| 				case UPLOAD_ERR_NO_FILE: | ||||
| 					$error .= ' - zero-length file uploaded.'; | ||||
| 					break; | ||||
| 				default: | ||||
| 					$error .= ' - internal error #' . $file['error']; | ||||
| 					break; | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		if (isset($error) && $error != false) { | ||||
| 			error($error); | ||||
| 		} else { | ||||
| 			if (is_uploaded_file($file['tmp_name'])) { | ||||
| 				$filetype = strtolower(pathinfo($filename, PATHINFO_EXTENSION)); | ||||
| 				if ($filetype == 'zip') // check if it is zipped/compressed file | ||||
| 				{ | ||||
| 					$tmp_filename = pathinfo($filename, PATHINFO_FILENAME); | ||||
| 					$targetzip = BASE . 'plugins/' . $tmp_filename . '.zip'; | ||||
|  | ||||
| 					if (move_uploaded_file($tmp_name, $targetzip)) { // move uploaded file | ||||
| 						if (Plugins::install($targetzip)) { | ||||
| 							foreach (Plugins::getWarnings() as $warning) { | ||||
| 								warning($warning); | ||||
| 							} | ||||
|  | ||||
| 							$info = Plugins::getPluginJson(); | ||||
| 							success((isset($info['name']) ? '<strong>' . $info['name'] . '</strong> p' : 'P') . 'lugin has been successfully installed.'); | ||||
| 						} else { | ||||
| 							$error = Plugins::getError(); | ||||
| 							error(!empty($error) ? $error : 'Unexpected error happened while installing plugin. Please try again later.'); | ||||
| 						} | ||||
|  | ||||
| 						unlink($targetzip); // delete the Zipped file | ||||
| 					} else | ||||
| 						error('There was a problem with the upload. Please try again.'); | ||||
| 				} else { | ||||
| 					error('The file you are trying to upload is not a .zip file. Please try again.'); | ||||
| 				} | ||||
| 			} else { | ||||
| 				error('Error uploading file - unknown error.'); | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| $plugins = array(); | ||||
| foreach (get_plugins(true) as $plugin) { | ||||
| 	$string = file_get_contents(BASE . 'plugins/' . $plugin . '.json'); | ||||
| 	$plugin_info = json_decode($string, true); | ||||
|  | ||||
| 	if (!$plugin_info) { | ||||
| 		warning('Cannot load plugin info ' . $plugin . '.json'); | ||||
| 	} else { | ||||
| 		$disabled = (strpos($plugin, 'disabled.') !== false); | ||||
| 		$pluginOriginal = ($disabled ? str_replace('disabled.', '', $plugin) : $plugin); | ||||
| 		$plugins[] = array( | ||||
| 			'name' => $plugin_info['name'] ?? '', | ||||
| 			'description' => $plugin_info['description'] ?? '', | ||||
| 			'version' => $plugin_info['version'] ?? '', | ||||
| 			'author' => $plugin_info['author'] ?? '', | ||||
| 			'contact' => $plugin_info['contact'] ?? '', | ||||
| 			'file' => $pluginOriginal, | ||||
| 			'enabled' => !$disabled, | ||||
| 			'uninstall' => isset($plugin_info['uninstall']) | ||||
| 		); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| $twig->display('admin.plugins.html.twig', array( | ||||
| 	'plugins' => $plugins | ||||
| )); | ||||
							
								
								
									
										61
									
								
								admin/pages/reports.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,61 @@ | ||||
| <?php | ||||
| /** | ||||
|  * Reports | ||||
|  * | ||||
|  * @package   MyAAC | ||||
|  * @author    Lee | ||||
|  * @copyright 2020 MyAAC | ||||
|  * @link      https://my-aac.org | ||||
|  */ | ||||
| defined('MYAAC') or die('Direct access not allowed!'); | ||||
| $title = 'Report Viewer'; | ||||
| $use_datatable = true; | ||||
|  | ||||
| $files = array(); | ||||
| $server_path_reports = $config['data_path'] . 'reports/'; | ||||
|  | ||||
| if (file_exists($server_path_reports)) { | ||||
| 	foreach (scandir($server_path_reports, SCANDIR_SORT_ASCENDING) as $f) { | ||||
| 		if ($f[0] === '.') { | ||||
| 			continue; | ||||
| 		} | ||||
|  | ||||
| 		if (is_dir($server_path_reports . $f)) { | ||||
| 			foreach (scandir($server_path_reports . $f, SCANDIR_SORT_ASCENDING) as $f2) { | ||||
| 				if ($f2[0] === '.') { | ||||
| 					continue; | ||||
| 				} | ||||
|  | ||||
| 				$files[] = array($f . '/' . $f2, $server_path_reports); | ||||
| 			} | ||||
|  | ||||
| 			continue; | ||||
| 		} | ||||
|  | ||||
| 		$files[] = array($f, $server_path_reports); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| foreach ($files as &$f) { | ||||
| 	$f['mtime'] = filemtime($f[1] . $f[0]); | ||||
| 	$f['name'] = $f[0]; | ||||
| } | ||||
|  | ||||
| unset($f); | ||||
|  | ||||
| $file = isset($_GET['file']) ? $_GET['file'] : NULL; | ||||
| if (!empty($file)) { | ||||
| 	if (!preg_match('/[^A-z0-9\' _\/\-\.]/', $file)) { | ||||
| 		if (file_exists($server_path_reports . $file)) { | ||||
| 			$file_content = nl2br(file_get_contents($server_path_reports . $file)); | ||||
|  | ||||
| 			$twig->display('admin.logs.view.html.twig', array('file' => $file, 'content' => $file_content)); | ||||
| 		} else { | ||||
| 			echo 'Specified file does not exist.'; | ||||
| 		} | ||||
| 	} else { | ||||
| 		echo 'Invalid file name specified.'; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| $twig->display('admin.reports.html.twig', array('files' => $files)); | ||||
							
								
								
									
										39
									
								
								admin/pages/statistics.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,39 @@ | ||||
| <?php | ||||
| /** | ||||
|  * Statistics | ||||
|  * | ||||
|  * @package   MyAAC | ||||
|  * @author    Slawkens <slawkens@gmail.com> | ||||
|  * @copyright 2019 MyAAC | ||||
|  * @link      https://my-aac.org | ||||
|  */ | ||||
| defined('MYAAC') or die('Direct access not allowed!'); | ||||
| $title = 'Statistics'; | ||||
|  | ||||
| $query = $db->query('SELECT count(*) as `how_much` FROM `accounts`;'); | ||||
| $query = $query->fetch(); | ||||
| $total_accounts = $query['how_much']; | ||||
|  | ||||
| $query = $db->query('SELECT count(*) as `how_much` FROM `players`;'); | ||||
| $query = $query->fetch(); | ||||
| $total_players = $query['how_much']; | ||||
|  | ||||
| $query = $db->query('SELECT count(*) as `how_much` FROM `guilds`;'); | ||||
| $query = $query->fetch(); | ||||
| $total_guilds = $query['how_much']; | ||||
|  | ||||
| $query = $db->query('SELECT count(*) as `how_much` FROM `houses`;'); | ||||
| $query = $query->fetch(); | ||||
| $total_houses = $query['how_much']; | ||||
|  | ||||
| $points = $db->query('SELECT `premium_points`, `' . (USE_ACCOUNT_NAME ? 'name' : 'id') . '` as `name` FROM `accounts` ORDER BY `premium_points` DESC LIMIT 10;'); | ||||
|  | ||||
| $twig->display('admin.statistics.html.twig', array( | ||||
| 	'total_accounts' => $total_accounts, | ||||
| 	'total_players' => $total_players, | ||||
| 	'total_guilds' => $total_guilds, | ||||
| 	'total_houses' => $total_houses, | ||||
| 	'account_type' => (USE_ACCOUNT_NAME ? 'name' : 'number'), | ||||
| 	'points' => $points | ||||
| )); | ||||
| ?> | ||||
							
								
								
									
										33
									
								
								admin/pages/tools.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,33 @@ | ||||
| <?php | ||||
| /** | ||||
|  * Tools | ||||
|  * | ||||
|  * @package   MyAAC | ||||
|  * @author    Slawkens <slawkens@gmail.com> | ||||
|  * @copyright 2019 MyAAC | ||||
|  * @link      https://my-aac.org | ||||
|  */ | ||||
| defined('MYAAC') or die('Direct access not allowed!'); | ||||
| $title = 'Tools'; | ||||
|  | ||||
| if (!isset($_GET['tool'])) { | ||||
| 	echo 'Tool not set.'; | ||||
| 	return; | ||||
| } | ||||
|  | ||||
| $tool = $_GET['tool']; | ||||
| if (preg_match("/[^A-z0-9_\-]/", $tool)) { | ||||
| 	echo 'Invalid tool.'; | ||||
| 	return; | ||||
| } | ||||
|  | ||||
| $file = ADMIN . 'tools/' . $tool . '.php'; | ||||
|  | ||||
| if (@file_exists($file)) { | ||||
| 	require $file; | ||||
| 	return; | ||||
| } | ||||
|  | ||||
| echo 'Tool <strong>' . $tool . '</strong> not found.'; | ||||
|  | ||||
| ?> | ||||
							
								
								
									
										50
									
								
								admin/pages/version.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,50 @@ | ||||
| <?php | ||||
| /** | ||||
|  * Version check | ||||
|  * | ||||
|  * @package   MyAAC | ||||
|  * @author    Slawkens <slawkens@gmail.com> | ||||
|  * @copyright 2019 MyAAC | ||||
|  * @link      https://my-aac.org | ||||
|  */ | ||||
| defined('MYAAC') or die('Direct access not allowed!'); | ||||
| $title = 'Version check'; | ||||
|  | ||||
| // fetch version | ||||
| //$file = @fopen('https://my-aac.org/VERSION', 'r') or die('Error while fetching version.'); | ||||
| //$myaac_version = fgets($file); | ||||
| $myaac_version = @file_get_contents('https://my-aac.org/VERSION'); | ||||
| if (!$myaac_version) { | ||||
| 	warning('Error while fetching version info from https://my-aac.org<br/> | ||||
| 	Please try again later.'); | ||||
| 	return; | ||||
| } | ||||
|  | ||||
| // compare them | ||||
| $version_compare = version_compare($myaac_version, MYAAC_VERSION); | ||||
| if ($version_compare == 0) { | ||||
| 	success('MyAAC latest version is ' . $myaac_version . '. You\'re using the latest version. | ||||
| 	<br/>View CHANGELOG ' . generateLink(ADMIN_URL . '?p=clmd', 'here')); | ||||
| } else if ($version_compare < 0) { | ||||
| 	success('Woah, seems you\'re using newer version as latest released one! MyAAC latest released version is ' . $myaac_version . ', and you\'re using version ' . MYAAC_VERSION . '. | ||||
| 	<br/>View CHANGELOG ' . generateLink(ADMIN_URL . '?p=clmd', 'here')); | ||||
| } else { | ||||
| 	warning('You\'re using outdated version.<br/> | ||||
| 		Your version: <b>' . MYAAC_VERSION . '</b><br/> | ||||
| 		Latest version: <b>' . $myaac_version . '</b><br/> | ||||
| 		Download available at: <a href="https://my-aac.org" target="_blank">www.my-aac.org</a>'); | ||||
| } | ||||
|  | ||||
| /* | ||||
| function version_revert($version) | ||||
| { | ||||
| 	$major = floor($version / 10000); | ||||
| 	$version -= $major * 10000; | ||||
|  | ||||
| 	$minor = floor($version / 100); | ||||
| 	$version -= $minor * 100; | ||||
|  | ||||
| 	$release = $version; | ||||
| 	return $major . '.' . $minor . '.' . $release; | ||||
| }*/ | ||||
| ?> | ||||
							
								
								
									
										67
									
								
								admin/pages/visitors.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,67 @@ | ||||
| <?php | ||||
| /** | ||||
|  * Visitors viewer | ||||
|  * | ||||
|  * @package   MyAAC | ||||
|  * @author    Slawkens <slawkens@gmail.com> | ||||
|  * @copyright 2019 MyAAC | ||||
|  * @link      https://my-aac.org | ||||
|  */ | ||||
| defined('MYAAC') or die('Direct access not allowed!'); | ||||
|  | ||||
| use DeviceDetector\DeviceDetector; | ||||
| use DeviceDetector\Parser\Client\Browser; | ||||
| use DeviceDetector\Parser\OperatingSystem; | ||||
|  | ||||
| $title = 'Visitors'; | ||||
| $use_datatable = true; | ||||
|  | ||||
| if (!$config['visitors_counter']): ?> | ||||
| 	Visitors counter is disabled.<br/> | ||||
| 	You can enable it by editing this configurable in <b>config.local.php</b> file:<br/> | ||||
| 	<p style="margin-left: 3em;"><b>$config['visitors_counter'] = true;</b></p> | ||||
| 	<?php | ||||
| 	return; | ||||
| endif; | ||||
|  | ||||
| require SYSTEM . 'libs/visitors.php'; | ||||
| $visitors = new Visitors($config['visitors_counter_ttl']); | ||||
|  | ||||
| function compare($a, $b) | ||||
| { | ||||
| 	return $a['lastvisit'] > $b['lastvisit'] ? -1 : 1; | ||||
| } | ||||
|  | ||||
| $tmp = $visitors->getVisitors(); | ||||
| usort($tmp, 'compare'); | ||||
|  | ||||
| foreach ($tmp as &$visitor) { | ||||
| 	$userAgent = $visitor['user_agent'] ?? ''; | ||||
| 	if (!strlen($userAgent) || $userAgent == 'unknown') { | ||||
| 		$browser = 'Unknown'; | ||||
| 	} | ||||
| 	else { | ||||
| 		$dd = new DeviceDetector($userAgent); | ||||
| 		$dd->parse(); | ||||
|  | ||||
| 		if ($dd->isBot()) { | ||||
| 			$bot = $dd->getBot(); | ||||
| 			$message = '(Bot) %s, <a href="%s" target="_blank">%s</a>'; | ||||
| 			$browser = sprintf($message, $bot['category'], $bot['url'], $bot['name']); | ||||
| 		} | ||||
| 		else { | ||||
| 			$osFamily = OperatingSystem::getOsFamily($dd->getOs('name')); | ||||
| 			$browserFamily = Browser::getBrowserFamily($dd->getClient('name')); | ||||
|  | ||||
| 			$browser = $osFamily . ', ' . $browserFamily; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	$visitor['browser'] = $browser; | ||||
| } | ||||
|  | ||||
| $twig->display('admin.visitors.html.twig', array( | ||||
| 	'config_visitors_counter_ttl' => $config['visitors_counter_ttl'], | ||||
| 	'visitors' => $tmp | ||||
| )); | ||||
| ?> | ||||
							
								
								
									
										66
									
								
								admin/template/menus.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,66 @@ | ||||
| <?php | ||||
|  | ||||
| $menus = [ | ||||
| 	['name' => 'Dashboard', 'icon' => 'tachometer-alt', 'order' => 10, 'link' => 'dashboard'], | ||||
| 	['name' => 'News', 'icon' => 'newspaper', 'order' => 20, 'link' => | ||||
| 		[ | ||||
| 			['name' => 'View', 'link' => 'news', 'icon' => 'list', 'order' => 10], | ||||
| 			['name' => 'Add news', 'link' => 'news&action=new&type=1', 'icon' => 'plus', 'order' => 20], | ||||
| 			['name' => 'Add ticker', 'link' => 'news&action=new&type=2', 'icon' => 'plus', 'order' => 30], | ||||
| 			['name' => 'Add article', 'link' => 'news&action=new&type=3', 'icon' => 'plus', 'order' => 40], | ||||
| 		], | ||||
| 	], | ||||
| 	['name' => 'Changelogs', 'icon' => 'newspaper', 'order' => 30, 'link' => | ||||
| 		[ | ||||
| 			['name' => 'View', 'link' => 'changelog', 'icon' => 'list', 'order' => 10], | ||||
| 			['name' => 'Add', 'link' => 'changelog&action=new', 'icon' => 'plus', 'order' => 20], | ||||
| 		], | ||||
| 	], | ||||
| 	['name' => 'Mailer', 'icon' => 'envelope', 'order' => 40, 'link' => 'mailer', 'disabled' => !config('mail_enabled')], | ||||
| 	['name' => 'Pages', 'icon' => 'book', 'order' => 50, 'link' => | ||||
| 		[ | ||||
| 			['name' => 'View', 'link' => 'pages', 'icon' => 'list', 'order' => 10], | ||||
| 			['name' => 'Add', 'link' => 'pages&action=new', 'icon' => 'plus', 'order' => 20], | ||||
| 		], | ||||
| 	], | ||||
| 	['name' => 'Menus', 'icon' => 'list', 'order' => 60, 'link' => 'menus'], | ||||
| 	['name' => 'Plugins', 'icon' => 'plug', 'order' => 70, 'link' => 'plugins'], | ||||
| 	['name' => 'Server Data', 'icon' => 'gavel', 'order' => 80, 'link' => 'data'], | ||||
| 	['name' => 'Editor', 'icon' => 'edit', 'order' => 90, 'link' => | ||||
| 		[ | ||||
| 			['name' => 'Accounts', 'link' => 'accounts', 'icon' => 'users', 'order' => 10], | ||||
| 			['name' => 'Players', 'link' => 'players', 'icon' => 'user-astronaut', 'order' => 20], | ||||
| 		], | ||||
| 	], | ||||
| 	['name' => 'Tools', 'icon' => 'tools', 'order' => 100, 'link' => | ||||
| 		[ | ||||
| 			['name' => 'Mass Account Actions', 'link' => 'mass_account', 'icon' => 'globe', 'order' => 10], | ||||
| 			['name' => 'Mass Teleport Actions', 'link' => 'mass_teleport', 'icon' => 'globe', 'order' => 20], | ||||
| 			['name' => 'Notepad', 'link' => 'notepad', 'icon' => 'marker', 'order' => 30], | ||||
| 			['name' => 'phpinfo', 'link' => 'phpinfo', 'icon' => 'server', 'order' => 40], | ||||
| 		], | ||||
| 	], | ||||
| 	['name' => 'Logs', 'icon' => 'bug', 'order' => 110, 'link' => | ||||
| 		[ | ||||
| 			['name' => 'Logs', 'link' => 'logs', 'icon' => 'book', 'order' => 10], | ||||
| 			['name' => 'Reports', 'link' => 'reports', 'icon' => 'book', 'order' => 20], | ||||
| 			['name' => 'Visitors', 'link' => 'visitors', 'icon' => 'user', 'order' => 30], | ||||
| 		], | ||||
| 	], | ||||
| ]; | ||||
|  | ||||
| $hooks->trigger(HOOK_ADMIN_MENU); | ||||
|  | ||||
| usort($menus, function ($a, $b) { | ||||
| 	return $a['order'] - $b['order']; | ||||
| }); | ||||
|  | ||||
| foreach ($menus as $i => $menu) { | ||||
| 	if (isset($menu['link']) && is_array($menu['link'])) { | ||||
| 		usort($menus[$i]['link'], function ($a, $b) { | ||||
| 			return $a['order'] - $b['order']; | ||||
| 		}); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| return $menus; | ||||
| @@ -1,147 +1,10 @@ | ||||
| *{ | ||||
| 	margin:0; | ||||
| 	padding:0; | ||||
| } | ||||
| body { | ||||
| 	font-family: Helvetica; | ||||
| 	color: #313334; | ||||
| 	background: /*#f9f9f9 #EEEEEE*/#F7F6F1; | ||||
| .menu-text-li {color: #4b646f; background: #1a2226;} | ||||
| .menu-text { | ||||
| 	display: block; | ||||
| 	padding: .5rem 1rem; | ||||
| 	white-space: nowrap; | ||||
| } | ||||
|  | ||||
| img {border: none;} | ||||
|  | ||||
| a:link		{color: #000; text-decoration: none;} | ||||
| a:visited	{color: #000; text-decoration: none;} | ||||
| a:focus		{color: #000; text-decoration: none;} | ||||
| a:active	{color: #000; text-decoration: underline;} | ||||
| a:hover		{color: #000; text-decoration: underline;} | ||||
| a.current	{font-weight: bold;} | ||||
|  | ||||
| h5.blue		{color: #6b7b95;} | ||||
| h5.red		{color: #c17878;} | ||||
| h5.green	{color: #78ba91;} | ||||
| h5.purple	{color: #a87aad;} | ||||
|  | ||||
| h1, h2, h3, h4, h5, h6 {color: #313334; font-weight: bold;} | ||||
| .separator {color:#BCE} | ||||
| .margin-left{ | ||||
| 	margin-left:5px; | ||||
| } | ||||
|  | ||||
| .button { background:#eee url(images/button.gif) repeat-x 0 0; border:solid 1px #b1a874; color:#7f7f7f; font-size:11px; padding:2px 6px 2px 6px; cursor:pointer; line-height:14px !important; } | ||||
| .button:hover { color:#333; border-color:#857b42; } | ||||
|  | ||||
| .field, .button { -moz-border-radius:4px; -webkit-border-radius:4px; } | ||||
| .small-field, .button, .pagging a { -moz-border-radius:3px; -webkit-border-radius:3px; } | ||||
|  | ||||
| .table th { | ||||
|     background-color: #4CAF50; | ||||
|     color: white; | ||||
| 	text-align: left; | ||||
| } | ||||
|  | ||||
| .table, .table td, .table th{ | ||||
| 	border: 1px solid #ddd; | ||||
| } | ||||
|  | ||||
| .table th a:link {color: white; text-decoration: none;} | ||||
| .table th a:link		{color: white; text-decoration: none;} | ||||
| .table th a:visited	{color: white; text-decoration: none;} | ||||
| .table th a:focus		{color: white; text-decoration: none;} | ||||
| .table th a:active	{color: white; text-decoration: underline;} | ||||
| .table th a:hover		{color: white; text-decoration: underline;} | ||||
|  | ||||
| .table tr:nth-child(odd) {background-color: #d1d1d1} | ||||
|  | ||||
| a.ico { color:#9d9c9a; font-size:10px; text-decoration: none; padding:0 0 0 14px; background-repeat:no-repeat; background-position:0 0; } | ||||
| a.ico:hover { color:#333;} | ||||
|  | ||||
| #container{ | ||||
| 	width:960px; | ||||
| 	margin-left:auto; | ||||
| 	margin-right:auto; | ||||
| } | ||||
| #header { | ||||
| 	/*width: 960px;*/ | ||||
| 	padding-left: auto; | ||||
| 	padding-right: auto; | ||||
| 	border-bottom: 1px dotted black; | ||||
| 	margin-top: 40px; | ||||
| } | ||||
| #header h1 { | ||||
| 	margin: 0; | ||||
| 	padding-top: 20px; | ||||
| 	text-align: center; | ||||
| } | ||||
| #sidebar{ | ||||
| 	background: #FFF; | ||||
| 	width: 170px; | ||||
| 	float: left; | ||||
| 	margin: 10px 0 10px 0; | ||||
| 	padding: 10px; | ||||
| 	border: 1px solid #CCC; | ||||
| } | ||||
| #content { | ||||
| 	width: 740px; | ||||
| 	float: right; | ||||
| 	margin: 20px 0 10px 0; | ||||
| 	padding: 10px; | ||||
| } | ||||
| #footer { | ||||
| 	margin-top: 20px; | ||||
| 	border-top: 1px dotted black; | ||||
| 	text-align: center; | ||||
| 	clear: both; | ||||
| } | ||||
| /********************* | ||||
| 	Sidebar | ||||
| *********************/ | ||||
| #sidebar ul{ | ||||
| 	list-style:none; | ||||
| 	line-height:22px; | ||||
| } | ||||
| #sidebar ul li a,#sidebar ul li a:visited{ | ||||
| 	padding-left:19px; | ||||
| 	text-decoration:none; | ||||
| 	margin:0 3px; | ||||
| 	display:block; | ||||
| } | ||||
| #sidebar ul li a:hover{ | ||||
| 	text-decoration:underline; | ||||
| } | ||||
| #sidebar ul li ul{ | ||||
| 	margin-left:10px; | ||||
| } | ||||
| #sidebar h3{ | ||||
| 	padding:2px; | ||||
| 	font-size:14px; | ||||
| } | ||||
| /********************* | ||||
| 	Status & version boxes | ||||
| *********************/ | ||||
| #status { | ||||
| 	position: absolute; top: 10px; left: 10px; | ||||
| 	margin: 0px; | ||||
| 	float: right; | ||||
| 	font-size: 12px; | ||||
| } | ||||
| #status .success { | ||||
|   margin: 0px: | ||||
| } | ||||
| #version { | ||||
| 	position: absolute; top: 10px; right: 10px; | ||||
| 	float: right; | ||||
| 	text-align: right; | ||||
| 	font-size: 12px; | ||||
| } | ||||
| /********************* | ||||
| 	Infobox | ||||
| *********************/ | ||||
| #infobox{ | ||||
| 	border:1px solid #e9e8e3; | ||||
| } | ||||
| #infobox h3{ | ||||
| 	background:#f7f6f1; | ||||
| 	border-bottom:1px solid #e9e8e3; | ||||
| 	color:#654322; | ||||
| .sidebar-mini.sidebar-collapse .menu-text { | ||||
| 	display: none; | ||||
| } | ||||
| @@ -1,95 +1,203 @@ | ||||
| <?php defined('MYAAC') or die('Direct access not allowed!'); ?> | ||||
| <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> | ||||
| <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> | ||||
| <!doctype html> | ||||
| <html lang="en"> | ||||
| <head> | ||||
| 	<?php $hooks->trigger(HOOK_ADMIN_HEAD_START); ?> | ||||
| 	<?php echo template_header(true); ?> | ||||
| 	<title><?php echo $title . $config['title_separator'] . $config['lua']['serverName']; ?> - Powered by MyAAC</title> | ||||
| 	<link rel="stylesheet" type="text/css" href="<?php echo $template_path; ?>style.css" /> | ||||
| 	<title><?php echo (isset($title) ? $title . ' - ' : '') . $config['lua']['serverName'];?></title> | ||||
| 	<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> | ||||
| 	<link rel="stylesheet" href="<?php echo BASE_URL; ?>tools/css/adminlte.min.css"> | ||||
| 	<link rel="stylesheet" href="<?php echo BASE_URL; ?>tools/css/font-awesome.min.css"> | ||||
| 	<?php if (isset($use_datatable)) { ?> | ||||
| 	<link rel="stylesheet" href="<?php echo BASE_URL; ?>tools/css/datatables.bs.min.css"> | ||||
| 	<?php } ?> | ||||
| 	<link rel="stylesheet" type="text/css" href="<?php echo $template_path; ?>style.css"/> | ||||
| 	<!--[if lt IE 9]> | ||||
| 	<script src="<?php echo BASE_URL; ?>tools/js/html5shiv.min.js"></script> | ||||
| 	<script src="<?php echo BASE_URL; ?>tools/js/respond.min.js"></script> | ||||
| 	<![endif]--> | ||||
| 	<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Source+Sans+Pro:300,400,600,700,300italic,400italic,600italic"> | ||||
| 	<?php $hooks->trigger(HOOK_ADMIN_HEAD_END); ?> | ||||
| </head> | ||||
| <body> | ||||
| <?php if($page != 'tools'): ?> | ||||
| 	<div id="container"> | ||||
| 		<div id="header"> | ||||
| 			<?php if($logged && admin()): ?> | ||||
| 			<div id="status"> | ||||
| 				<?php if($status['online']): ?> | ||||
| 				<p class="success" style="width: 120px; text-align: center;">Status: Online<br/> | ||||
| 					<?php echo $status['uptimeReadable'] . ', ' . $status['players'] . '/' . $status['playersMax']; ?><br/> | ||||
| 					<?php echo $config['lua']['ip'] . ' : ' . $config['lua']['loginPort']; ?> | ||||
| 				</p> | ||||
| 				<?php else: ?> | ||||
| 				<p class="error" style="width: 120px; text-align: center;">Status: Offline</p> | ||||
| 				<?php endif; ?> | ||||
| 			</div> | ||||
| 			<div id="version">Version: <?php echo MYAAC_VERSION; ?> (<a id="update" href="?p=version">Check for updates</a>)<br/> | ||||
| 				Logged in as: <b><?php echo (USE_ACCOUNT_NAME ? $account_logged->getName() : $account_logged->getId()); ?></b><br/> | ||||
| 				<a href="<?php echo BASE_URL; ?>" target="_blank">Preview</a> <span class="separator">|</span> <a href="?action=logout">Log out<img src="<?php echo BASE_URL; ?>images/icons/logout.png" alt="" title="Log out" /></a> | ||||
| 			</div> | ||||
| 			<?php endif; ?> | ||||
| 			<h1><?php echo $config['lua']['serverName'] . ' - ' . $title; ?> - Admin Panel</h1> | ||||
| 		</div> | ||||
| 		<div id="wrapper"> | ||||
| 			<?php | ||||
| 			if($logged && admin()) { | ||||
| 			?> | ||||
| 			<div id="sidebar"> | ||||
| 				<ul> | ||||
| 				<?php | ||||
| 					$menus = array( | ||||
| 						'Dashboard' => 'dashboard', | ||||
| 						'Mailer' => 'mailer', | ||||
| 						'Pages' => 'pages', | ||||
| 						'Plugins' => 'plugins', | ||||
| 						'Statistics' => 'statistics', | ||||
| 						'Visitors' => 'visitors', | ||||
| 						'Players' => 'players', | ||||
| 						'Tools' => array( | ||||
| 							'phpinfo' => 'phpinfo' | ||||
| 						), | ||||
| 						'Notepad' => 'notepad', | ||||
| 						'Logs' => 'logs' | ||||
| 					); | ||||
| <body class="sidebar-mini "> | ||||
| <?php $hooks->trigger(HOOK_ADMIN_BODY_START); ?> | ||||
| <?php if ($logged && admin()) { ?> | ||||
| 	<div class="wrapper"> | ||||
| 		<nav class="main-header navbar navbar-expand navbar-white navbar-light"> | ||||
| 			<ul class="navbar-nav"> | ||||
| 				<li class="nav-item"> | ||||
| 					<a class="nav-link" data-widget="pushmenu" href="#"><i class="fas fa-bars"></i></a> | ||||
| 				</li> | ||||
| 				<li class="nav-item d-none d-sm-inline-block"> | ||||
| 					<a href="<?php echo ADMIN_URL; ?>" class="nav-link">Home</a> | ||||
| 				</li> | ||||
| 			</ul> | ||||
| 			<ul class="navbar-nav ml-auto"> | ||||
| 				<li class="nav-item"> | ||||
| 					<a class="nav-link" data-widget="control-sidebar" data-slide="true" href="#"><i class="fas fa-th-large"></i></a> | ||||
| 				</li> | ||||
| 			</ul> | ||||
| 		</nav> | ||||
| 		<aside class="main-sidebar sidebar-dark-info elevation-4"> | ||||
| 			<a href="<?php echo ADMIN_URL; ?>" class="brand-link navbar-info"> | ||||
| 				<img src="<?php echo ADMIN_URL; ?>images/logo.png" class="brand-image img-circle elevation-3" style="opacity: .8"> | ||||
| 				<span class="brand-text"><b>My</b>AAC</span> | ||||
| 			</a> | ||||
| 			<div class="sidebar"> | ||||
| 				<nav class="mt-1"> | ||||
| 					<ul class="nav nav-pills nav-sidebar flex-column nav-legacy nav-child-indent" data-widget="treeview" data-accordion="false"> | ||||
| 						<li class="menu-text-li"> | ||||
| 							<span class="menu-text"> | ||||
| 								<a class="text-info" href="<?php echo BASE_URL; ?>" target="_blank"> | ||||
| 									<?php echo $config['lua']['serverName'] ?> | ||||
| 								</a> | ||||
| 							</span> | ||||
| 						</li> | ||||
| 						<?php | ||||
| 						// name = Display name of link | ||||
| 						// icon = fontawesome icon name without "fas fa-" | ||||
| 						// link = Page link or use as array for sub items | ||||
| 						$menus = require __DIR__ . '/menus.php'; | ||||
|  | ||||
| 					$i = 0; | ||||
| 					foreach($menus as $_name => $_page) { | ||||
| 						//echo '<a ' . ($page == $_page ? ' class="current"' : '') . 'href="?p=' . $_page . '">' . $_name . '</a>'; | ||||
| 						echo '<li><h3>'; | ||||
| 						$has_child = is_array($_page); | ||||
| 						if(!$has_child) { | ||||
| 							echo '<a href="?p=' . $_page . '">'; | ||||
| 							if($page == $_page) echo '<u>'; | ||||
| 								echo $_name; | ||||
| 							if($page == $_page) echo '</u>'; | ||||
| 							echo '</a>'; | ||||
| 						} | ||||
| 						else | ||||
| 							echo $_name; | ||||
| 						foreach ($menus as $category => $menu) { | ||||
| 							if (isset($menu['disabled']) && $menu['disabled']) { | ||||
| 								continue; | ||||
| 							} | ||||
|  | ||||
| 						echo '</h3>'; | ||||
| 						if($has_child) { | ||||
| 							echo '<ul>'; | ||||
| 							foreach($_page as $__name => $__page) | ||||
| 								echo '<li><a href="?p=' . $__page . '">'; | ||||
| 								if($page == $__page) echo '<u>'; | ||||
| 									echo $__name; | ||||
| 								if($page == $__page) echo '</u>'; | ||||
| 								echo '</a></li>'; | ||||
| 							echo '</ul>'; | ||||
| 							$has_child = is_array($menu['link']); | ||||
| 							if (!$has_child) { ?> | ||||
| 								<li class="nav-item"> | ||||
| 									<a class="nav-link<?php echo(strpos($menu['link'], $page) !== false ? ' active' : '') ?>" href="?p=<?php echo $menu['link'] ?>"> | ||||
| 										<i class="nav-icon fas fa-<?php echo(isset($menu['icon']) ? $menu['icon'] : 'link') ?>"></i> | ||||
| 										<p><?php echo $menu['name'] ?></p> | ||||
| 									</a> | ||||
| 								</li> | ||||
| 								<?php | ||||
| 							} else if ($has_child) { | ||||
| 								$used_menu = null; | ||||
| 								$nav_construct = ''; | ||||
| 								foreach ($menu['link'] as $category => $sub_menu) { | ||||
| 									$nav_construct .= '<li class="nav-item"><a href="?p=' . $sub_menu['link'] . '" class="nav-link'; | ||||
| 									if ($page == $sub_menu['link']) { | ||||
| 										$nav_construct .= ' active'; | ||||
| 										$used_menu = true; | ||||
| 									} | ||||
| 									$nav_construct .= '"><i class="fas fa-' . ($sub_menu['icon'] ?? 'circle') . ' nav-icon"></i><p>' . $sub_menu['name'] . '</p></a></li>'; | ||||
| 								} | ||||
| 								?> | ||||
| 								<li class="nav-item has-treeview<?php echo($used_menu ? ' menu-open' : '') ?>"> | ||||
| 									<a href="#" class="nav-link<?php echo($used_menu ? ' active' : '') ?>"> | ||||
| 										<i class="nav-icon fas fa-<?php echo($menu['icon'] ?? 'link') ?>"></i> | ||||
| 										<p><?php echo $menu['name'] ?></p><i class="right fas fa-angle-left"></i> | ||||
| 									</a> | ||||
| 									<ul class="nav nav-treeview"> | ||||
| 										<?php echo $nav_construct; ?> | ||||
| 									</ul> | ||||
| 								</li> | ||||
| 								<?php | ||||
| 							} | ||||
| 						} | ||||
| 						echo '</li>'; | ||||
| 					} | ||||
| 				?> | ||||
| 				</ul> | ||||
|  | ||||
| 						$query = $db->query('SELECT `name`, `page`, `flags` FROM `' . TABLE_PREFIX . 'admin_menu` ORDER BY `ordering`'); | ||||
| 						$menu_db = $query->fetchAll(); | ||||
| 						foreach ($menu_db as $item) { | ||||
| 							if ($item['flags'] == 0 || hasFlag($item['flags'])) { ?> | ||||
| 								<li class="nav-item"> | ||||
| 									<a class="nav-link<?php echo($page == $item['page'] ? ' active' : '') ?>" href="?p=<?php echo $item['page'] ?>"> | ||||
| 										<i class="nav-icon fas fa-link"></i> | ||||
| 										<p><?php echo $item['name'] ?></p> | ||||
| 									</a> | ||||
| 								</li> | ||||
| 								<?php | ||||
| 							} | ||||
| 						} | ||||
| 						?> | ||||
| 					</ul> | ||||
| 				</nav> | ||||
| 			</div> | ||||
| 		</aside> | ||||
|  | ||||
| 		<div class="content-wrapper" style="min-height: 823px;"> | ||||
| 			<div class="content-header"> | ||||
| 				<div class="container-fluid"> | ||||
| 					<div class="row mb-2"> | ||||
| 						<div class="col-sm-6"> | ||||
| 							<h3 class="m-0 text-dark"><?php echo(isset($title) ? $title : ''); ?><small> - Admin Panel</small></h3> | ||||
| 						</div> | ||||
| 						<div class="col-sm-6"> | ||||
| 							<div class="float-sm-right d-none d-sm-inline"> | ||||
| 								<span class="p-2 right badge badge-<?php echo((isset($status['online']) and $status['online']) ? 'success' : 'danger'); ?>"><?php echo $config['lua']['serverName'] ?></span> | ||||
| 							</div> | ||||
| 						</div> | ||||
| 					</div> | ||||
| 				</div> | ||||
| 			</div> | ||||
| 			<div class="content"> | ||||
| 				<div class="container-fluid"> | ||||
| 					<?php echo $content; ?> | ||||
| 				</div> | ||||
| 			</div> | ||||
| 			<?php | ||||
| 			} | ||||
| 			?> | ||||
| 			<div id="content"><?php echo $content; ?></div> | ||||
| 		</div> | ||||
| 		<div id="footer"> | ||||
|  | ||||
| 		<aside class="control-sidebar control-sidebar-dark"> | ||||
| 			<div class="p-3"> | ||||
| 				<h4>Account:</h4> | ||||
| 				<p><h5><a href="?action=logout"><i class="fas fa-sign-out-alt text-danger"></i> Log out</h5></a> | ||||
| 				<small>This will log you out</small></p> | ||||
| 			</div> | ||||
| 			<div class="p-3"> | ||||
| 				<h4>Site:</h4> | ||||
| 				<p><h5><a href="<?php echo BASE_URL; ?>" target="_blank"><i class="far fa-eye text-blue"></i> Preview</a></h5> | ||||
| 				<small>This will open a new tab</small></p> | ||||
| 			</div> | ||||
| 			<div class="p-3"> | ||||
| 				<h4>Version:</h4> | ||||
| 				<p><h5><a href="?p=version"><i class="fas fa-code-branch"></i> <?php echo MYAAC_VERSION; ?></a></h5> | ||||
| 				<small>Check for updates</small></p> | ||||
| 			</div> | ||||
| 			<div class="p-3"> | ||||
| 				<h4>Site:</h4> | ||||
| 				<p><h5><a href="https://github.com/slawkens/myaac" target="_blank"><i class="fab fa-github"></i> Github</a></h5> | ||||
| 				<small>Goto GitHub Page</small></p> | ||||
|  | ||||
| 				<p><h5><a href="http://my-aac.org/" target="_blank"><i class="fas fa-shoe-prints"></i> MyAAC Official</a></h5> | ||||
| 				<small>Goto MyAAC Official Website</small></p> | ||||
|  | ||||
| 				<p><h5><a href="?p=open_source"><i class="fas fa-wrench"></i> Open Source</a></h5> | ||||
| 				<small>View Open Source Software MyAAC is using</small></p> | ||||
| 			</div> | ||||
| 		</aside> | ||||
|  | ||||
| 		<footer class="main-footer"> | ||||
| 			<div class="float-sm-right d-none d-sm-inline"> | ||||
| 				<span class="p-2 right badge badge-<?php echo((isset($status['online']) and $status['online']) ? 'success' : 'danger'); ?>"><?php echo $config['lua']['serverName'] ?></span> | ||||
| 			</div> | ||||
| 			<?php echo base64_decode('UG93ZXJlZCBieSA8YSBocmVmPSJodHRwOi8vbXktYWFjLm9yZyIgdGFyZ2V0PSJfYmxhbmsiPk15QUFDLjwvYT4='); ?> | ||||
| 		</div> | ||||
| 		</footer> | ||||
| 		<div id="sidebar-overlay"></div> | ||||
| 	</div> | ||||
| <?php endif; ?> | ||||
|  | ||||
| <?php } else if (!$logged && !admin()) { | ||||
| 	echo $content; | ||||
| } | ||||
| ?> | ||||
| <?php | ||||
| /** | ||||
|  * @var OTS_Account $account_logged | ||||
|  */ | ||||
| if ($logged && admin()) { | ||||
| 	$twig->display('admin-bar.html.twig', [ | ||||
| 		'username' => USE_ACCOUNT_NAME ? $account_logged->getName() : $account_logged->getId() | ||||
| 	]); | ||||
| } | ||||
| ?> | ||||
| <script src="<?php echo BASE_URL; ?>tools/js/bootstrap.min.js"></script> | ||||
| <script src="<?php echo BASE_URL; ?>tools/js/jquery-ui.min.js"></script> | ||||
| <?php if (isset($use_datatable))  { ?> | ||||
| <script src="<?php echo BASE_URL; ?>tools/js/datatables.min.js"></script> | ||||
| <script src="<?php echo BASE_URL; ?>tools/js/datatables.bs.min.js"></script> | ||||
| <?php } ?> | ||||
| <script src="<?php echo BASE_URL; ?>tools/js/adminlte.min.js"></script> | ||||
| <?php $hooks->trigger(HOOK_ADMIN_BODY_END); ?> | ||||
| </body> | ||||
| </html> | ||||
|   | ||||
| @@ -1,8 +1,10 @@ | ||||
| <?php | ||||
| require('../../common.php'); | ||||
| require(SYSTEM . 'functions.php'); | ||||
| require(SYSTEM . 'init.php'); | ||||
| require(SYSTEM . 'login.php'); | ||||
| define('MYAAC_ADMIN', true); | ||||
|  | ||||
| require '../../common.php'; | ||||
| require SYSTEM . 'functions.php'; | ||||
| require SYSTEM . 'init.php'; | ||||
| require SYSTEM . 'login.php'; | ||||
|  | ||||
| if(!admin()) | ||||
| 	die('Access denied.'); | ||||
|   | ||||
							
								
								
									
										46
									
								
								admin/tools/reload_data.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,46 @@ | ||||
| <?php | ||||
| /** | ||||
|  * Project: MyAAC | ||||
|  *     Automatic Account Creator for Open Tibia Servers | ||||
|  * | ||||
|  * This is free software; you can redistribute it and/or | ||||
|  * modify it under the terms of the GNU Lesser General Public | ||||
|  * License as published by the Free Software Foundation; either | ||||
|  * version 2.1 of the License, or (at your option) any later version. | ||||
|  * | ||||
|  * This software is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | ||||
|  * Lesser General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU Lesser General Public | ||||
|  * License along with this library; if not, write to the Free Software | ||||
|  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA | ||||
|  * | ||||
|  * @package   MyAAC | ||||
|  * @author    Slawkens <slawkens@gmail.com> | ||||
|  * @copyright 2020 MyAAC | ||||
|  * @link      https://my-aac.org | ||||
|  */ | ||||
| define('MYAAC_ADMIN', true); | ||||
|  | ||||
| require '../../common.php'; | ||||
| require SYSTEM . 'functions.php'; | ||||
| require SYSTEM . 'init.php'; | ||||
| require SYSTEM . 'login.php'; | ||||
|  | ||||
| if (!admin()) | ||||
| 	die('Access denied.'); | ||||
|  | ||||
| ini_set('max_execution_time', 300); | ||||
| ob_implicit_flush(); | ||||
| ob_end_flush(); | ||||
| header('X-Accel-Buffering: no'); | ||||
|  | ||||
| require LIBS . 'DataLoader.php'; | ||||
|  | ||||
| require LOCALE . 'en/main.php'; | ||||
| require LOCALE . 'en/install.php'; | ||||
|  | ||||
| DataLoader::setLocale($locale); | ||||
| DataLoader::load(); | ||||
| @@ -1,9 +1,11 @@ | ||||
| <?php | ||||
| require('../../common.php'); | ||||
| require(SYSTEM . 'init.php'); | ||||
| require(SYSTEM . 'functions.php'); | ||||
| require(SYSTEM . 'status.php'); | ||||
| require(SYSTEM . 'login.php'); | ||||
| define('MYAAC_ADMIN', true); | ||||
|  | ||||
| require '../../common.php'; | ||||
| require SYSTEM . 'init.php'; | ||||
| require SYSTEM . 'functions.php'; | ||||
| require SYSTEM . 'status.php'; | ||||
| require SYSTEM . 'login.php'; | ||||
|  | ||||
| if(!admin()) | ||||
| 	die('Access denied.'); | ||||
|   | ||||
							
								
								
									
										53
									
								
								admin/tools/upload_image.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,53 @@ | ||||
| <?php | ||||
| define('MYAAC_ADMIN', true); | ||||
|  | ||||
| require '../../common.php'; | ||||
| require SYSTEM . 'functions.php'; | ||||
| require SYSTEM . 'init.php'; | ||||
| require SYSTEM . 'login.php'; | ||||
|  | ||||
| if(!admin()) | ||||
| 	die('Access denied.'); | ||||
|  | ||||
| // Don't attempt to process the upload on an OPTIONS request | ||||
| if ($_SERVER['REQUEST_METHOD'] == 'OPTIONS') { | ||||
| 	header('Access-Control-Allow-Methods: POST, OPTIONS'); | ||||
| 	return; | ||||
| } | ||||
|  | ||||
| $imageFolder = BASE . EDITOR_IMAGES_DIR; | ||||
|  | ||||
| reset ($_FILES); | ||||
| $temp = current($_FILES); | ||||
| if (is_uploaded_file($temp['tmp_name'])) { | ||||
| 	header('Access-Control-Allow-Credentials: true'); | ||||
| 	header('P3P: CP="There is no P3P policy."'); | ||||
|  | ||||
| 	// Sanitize input | ||||
| 	if (preg_match("/([^\w\s\d\-_~,;:\[\]\(\).])|([\.]{2,})/", $temp['name'])) { | ||||
| 		header('HTTP/1.1 400 Invalid file name.'); | ||||
| 		return; | ||||
| 	} | ||||
|  | ||||
| 	// Verify extension | ||||
| 	$ext = strtolower(pathinfo($temp['name'], PATHINFO_EXTENSION)); | ||||
| 	if (!in_array($ext, ['gif', 'jpg', 'png'])) { | ||||
| 		header('HTTP/1.1 400 Invalid extension.'); | ||||
| 		return; | ||||
| 	} | ||||
|  | ||||
| 	do { | ||||
| 		$randomName = generateRandomString(8). ".$ext"; | ||||
| 		$fileToWrite = $imageFolder . $randomName; | ||||
| 	} while (file_exists($fileToWrite)); | ||||
|  | ||||
| 	move_uploaded_file($temp['tmp_name'], $fileToWrite); | ||||
|  | ||||
| 	$returnPathToImage = BASE_URL . EDITOR_IMAGES_DIR . $randomName; | ||||
| 	echo json_encode(['location' => $returnPathToImage]); | ||||
| } else { | ||||
| 	// Notify editor that the upload failed | ||||
| 	header('HTTP/1.1 500 Server Error'); | ||||
| } | ||||
|  | ||||
|  | ||||
							
								
								
									
										160
									
								
								common.php
									
									
									
									
									
								
							
							
						
						| @@ -20,76 +20,132 @@ | ||||
|  * | ||||
|  * @package   MyAAC | ||||
|  * @author    Slawkens <slawkens@gmail.com> | ||||
|  * @copyright 2017 MyAAC | ||||
|  * @version   0.3.0 | ||||
|  * @link      http://my-aac.org | ||||
|  * @copyright 2019 MyAAC | ||||
|  * @link      https://my-aac.org | ||||
|  */ | ||||
| session_start(); | ||||
| if (version_compare(phpversion(), '7.2.5', '<')) die('PHP version 7.2.5 or higher is required.'); | ||||
|  | ||||
| define('MYAAC', true); | ||||
| define('MYAAC_VERSION', '0.3.0'); | ||||
| define('DATABASE_VERSION', 7); | ||||
| define('TABLE_PREFIX', 'myaac_'); | ||||
| const MYAAC = true; | ||||
| const MYAAC_VERSION = '0.9.0-alpha'; | ||||
| const DATABASE_VERSION = 35; | ||||
| const TABLE_PREFIX = 'myaac_'; | ||||
| define('START_TIME', microtime(true)); | ||||
| define('MYAAC_OS', (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') ? 'WINDOWS' : (strtoupper(PHP_OS) == 'DARWIN' ? 'MAC' : 'LINUX')); | ||||
| define('MYAAC_OS', stripos(PHP_OS, 'WIN') === 0 ? 'WINDOWS' : (strtoupper(PHP_OS) === 'DARWIN' ? 'MAC' : 'LINUX')); | ||||
| define('IS_CLI', in_array(php_sapi_name(), ['cli', 'phpdb'])); | ||||
|  | ||||
| // account flags | ||||
| define('FLAG_ADMIN', 1); | ||||
| define('FLAG_SUPER_ADMIN', 2); | ||||
| define('FLAG_CONTENT_PAGES', 4); | ||||
| define('FLAG_CONTENT_MAILER', 8); | ||||
| define('FLAG_CONTENT_NEWS', 16); | ||||
| define('FLAG_CONTENT_FORUM', 32); | ||||
| define('FLAG_CONTENT_COMMANDS', 64); | ||||
| define('FLAG_CONTENT_SPELLS', 128); | ||||
| define('FLAG_CONTENT_MONSTERS', 256); | ||||
| define('FLAG_CONTENT_SCREENSHOTS', 512); | ||||
| define('FLAG_CONTENT_MOVIES', 1024); | ||||
| const FLAG_NONE = 0; | ||||
| const FLAG_ADMIN = 1; | ||||
| const FLAG_SUPER_ADMIN = 2; | ||||
| const FLAG_SUPER_BOTH = 3; | ||||
| const FLAG_CONTENT_PAGES = 4; | ||||
| const FLAG_CONTENT_MAILER = 8; | ||||
| const FLAG_CONTENT_NEWS = 16; | ||||
| const FLAG_CONTENT_FORUM = 32; | ||||
| const FLAG_CONTENT_COMMANDS = 64; | ||||
| const FLAG_CONTENT_SPELLS = 128; | ||||
| const FLAG_CONTENT_MONSTERS = 256; | ||||
| const FLAG_CONTENT_GALLERY = 512; | ||||
| const FLAG_CONTENT_VIDEOS = 1024; | ||||
| const FLAG_CONTENT_FAQ = 2048; | ||||
| const FLAG_CONTENT_MENUS = 4096; | ||||
| const FLAG_CONTENT_PLAYERS = 8192; | ||||
|  | ||||
| // account access types | ||||
| const ACCOUNT_WEB_FLAGS = [ | ||||
| 	FLAG_NONE => 'None', | ||||
| 	FLAG_ADMIN =>'Admin', | ||||
| 	FLAG_SUPER_ADMIN => 'Super Admin', | ||||
| 	FLAG_SUPER_BOTH =>'(Admin + Super Admin)', | ||||
| ]; | ||||
|  | ||||
| // news | ||||
| define('NEWS', 1); | ||||
| define('TICKET', 2); | ||||
| define('ARTICLE', 3); | ||||
| const NEWS = 1; | ||||
| const TICKER = 2; | ||||
| const ARTICLE = 3; | ||||
|  | ||||
| // here you can change location of admin panel | ||||
| // you need also to rename folder "admin" | ||||
| // this may improve security | ||||
| const ADMIN_PANEL_FOLDER = 'admin'; | ||||
|  | ||||
| // directories | ||||
| define('BASE', dirname(__FILE__) . '/'); | ||||
| define('ADMIN', BASE . 'admin/'); | ||||
| define('SYSTEM', BASE . 'system/'); | ||||
| define('CACHE', SYSTEM . 'cache/'); | ||||
| define('LOCALE', SYSTEM . 'locale/'); | ||||
| define('LIBS', SYSTEM . 'libs/'); | ||||
| define('LOGS', SYSTEM . 'logs/'); | ||||
| define('PLUGINS', BASE . 'plugins/'); | ||||
| define('TEMPLATES', BASE . 'templates/'); | ||||
| define('TOOLS', BASE . 'tools/'); | ||||
| const BASE = __DIR__ . '/'; | ||||
| const ADMIN = BASE . ADMIN_PANEL_FOLDER . '/'; | ||||
| const SYSTEM = BASE . 'system/'; | ||||
| const CACHE = SYSTEM . 'cache/'; | ||||
| const LOCALE = SYSTEM . 'locale/'; | ||||
| const LIBS = SYSTEM . 'libs/'; | ||||
| const LOGS = SYSTEM . 'logs/'; | ||||
| const PAGES = SYSTEM . 'pages/'; | ||||
| const PLUGINS = BASE . 'plugins/'; | ||||
| const TEMPLATES = BASE . 'templates/'; | ||||
| const TOOLS = BASE . 'tools/'; | ||||
| const VENDOR = BASE . 'vendor/'; | ||||
|  | ||||
| // other dirs | ||||
| const SESSIONS_DIR = SYSTEM . 'php_sessions'; | ||||
| const GUILD_IMAGES_DIR = 'images/guilds/'; | ||||
| const EDITOR_IMAGES_DIR = 'images/editor/'; | ||||
| const GALLERY_DIR = 'images/gallery/'; | ||||
|  | ||||
| // menu categories | ||||
| const MENU_CATEGORY_NEWS = 1; | ||||
| const MENU_CATEGORY_ACCOUNT = 2; | ||||
| const MENU_CATEGORY_COMMUNITY = 3; | ||||
| const MENU_CATEGORY_FORUM = 4; | ||||
| const MENU_CATEGORY_LIBRARY = 5; | ||||
| const MENU_CATEGORY_SHOP = 6; | ||||
|  | ||||
| // otserv versions | ||||
| define('OTSERV', 1); | ||||
| define('OTSERV_06', 2); | ||||
| define('OTSERV_FIRST', OTSERV); | ||||
| define('OTSERV_LAST', OTSERV_06); | ||||
| define('TFS_02', 3); | ||||
| define('TFS_03', 4); | ||||
| define('TFS_FIRST', TFS_02); | ||||
| define('TFS_LAST', TFS_03); | ||||
| const OTSERV = 1; | ||||
| const OTSERV_06 = 2; | ||||
| const OTSERV_FIRST = OTSERV; | ||||
| const OTSERV_LAST = OTSERV_06; | ||||
| const TFS_02 = 3; | ||||
| const TFS_03 = 4; | ||||
| const TFS_FIRST = TFS_02; | ||||
| const TFS_LAST = TFS_03; | ||||
|  | ||||
| // other definitions | ||||
| const ACCOUNT_NUMBER_LENGTH = 8; | ||||
|  | ||||
| if (!IS_CLI) { | ||||
| 	session_save_path(SESSIONS_DIR); | ||||
| 	session_start(); | ||||
| } | ||||
|  | ||||
| // basedir | ||||
| $basedir = ''; | ||||
| $tmp = explode('/', $_SERVER['SCRIPT_NAME']); | ||||
| $size = sizeof($tmp) - 1; | ||||
| $size = count($tmp) - 1; | ||||
| for($i = 1; $i < $size; $i++) | ||||
| 	$basedir .= '/' . $tmp[$i]; | ||||
|  | ||||
| $basedir = str_replace('/admin', '', $basedir); | ||||
| $basedir = str_replace('/install', '', $basedir); | ||||
| $basedir = str_replace(['/' . ADMIN_PANEL_FOLDER, '/install', '/tools'], '', $basedir); | ||||
| define('BASE_DIR', $basedir); | ||||
|  | ||||
| if(isset($_SERVER['HTTPS'][0]) && $_SERVER['HTTPS'] == 'on') | ||||
| 	define('SERVER_URL', 'https://' . $_SERVER['HTTP_HOST']); | ||||
| else | ||||
| 	define('SERVER_URL', 'http://' . $_SERVER['HTTP_HOST']); | ||||
| if(!IS_CLI) { | ||||
| 	if (isset($_SERVER['HTTP_HOST'][0])) { | ||||
| 		$baseHost = $_SERVER['HTTP_HOST']; | ||||
| 	} else { | ||||
| 		if (isset($_SERVER['SERVER_NAME'][0])) { | ||||
| 			$baseHost = $_SERVER['SERVER_NAME']; | ||||
| 		} else { | ||||
| 			$baseHost = $_SERVER['SERVER_ADDR']; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| define('BASE_URL', SERVER_URL . BASE_DIR . '/'); | ||||
| define('ADMIN_URL', SERVER_URL . BASE_DIR . '/admin/'); | ||||
| //define('CURRENT_URL', BASE_URL . $_SERVER['REQUEST_URI']); | ||||
| ?> | ||||
| 	define('SERVER_URL', 'http' . (isset($_SERVER['HTTPS'][0]) && strtolower($_SERVER['HTTPS']) === 'on' ? 's' : '') . '://' . $baseHost); | ||||
| 	define('BASE_URL', SERVER_URL . BASE_DIR . '/'); | ||||
| 	define('ADMIN_URL', SERVER_URL . BASE_DIR . '/' . ADMIN_PANEL_FOLDER . '/'); | ||||
|  | ||||
| 	//define('CURRENT_URL', BASE_URL . $_SERVER['REQUEST_URI']); | ||||
| } | ||||
|  | ||||
| $autoloadFile = VENDOR . 'autoload.php'; | ||||
| if (!is_file($autoloadFile)) { | ||||
| 	throw new RuntimeException('The vendor folder is missing. Please download Composer: <a href="https://getcomposer.org/download">https://getcomposer.org/download</a>, install it and execute in the main MyAAC directory this command: <b>composer install</b>. Or download MyAAC from <a href="https://github.com/slawkens/myaac/releases">GitHub releases</a>, which includes Vendor folder.'); | ||||
| } | ||||
|  | ||||
| require $autoloadFile; | ||||
|   | ||||
							
								
								
									
										19
									
								
								composer.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,19 @@ | ||||
| { | ||||
|     "require": { | ||||
|         "php": "^7.2.5 || ^8.0", | ||||
|         "ext-pdo": "*", | ||||
|         "ext-pdo_mysql": "*", | ||||
|         "ext-json": "*", | ||||
|         "ext-xml": "*", | ||||
|         "ext-dom": "*", | ||||
|         "phpmailer/phpmailer": "^6.1", | ||||
|         "composer/semver": "^3.2", | ||||
|         "twig/twig": "^2.0", | ||||
|         "erusev/parsedown": "^1.7", | ||||
|         "nikic/fast-route": "^1.3", | ||||
|         "matomo/device-detector": "^6.0" | ||||
|     }, | ||||
|     "require-dev": { | ||||
|         "filp/whoops": "^2.15" | ||||
|     } | ||||
| } | ||||
| @@ -1,3 +0,0 @@ | ||||
| <?php | ||||
| 	// place for your configuration directives, so you can later easily update myaac | ||||
| ?> | ||||
							
								
								
									
										172
									
								
								config.php
									
									
									
									
									
								
							
							
						
						| @@ -12,15 +12,25 @@ | ||||
|  * | ||||
|  * @package   MyAAC | ||||
|  * @author    Slawkens <slawkens@gmail.com> | ||||
|  * @copyright 2017 MyAAC | ||||
|  * @version   0.3.0 | ||||
|  * @link      http://my-aac.org | ||||
|  * @copyright 2019 MyAAC | ||||
|  * @link      https://my-aac.org | ||||
|  */ | ||||
|  | ||||
| $config = array( | ||||
| 	// directories & files | ||||
| 	'server_path' => '', // path to the server directory (same directory where config file is located) | ||||
|  | ||||
| 	/** | ||||
| 	 * Environment Setting | ||||
| 	 * | ||||
| 	 * if you use this script on your live server - set to 'prod' (production) | ||||
| 	 * if you want to test and debug the script locally, or develop plugins, set to 'dev' (development) | ||||
| 	 * WARNING: on 'dev' cache is disabled, so site will be significantly slower !!! | ||||
| 	 * WARNING2: on 'dev' all PHP errors/warnings are displayed | ||||
| 	 * Recommended: 'prod' cause of speed (page load time is better) | ||||
| 	 */ | ||||
| 	'env' => 'prod', // 'prod' for production and 'dev' for development | ||||
|  | ||||
| 	'template' => 'kathrine', // template used by website (kathrine, tibiacom) | ||||
| 	'template_allow_change' => true, // allow users to choose their own template while browsing website? | ||||
|  | ||||
| @@ -30,23 +40,22 @@ $config = array( | ||||
| 	// used for the Downloads page and some templates aswell | ||||
| 	'client' => 1098, // 954 = client 9.54 | ||||
|  | ||||
| 	'friendly_urls' => false, // mod_rewrite is required for this, it makes links looks more elegant to eye, and also are SEO friendly (example: http://my-aac.org/guilds/Testing instead of http://my-aac.org/?subtopic=guilds&name=Testing). Remember to rename .htaccess.dist to .htaccess | ||||
| 	'session_prefix' => 'myaac_', // must be unique for every site on your server | ||||
| 	'friendly_urls' => false, // mod_rewrite is required for this, it makes links looks more elegant to eye, and also are SEO friendly (example: https://my-aac.org/guilds/Testing instead of https://my-aac.org/?subtopic=guilds&name=Testing). Remember to rename .htaccess.dist to .htaccess | ||||
| 	'gzip_output' => false, // gzip page content before sending it to the browser, uses less bandwidth but more cpu cycles | ||||
|  | ||||
| 	// gesior backward support (templates & pages) | ||||
| 	// allows using gesior templates and pages with myaac | ||||
| 	// might bring some performance when disabled | ||||
| 	'backward_support' => true, | ||||
|  | ||||
| 	// head options (html) | ||||
| 	'meta_description' => 'Tibia is a free massive multiplayer online role playing game (MMORPG).', // description of the site | ||||
| 	'meta_keywords' => 'free online game, free multiplayer game, ots, open tibia server', // keywords list separated by commas | ||||
| 	'title_separator' => ' - ', | ||||
|  | ||||
| 	// footer | ||||
| 	'footer' => ''/*'<br/>Your Server © 2016. All rights reserved.'*/, | ||||
|  | ||||
| 	'debug_level' => 0, // 0 - disabled, 1 - show load time, 2 - show db query counter, 3 - both, 4 - memory usage, 5 - load time & load time, 6 - queries & memory usage, 7 - all | ||||
|  | ||||
| 	'language' => 'en', // default language (currently only 'en' available) | ||||
| 	'language_allow_change' => false, | ||||
|  | ||||
| @@ -55,7 +64,7 @@ $config = array( | ||||
| 	'views_counter' => true, | ||||
|  | ||||
| 	// cache system. by default file cache is used | ||||
| 	'cache_engine' => 'auto', // apc, eaccelerator, xcache, file, auto, or blank to disable. | ||||
| 	'cache_engine' => 'auto', // apc, apcu, eaccelerator, xcache, file, auto, or blank to disable. | ||||
| 	'cache_prefix' => 'myaac_', // have to be unique if running more MyAAC instances on the same server (except file system cache) | ||||
|  | ||||
| 	// database details (leave blank for auto detect from config.lua) | ||||
| @@ -64,22 +73,46 @@ $config = array( | ||||
| 	'database_user' => '', | ||||
| 	'database_password' => '', | ||||
| 	'database_name' => '', | ||||
| 	'database_log' => false, // should database queries be logged and saved into system/logs/database.log? | ||||
| 	'database_socket' => '', // set if you want to connect to database through socket (example: /var/run/mysqld/mysqld.sock) | ||||
| 	'database_persistent' => false, // use database permanent connection (like server), may speed up your site | ||||
|  | ||||
| 	// multiworld system | ||||
| 	// multiworld system (only TFS 0.3) | ||||
| 	'multiworld' => false, // use multiworld system? | ||||
| 	'worlds' => array( // list of worlds | ||||
| 		//'1' => 'Your World Name', | ||||
| 		//'2' => 'Your Second World Name' | ||||
| 	), | ||||
|  | ||||
| 	// items | ||||
| 	'outfit_images_url' => 'http://outfit-images.ots.me/outfit.php', // set to animoutfit.php for animated outfit | ||||
| 	'item_images_url' => 'http://item-images.ots.me/960/', // set to images/items if you host your own items in images folder | ||||
| 	// images | ||||
| 	'outfit_images_url' => 'https://outfit-images.ots.me/outfit.php', // set to animoutfit.php for animated outfit | ||||
| 	'outfit_images_wrong_looktypes' => [75, 126, 127, 266, 302], // this looktypes needs to have different margin-top and margin-left because they are wrong positioned | ||||
| 	'item_images_url' => 'https://item-images.ots.me/1092/', // set to images/items if you host your own items in images folder | ||||
| 	'item_images_extension' => '.gif', | ||||
|  | ||||
| 	// creatures | ||||
| 	'creatures_images_url' => 'images/monsters/', // set to images/monsters if you host your own creatures in images folder | ||||
| 	'creatures_images_extension' => '.gif', | ||||
| 	'creatures_images_preview' => false,  // set to true to allow picture previews for creatures | ||||
| 	'creatures_items_url' => 'https://tibia.fandom.com/wiki/', // set to website which shows details about items. | ||||
| 	'creatures_loot_percentage' => true, // set to true to show the loot tooltip percent | ||||
|  | ||||
| 	// account | ||||
| 	'account_management' => true, // disable if you're using other method to manage users (fe. tfs account manager) | ||||
| 	'account_mail_verify' => false, // force users to confirm their email addresses when registering account | ||||
| 	'account_login_by_email' => false, // use email instead of Account Name like in latest Tibia | ||||
| 	'account_login_by_email_fallback' => false, // allow also additionally login by Account Name/Number (for users that might forget their email) | ||||
| 	'account_create_auto_login' => false, // auto login after creating account? | ||||
| 	'account_create_character_create' => true, // allow directly to create character on create account page? | ||||
| 	'account_mail_verify' => false, // force users to confirm their email addresses when registering | ||||
| 	'account_mail_confirmed_reward' => [ // reward users for confirming their E-Mails | ||||
| 		// account_mail_verify needs to be enabled too | ||||
| 		'premium_days' => 0, | ||||
| 		'premium_points' => 0, | ||||
| 		'coins' => 0, | ||||
| 		'message' => 'You received %d %s for confirming your E-Mail address.' // example: You received 20 premium points for confirming your E-Mail address. | ||||
| 	], | ||||
| 	'account_mail_unique' => true, // email addresses cannot be duplicated? (one account = one email) | ||||
| 	'account_mail_block_plus_sign' => true, // block email with '+' signs like test+box@gmail.com (help protect against spamming accounts) | ||||
| 	'account_premium_days' => 0, // default premium days on new account | ||||
| 	'account_premium_points' => 0, // default premium points on new account | ||||
| 	'account_welcome_mail' => true, // send welcome email when user registers | ||||
| @@ -97,21 +130,17 @@ $config = array( | ||||
| 	'mail_address' => 'no-reply@your-server.org', // server e-mail address (from:) | ||||
| 	'mail_admin' => 'your-address@your-server.org', // admin email address, where mails from contact form will be sent | ||||
| 	'mail_signature' => array( // signature that will be included at the end of every message sent using _mail function | ||||
| 		'plain' => ''/*'--\nMy Server,\nhttp://www.myserver.com'*/, | ||||
| 		'plain' => ""/*"--\nMy Server,\nhttp://www.myserver.com"*/, | ||||
| 		'html' => ''/*'<br/>My Server,\n<a href="http://www.myserver.com">myserver.com</a>'*/ | ||||
| 	), | ||||
| 	'smtp_enabled' => false, // send by smtp or mail function (set false if use mail function) | ||||
| 	'smtp_host' => '', // mail host | ||||
| 	'smtp_port' => 25, // 25 (default) / 465 (ssl, e.g. gmail) | ||||
| 	'smtp_enabled' => false, // send by smtp or mail function (set false if use mail function, set to true if you use GMail or Microsoft Outlook) | ||||
| 	'smtp_host' => '', // mail host. smtp.gmail.com for GMail / smtp-mail.outlook.com for Microsoft Outlook | ||||
| 	'smtp_port' => 25, // 25 (default) / 465 (ssl, GMail) / 587 (tls, Microsoft Outlook) | ||||
| 	'smtp_auth' => true, // need authorization? | ||||
| 	'smtp_user' => 'admin@example.org', | ||||
| 	'smtp_user' => 'admin@example.org', // here your email username | ||||
| 	'smtp_pass' => '', | ||||
|  | ||||
| 	// reCAPTCHA (prevent spam bots) | ||||
| 	'recaptcha_enabled' => false, // enable recaptcha verification code | ||||
| 	'recaptcha_site_key' => '', // get your own public and private keys at https://www.google.com/recaptcha | ||||
| 	'recaptcha_secret_key' => '', | ||||
| 	'recaptcha_theme' => 'light', // light, dark | ||||
| 	'smtp_secure' => '', // What kind of encryption to use on the SMTP connection. Options: '', 'ssl' (GMail) or 'tls' (Microsoft Outlook) | ||||
| 	'smtp_debug' => false, // set true to debug (you will see more info in error.log) | ||||
|  | ||||
| 	// | ||||
| 	'generate_new_reckey' => true,				// let player generate new recovery key, he will receive e-mail with new rec key (not display on page, hacker can't generate rec key) | ||||
| @@ -119,12 +148,24 @@ $config = array( | ||||
| 	'send_mail_when_change_password' => true,	// send e-mail with new password when change password to account | ||||
| 	'send_mail_when_generate_reckey' => true,	// send e-mail with rec key (key is displayed on page anyway when generate) | ||||
|  | ||||
| 	// you may need to adjust this for older tfs versions | ||||
| 	// by removing Community Manager | ||||
| 	'account_types' => [ | ||||
| 		'None', | ||||
| 		'Normal', | ||||
| 		'Tutor', | ||||
| 		'Senior Tutor', | ||||
| 		'Gamemaster', | ||||
| 		'Community Manager', | ||||
| 		'God', | ||||
| 	], | ||||
|  | ||||
| 	// genders (aka sex) | ||||
| 	'genders' => array( | ||||
| 		0 => 'Female', | ||||
| 		1 => 'Male' | ||||
| 	), | ||||
| 	 | ||||
|  | ||||
| 	// new character config | ||||
| 	'character_samples' => array( // vocations, format: ID_of_vocation => 'Name of Character to copy' | ||||
| 		//0 => 'Rook Sample', | ||||
| @@ -134,11 +175,25 @@ $config = array( | ||||
| 		4 => 'Knight Sample' | ||||
| 	), | ||||
|  | ||||
| 	'use_character_sample_skills' => false, | ||||
|  | ||||
| 	// it must show limited number of players after using search in character page | ||||
| 	'characters_search_limit' => 15, | ||||
|  | ||||
| 	// town list used when creating character | ||||
| 	// won't be displayed if there is only one item (rookgaard for example) | ||||
| 	'character_towns' => array(1), | ||||
|  | ||||
| 	// characters length | ||||
| 	// This is the minimum and the maximum length that a player can create a character. It is highly recommend the maximum length to be 21. | ||||
| 	'character_name_min_length' => 4, | ||||
| 	'character_name_max_length' => 21, | ||||
| 	'character_name_npc_check' => true, | ||||
|  | ||||
| 	// list of towns | ||||
| 	// if you use TFS 1.3 with support for 'towns' table in database, then you can ignore this - it will be configured automatically (from MySQL database - Table - towns) | ||||
| 	// otherwise it will try to load from your .OTBM map file | ||||
| 	// if you don't see towns on website, then you need to fill this out | ||||
| 	'towns' => array( | ||||
| 		0 => 'No town', | ||||
| 		1 => 'Sample town' | ||||
| @@ -149,16 +204,11 @@ $config = array( | ||||
| 	'guild_need_level' => 1, // min. level to form a guild | ||||
| 	'guild_need_premium' => true, // require premium account to form a guild? | ||||
| 	'guild_image_size_kb' => 80, // maximum size of the guild logo image in KB (kilobytes) | ||||
| 	'guild_description_default' => 'New guild. Leader must edit this text :)', | ||||
| 	'guild_description_chars_limit' => 1000, // limit of guild description | ||||
| 	'guild_description_lines_limit' => 6, // limit of lines, if description has more lines it will be showed as long text, without 'enters' | ||||
| 	'guild_motd_chars_limit' => 150, // limit of MOTD (message of the day) that is shown later in the game on the guild channel | ||||
|  | ||||
| 	'quests' => array(), // quests list (displayed in character view), name => storage | ||||
|  | ||||
| 	'signature_enabled' => true, | ||||
| 	'signature_type' => 'tibian', // signature engine to use: tibian, mango, gesior | ||||
| 	'signature_cache_time' => 5, // how long to store cached file (in minutes) | ||||
|  | ||||
| 	// online page | ||||
| 	'online_record' => true, // display players record? | ||||
| 	'online_vocations' => false, // display vocation statistics? | ||||
| @@ -172,18 +222,22 @@ $config = array( | ||||
| 	'team_display_status' => true, | ||||
| 	'team_display_lastlogin' => true, | ||||
| 	'team_display_world' => false, | ||||
| 	'team_display_outfit' => true, | ||||
|  | ||||
| 	// bans page | ||||
| 	'bans_limit' => 50, | ||||
| 	'bans_display_all' => true, // should all bans be displayed? (sorted page by page) | ||||
| 	'bans_per_page' => 20, | ||||
|  | ||||
| 	// highscores page | ||||
| 	'highscores_vocation_box' => true, // show 'Choose a vocation' box on the highscores (allowing peoples to sort highscores by vocation)? | ||||
| 	'highscores_vocation' => true, // show player vocation under his nickname? | ||||
| 	'highscores_frags' => false, // show 'Frags' tab (best fraggers on the server)? Only 0.3 | ||||
| 	'highscores_frags' => false, // show 'Frags' tab (best fraggers on the server)? | ||||
| 	'highscores_balance' => false, // show 'Balance' tab (richest players on the server) | ||||
| 	'highscores_outfit' => true, // show player outfit? | ||||
| 	'highscores_country_box' => false, // doesnt work yet! (not implemented) | ||||
| 	'highscores_groups_hidden' => 4, // this group id and higher won't be shown on the highscores | ||||
| 	'highscores_groups_hidden' => 3, // this group id and higher won't be shown on the highscores | ||||
| 	'highscores_ids_hidden' => array(0), // this ids of players will be hidden on the highscores (should be ids of samples) | ||||
| 	'highscores_per_page' => 100, // how many records per page on highscores | ||||
| 	'highscores_cache_ttl' => 15, // how often to update highscores from database in minutes (default 15 minutes) | ||||
|  | ||||
| 	// characters page | ||||
| 	'characters' => array( // what things to display on character view page (true/false in each option) | ||||
| @@ -197,44 +251,68 @@ $config = array( | ||||
| 		'quests' => true, | ||||
| 		'skills' => true, | ||||
| 		'equipment' => true, | ||||
| 		'frags' => false | ||||
| 		'frags' => false, | ||||
| 		'deleted' => false, // should deleted characters from same account be still listed on the list of characters? When enabled it will show that character is "[DELETED]" | ||||
| 	), | ||||
| 	'quests' => array( | ||||
| 		//'Some Quest' => 123, | ||||
| 		//'Some Quest Two' => 456, | ||||
| 	), // quests list (displayed in character view), name => storage | ||||
| 	'signature_enabled' => true, | ||||
| 	'signature_type' => 'tibian', // signature engine to use: tibian, mango, gesior | ||||
| 	'signature_cache_time' => 5, // how long to store cached file (in minutes), default 5 minutes | ||||
| 	'signature_browser_cache' => 60, // how long to cache by browser (in minutes), default 1 hour | ||||
|  | ||||
| 	// news page | ||||
| 	'news_limit' => 5, // limit of news on latest news page | ||||
| 	'news_limit' => 5, // limit of news on the latest news page | ||||
| 	'news_ticker_limit' => 5, // limit of news in tickers (mini news) (0 to disable) | ||||
| 	'news_date_format' => 'j.n.Y', // check php manual date() function for more info about this | ||||
| 	'news_author' => true, | ||||
| 	'news_author' => true, // show author of the news | ||||
|  | ||||
| 	// gifts/shop system | ||||
| 	'gifts_system' => false, | ||||
|  | ||||
| 	// support/system | ||||
| 	'bug_report' => true, // this configurable has no effect, its always enabled | ||||
|  | ||||
| 	// forum | ||||
| 	'forum' => 'site', // link to the server forum, set to "site" if you want to use build in forum system, otherwise leave empty if you aren't going to use any forum | ||||
| 	'forum_level_required' => 0, // level required to post, 0 to disable | ||||
| 	'forum_post_interval' => 30, // in seconds | ||||
| 	'forum_posts_per_page' => 20, | ||||
| 	'forum_threads_per_page' => 20, | ||||
| 	// uncomment to force use table for forum | ||||
| 	//'forum_table_prefix' => 'z_', // what forum mysql table to use, z_ (for gesior old forum) or myaac_ (for myaac) | ||||
|  | ||||
| 	// last kills | ||||
| 	'last_kills_limit' => 50, // max. number of deaths shown on the last kills page | ||||
|  | ||||
| 	// status, took automatically from config file if empty | ||||
| 	'status_enabled' => true, // you can disable status checking by settings this to "false" | ||||
| 	'status_ip' => '', | ||||
| 	'status_port' => '', | ||||
| 	'status_timeout' => 2.0, // how long to wait for the initial response from the server (default: 2 seconds) | ||||
|  | ||||
| 	// how often to connect to server and update status (default: every minute) | ||||
| 	// if your status timeout in config.lua is bigger, that it will be used instead | ||||
| 	// when server is offline, it will be checked every time web refreshes, ignoring this variable | ||||
| 	'status_interval' => 60, | ||||
|  | ||||
| 	// admin panel | ||||
| 	'admin_plugins_manage_enable' => 'yes', // you can disable possibility to upload and uninstall plugins, for security | ||||
| 	// enable support for plain php pages in admin panel, for security | ||||
| 	// existing pages still will be working, so you need to delete them manually | ||||
| 	'admin_pages_php_enable' => 'no', | ||||
| 	'admin_panel_modules' => 'statistics,web_status,server_status,lastlogin,created,points,coins,balance',    // default - statistics,web_status,server_status,lastlogin,created,points,coins,balance | ||||
|  | ||||
| 	// other | ||||
| 	'anonymous_usage_statistics' => true, | ||||
| 	'email_lai_sec_interval' => 60, // time in seconds between e-mails to one account from lost account interface, block spam | ||||
| 	'google_analytics_id' => '', // e.g.: UA-XXXXXXX-X | ||||
| 	'experiencetable_columns' => 5, // how many columns to display in experience table page. * experiencetable_rows, 5 = 500 (will show up to 500 level) | ||||
| 	'experiencetable_rows' => 100, // till how many levels in one column | ||||
| 	'experiencetable_columns' => 3, // how many columns to display in experience table page. * experiencetable_rows, 5 = 500 (will show up to 500 level) | ||||
| 	'experiencetable_rows' => 200, // till how many levels in one column | ||||
| 	'date_timezone' => 'Europe/Berlin', // more info at http://php.net/manual/en/timezones.php | ||||
| 	'footer_show_load_time' => true, // display load time of the page in the footer | ||||
|  | ||||
| 	'monsters' => array(), | ||||
| 	'npc' => array() | ||||
| ); | ||||
|  | ||||
| // download link to client. | ||||
| $config['client_download'] = 'http://tibia-clients.com/clients/download/'. $config['client'] .'/exe/windows'; | ||||
| $config['client_download_linux'] = 'http://tibia-clients.com/clients/download/'. $config['client'] .'/tar/linux'; | ||||
|  | ||||
| ?> | ||||
|   | ||||
							
								
								
									
										9
									
								
								cypress.config.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,9 @@ | ||||
| const { defineConfig } = require("cypress"); | ||||
|  | ||||
| module.exports = defineConfig({ | ||||
|   e2e: { | ||||
|     setupNodeEvents(on, config) { | ||||
|       // implement node event listeners here | ||||
|     }, | ||||
|   }, | ||||
| }); | ||||
							
								
								
									
										75
									
								
								cypress/e2e/1-install.cy.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,75 @@ | ||||
| describe('Install MyAAC', () => { | ||||
| 	beforeEach(() => { | ||||
| 		// Cypress starts out with a blank slate for each test | ||||
| 		// so we must tell it to visit our website with the `cy.visit()` command. | ||||
| 		// Since we want to visit the same URL at the start of all our tests, | ||||
| 		// we include it in our beforeEach function so that it runs before each test | ||||
| 		cy.visit(Cypress.env('URL')) | ||||
| 	}) | ||||
|  | ||||
| 	it('Go through installer', () => { | ||||
| 		cy.visit(Cypress.env('URL') + '/install/?step=welcome') | ||||
| 		cy.wait(1000) | ||||
|  | ||||
| 		cy.screenshot('install-welcome') | ||||
|  | ||||
| 		// step 1 - Welcome | ||||
| 		cy.get('select[name="lang"]').select('en') | ||||
|  | ||||
| 		//cy.get('input[type=button]').contains('Next »').click() | ||||
|  | ||||
| 		cy.get('form').submit() | ||||
|  | ||||
| 		// step 2 - License | ||||
| 		// just skip | ||||
| 		cy.contains('GNU/GPL License'); | ||||
| 		cy.get('form').submit() | ||||
|  | ||||
| 		// step 3 - Requirements | ||||
| 		cy.contains('Requirements check'); | ||||
|  | ||||
| 		cy.get('#step').then(elem => { | ||||
| 			elem.val('config'); | ||||
| 		}); | ||||
|  | ||||
| 		cy.get('form').submit() | ||||
|  | ||||
| 		// step 4 - Configuration | ||||
| 		cy.contains('Basic configuration'); | ||||
|  | ||||
| 		cy.get('#vars_server_path').click().clear().type(Cypress.env('SERVER_PATH')) | ||||
| 		cy.get('#vars_mail_admin').click().clear().type('noone@example.net') | ||||
|  | ||||
| 		cy.get('[type="checkbox"]').uncheck() // usage statistics uncheck | ||||
|  | ||||
| 		cy.wait(1000) | ||||
|  | ||||
| 		cy.get('form').submit() | ||||
|  | ||||
| 		// check if there is any error | ||||
|  | ||||
|  | ||||
| 		// step 5 - Import Schema | ||||
| 		cy.contains('Import MySQL schema'); | ||||
|  | ||||
| 		// AAC is not installed yet, this message should not come | ||||
| 		cy.contains('Seems AAC is already installed. Skipping importing MySQL schema..').should('not.exist') | ||||
|  | ||||
| 		cy.contains('[class="alert alert-success"]', 'Local configuration has been saved into file: config.local.php').should('be.visible') | ||||
|  | ||||
| 		cy.get('form').submit() | ||||
|  | ||||
| 		// step 6 - Admin Account | ||||
| 		cy.get('#vars_email').click().clear().type('admin@my-aac.org') | ||||
| 		cy.get('#vars_account').click().clear().type('admin') | ||||
| 		cy.get('#vars_password').click().clear().type('test1234') | ||||
| 		cy.get('#vars_password_confirm').click().clear().type('test1234') | ||||
| 		cy.get('#vars_player_name').click().clear().type('Admin') | ||||
|  | ||||
| 		cy.get('form').submit() | ||||
|  | ||||
| 		cy.contains('[class="alert alert-success"]', 'Congratulations', { timeout: 30000 }).should('be.visible') | ||||
|  | ||||
| 		cy.screenshot('install-finish') | ||||
| 	}) | ||||
| }) | ||||
							
								
								
									
										33
									
								
								cypress/e2e/2-create-account.cy.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,33 @@ | ||||
| describe('Create Account Page', () => { | ||||
| 	beforeEach(() => { | ||||
| 		// Cypress starts out with a blank slate for each test | ||||
| 		// so we must tell it to visit our website with the `cy.visit()` command. | ||||
| 		// Since we want to visit the same URL at the start of all our tests, | ||||
| 		// we include it in our beforeEach function so that it runs before each test | ||||
| 		cy.visit(Cypress.env('URL') + '/index.php/account/create') | ||||
| 	}) | ||||
|  | ||||
| 	it('Create Test Account', () => { | ||||
| 		cy.screenshot('create-account-page') | ||||
|  | ||||
| 		cy.get('#account_input').type('tester') | ||||
| 		cy.get('#email').type('tester@example.com') | ||||
|  | ||||
| 		cy.get('#password').type('test1234') | ||||
| 		cy.get('#password2').type('test1234') | ||||
|  | ||||
| 		cy.get('#character_name').type('Slaw') | ||||
|  | ||||
| 		cy.get('#sex1').check() | ||||
| 		cy.get('#vocation1').check() | ||||
| 		cy.get('#accept_rules').check() | ||||
|  | ||||
| 		cy.get('#createaccount').submit() | ||||
|  | ||||
| 		// no errors please | ||||
| 		cy.contains('The Following Errors Have Occurred:').should('not.exist') | ||||
|  | ||||
| 		// ss of post page | ||||
| 		cy.screenshot('create-account-page-post') | ||||
| 	}) | ||||
| }) | ||||
							
								
								
									
										5
									
								
								cypress/fixtures/example.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,5 @@ | ||||
| { | ||||
|   "name": "Using fixtures to represent data", | ||||
|   "email": "hello@cypress.io", | ||||
|   "body": "Fixtures are a great way to mock data for responses to routes" | ||||
| } | ||||
							
								
								
									
										25
									
								
								cypress/support/commands.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,25 @@ | ||||
| // *********************************************** | ||||
| // This example commands.js shows you how to | ||||
| // create various custom commands and overwrite | ||||
| // existing commands. | ||||
| // | ||||
| // For more comprehensive examples of custom | ||||
| // commands please read more here: | ||||
| // https://on.cypress.io/custom-commands | ||||
| // *********************************************** | ||||
| // | ||||
| // | ||||
| // -- This is a parent command -- | ||||
| // Cypress.Commands.add('login', (email, password) => { ... }) | ||||
| // | ||||
| // | ||||
| // -- This is a child command -- | ||||
| // Cypress.Commands.add('drag', { prevSubject: 'element'}, (subject, options) => { ... }) | ||||
| // | ||||
| // | ||||
| // -- This is a dual command -- | ||||
| // Cypress.Commands.add('dismiss', { prevSubject: 'optional'}, (subject, options) => { ... }) | ||||
| // | ||||
| // | ||||
| // -- This will overwrite an existing command -- | ||||
| // Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... }) | ||||
							
								
								
									
										20
									
								
								cypress/support/e2e.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,20 @@ | ||||
| // *********************************************************** | ||||
| // This example support/e2e.js is processed and | ||||
| // loaded automatically before your test files. | ||||
| // | ||||
| // This is a great place to put global configuration and | ||||
| // behavior that modifies Cypress. | ||||
| // | ||||
| // You can change the location of this file or turn off | ||||
| // automatically serving support files with the | ||||
| // 'supportFile' configuration option. | ||||
| // | ||||
| // You can read more here: | ||||
| // https://on.cypress.io/configuration | ||||
| // *********************************************************** | ||||
|  | ||||
| // Import commands.js using ES2015 syntax: | ||||
| import './commands' | ||||
|  | ||||
| // Alternatively you can use CommonJS syntax: | ||||
| // require('./commands') | ||||
							
								
								
									
										
											BIN
										
									
								
								images/changelog/unknown.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 797 B | 
							
								
								
									
										
											BIN
										
									
								
								images/del.png
									
									
									
									
									
								
							
							
						
						| Before Width: | Height: | Size: 433 B After Width: | Height: | Size: 318 B | 
							
								
								
									
										
											BIN
										
									
								
								images/druid.png
									
									
									
									
									
								
							
							
						
						| Before Width: | Height: | Size: 38 KiB After Width: | Height: | Size: 10 KiB | 
							
								
								
									
										
											BIN
										
									
								
								images/edit.png
									
									
									
									
									
								
							
							
						
						| Before Width: | Height: | Size: 450 B After Width: | Height: | Size: 363 B | 
							
								
								
									
										
											BIN
										
									
								
								images/error.ico
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 4.2 KiB | 
							
								
								
									
										
											BIN
										
									
								
								images/error.png
									
									
									
									
									
								
							
							
						
						| Before Width: | Height: | Size: 706 B After Width: | Height: | Size: 592 B | 
							
								
								
									
										
											BIN
										
									
								
								images/false.png
									
									
									
									
									
								
							
							
						
						| Before Width: | Height: | Size: 1004 B After Width: | Height: | Size: 845 B | 
| Before Width: | Height: | Size: 122 KiB After Width: | Height: | Size: 122 KiB | 
| Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 14 KiB | 
							
								
								
									
										
											BIN
										
									
								
								images/global/general/blank.gif
									
									
									
									
									
										Executable file
									
								
							
							
						
						| After Width: | Height: | Size: 71 B | 
							
								
								
									
										
											BIN
										
									
								
								images/global/general/box-bottom.gif
									
									
									
									
									
										Executable file
									
								
							
							
						
						| After Width: | Height: | Size: 2.0 KiB | 
							
								
								
									
										
											BIN
										
									
								
								images/global/general/box-top.gif
									
									
									
									
									
										Executable file
									
								
							
							
						
						| After Width: | Height: | Size: 2.0 KiB | 
							
								
								
									
										
											BIN
										
									
								
								images/global/general/chain.gif
									
									
									
									
									
										Executable file
									
								
							
							
						
						| After Width: | Height: | Size: 845 B | 
							
								
								
									
										
											BIN
										
									
								
								images/global/general/favicon.ico
									
									
									
									
									
										Executable file
									
								
							
							
						
						| After Width: | Height: | Size: 3.6 KiB | 
							
								
								
									
										
											BIN
										
									
								
								images/global/general/hide.gif
									
									
									
									
									
										Executable file
									
								
							
							
						
						| After Width: | Height: | Size: 469 B | 
							
								
								
									
										
											BIN
										
									
								
								images/global/general/minus.gif
									
									
									
									
									
										Executable file
									
								
							
							
						
						| After Width: | Height: | Size: 224 B | 
							
								
								
									
										
											BIN
										
									
								
								images/global/general/nok.gif
									
									
									
									
									
										Executable file
									
								
							
							
						
						| After Width: | Height: | Size: 117 B | 
							
								
								
									
										
											BIN
										
									
								
								images/global/general/ok.gif
									
									
									
									
									
										Executable file
									
								
							
							
						
						| After Width: | Height: | Size: 113 B | 
							
								
								
									
										
											BIN
										
									
								
								images/global/general/plus.gif
									
									
									
									
									
										Executable file
									
								
							
							
						
						| After Width: | Height: | Size: 224 B | 
							
								
								
									
										
											BIN
										
									
								
								images/global/general/show.gif
									
									
									
									
									
										Executable file
									
								
							
							
						
						| After Width: | Height: | Size: 681 B | 
							
								
								
									
										
											BIN
										
									
								
								images/hist.png
									
									
									
									
									
								
							
							
						
						| Before Width: | Height: | Size: 117 B After Width: | Height: | Size: 110 B | 
							
								
								
									
										
											BIN
										
									
								
								images/icons/comment_add.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 530 B | 
							
								
								
									
										
											BIN
										
									
								
								images/info.png
									
									
									
									
									
								
							
							
						
						| Before Width: | Height: | Size: 783 B After Width: | Height: | Size: 631 B | 
							
								
								
									
										
											BIN
										
									
								
								images/items/empty.gif
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 1.8 KiB |