@@ -0,0 +1,57 @@ | |||
# AnonIB 3D by Alex Krunch | |||
![Screenshot](https://pbs.twimg.com/media/D9Hjo53W4AUguEy.jpg) | |||
This project is a prototype for a 3D anonymous imageboard. The goal is to use the video game structure an abstraction layer to minimize censorship. Full project running here: https://3dchan.net | |||
## Software | |||
The project use Angular >6 and PHP > 5. It also use the libraries BabylonJS for the 3D and LazerDB for JSON database. | |||
[BabylonJS](https://github.com/BabylonJS/Babylon.js/tree/master/dist) | |||
[LazerDB](https://github.com/Greg0/Lazer-Database) | |||
## Installation | |||
**1/ Drag and drop the content at the _/ready2use/_ at the root of your server.** | |||
If you want to add AnonIB 3D to a subfolder, you will need to recompile the Angular project using this build command: | |||
```bash | |||
ng build --prod --base-href=/path-to-subfolder/ | |||
``` | |||
Add this .htaccess, modify _path-to-sub-folder_, and place it at the root of your sub-folder. | |||
```bash | |||
RewriteEngine on | |||
RewriteCond %{REQUEST_FILENAME} -s [OR] | |||
RewriteCond %{REQUEST_FILENAME} -l [OR] | |||
RewriteCond %{REQUEST_FILENAME} -d | |||
RewriteRule ^.*$ - [NC,L] | |||
RewriteRule ^(srv|user)($|/) - [L] | |||
RewriteRule ^(.*) /path-to-sub-folder/index.html [NC,L] | |||
``` | |||
Don't forget to add the content of _/src_php/_ in _/path-to-sub-folder/srv/_ | |||
**2/ Add you own custom map list** | |||
Go to _/php/MapController.php_ and add and suppress a new line. Use only characters allowed in Url for the board name. | |||
```bash | |||
array_push($levelToPlace, new Level("newmap", 15, 13, true, true) ); | |||
``` | |||
**3/Initialize the admin password + the DB** | |||
Go to _/srv/php/admin.php_ | |||
Type the you password in the field | |||
Click on Set password | |||
To re-init the password go to _/php/password/password.txt_ and erase the file | |||
After this erase database + posts and maps if they already exist and click Init the database + Init Map and Posts | |||
**4/Access to the admin** | |||
Go to _/admin_ , type your password and click on New user or Existing user. | |||
You know have access to the admin. Click on the Launch the Admin. | |||
Posts is to review , delete or ban user. | |||
Map is to change map. At the top you got a selector to choose the chan of the map, and at the bottom you got a selector for the type of tile you want to use. | |||
## Project status | |||
I paused the project due to my personal situation. There all you need in the code to activate the image upload, but security flows in it are highly probable. | |||
## Support | |||
For any question or problem contact me by mail (monsieur.krunch@gmail.com) or on Twitter (https://twitter.com/alexkrunch) | |||
## License | |||
[MIT](https://choosealicense.com/licenses/mit/) |
@@ -0,0 +1,58 @@ | |||
[ | |||
{ | |||
"url":"https://amzn.to/2VUOerv", | |||
"picture":"https://i.pinimg.com/originals/6b/7c/fa/6b7cfa7ca8acb25025f5bf7ea0056e92.jpg", | |||
"name":"Reçois le livre le très bon \"Sonny 60 years Hells Angels \" chez toi demain!", | |||
"desc":"Un super bouquins d'illustration sur les hells angels des années 60!", | |||
"chan": "alpha", | |||
"loc": "fr" | |||
}, | |||
{ | |||
"url":"https://amzn.to/2YSwn6B", | |||
"picture":"./assets/amaz/come_get_it.jpg", | |||
"name":"Get this book \"Come and Take It \" by the guy who 3D printed a 🔫, Cody Wilson!", | |||
"desc":"Come and Take It", | |||
"chan": "alpha", | |||
"loc": "us" | |||
}, | |||
{ | |||
"url":"https://amzn.to/2K9wu9U", | |||
"picture":"https://images-na.ssl-images-amazon.com/images/I/41qdCTNSp8L._SX330_BO1,204,203,200_.jpg", | |||
"name":"Get this book \"Radicals \" on crypto anarchism at home tomorow!", | |||
"desc":"An awesome book on crypto anarchism", | |||
"chan": "alpha", | |||
"loc": "us" | |||
}, | |||
{ | |||
"url":"https://amzn.to/2EAtkZg", | |||
"picture":"./assets/amaz/dark_net.webp", | |||
"name":"Get the only good book on the \"Dark Net\" exploring the topic in depth.", | |||
"desc":"An awesome book on crypto anarchism", | |||
"chan": "alpha", | |||
"loc": "us" | |||
}, | |||
{ | |||
"url":"https://amzn.to/2QsNIAf", | |||
"picture":"./assets/amaz/joker_leto.jpg", | |||
"name":"🤡 to LIVE IN A SOCIETY, get this. At your home tomorrow", | |||
"desc":"Jared Leto's joker", | |||
"chan": "alpha", | |||
"loc": "us" | |||
}, | |||
{ | |||
"url":"https://amzn.to/2W9L2NZ", | |||
"picture":"https://images-na.ssl-images-amazon.com/images/I/61znu9JU9IL._UY445_.jpg", | |||
"name":"No GF? Become the GF with this sailor uniform! Get it Tomorow!", | |||
"desc":"A very sailor uniform cosplay.", | |||
"chan": "alpha", | |||
"loc": "us" | |||
}, | |||
{ | |||
"url":"https://amzn.to/2QAxzJ7", | |||
"picture":"./assets/amaz/joker_nolan.jpg", | |||
"name":"🤡 13% of the population but 53% of the crime. By Nendoroid", | |||
"desc":"Christopher Nolan's joker", | |||
"chan": "alpha", | |||
"loc": "us" | |||
} | |||
] |
@@ -0,0 +1,139 @@ | |||
{ "height":14, | |||
"layers":[ | |||
{ | |||
"data":[2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 2, 2, 1, 1, 2, 1, 1, 1, 1, 1, 2, 1, 193, 1, 1, 2, 1, 1, 2, 2, 1, 1, 2, 1, 1, 1, 1, 1, 2, 1, 2, 1, 1, 2, 1, 1, 2, 2, 1, 1, 2, 1, 1, 1, 1, 1, 2, 1, 2, 1, 1, 2, 1, 1, 2, 2, 1, 1, 2, 1, 1, 1, 1, 1, 2, 1, 2, 1, 1, 2, 1, 1, 2, 2, 1, 1, 2, 2, 2, 193, 2, 2, 2, 2, 2, 1, 1, 2, 1, 1, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 2, 1, 1, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 2, 1, 1, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 194, 1, 1, 221, 1, 1, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2], | |||
"height":14, | |||
"name":"decors1", | |||
"opacity":1, | |||
"type":"tilelayer", | |||
"visible":true, | |||
"width":18, | |||
"x":0, | |||
"y":0 | |||
}, | |||
{ | |||
"draworder":"topdown", | |||
"height":0, | |||
"name":"characters", | |||
"objects":[ | |||
{ | |||
"height":32, | |||
"id":1, | |||
"name":"playerstart", | |||
"rotation":0, | |||
"type":"", | |||
"visible":true, | |||
"width":32, | |||
"x":189, | |||
"y":144 | |||
}, | |||
{ | |||
"height":32, | |||
"id":2, | |||
"name":"anon", | |||
"rotation":0, | |||
"type":"", | |||
"visible":true, | |||
"width":32, | |||
"x":129, | |||
"y":354 | |||
}, | |||
{ | |||
"height":32, | |||
"id":3, | |||
"name":"anon", | |||
"rotation":0, | |||
"type":"", | |||
"visible":true, | |||
"width":32, | |||
"x":384, | |||
"y":160 | |||
}, | |||
{ | |||
"height":32, | |||
"id":4, | |||
"name":"anon", | |||
"rotation":0, | |||
"type":"", | |||
"visible":true, | |||
"width":32, | |||
"x":417, | |||
"y":160 | |||
}], | |||
"opacity":1, | |||
"type":"objectgroup", | |||
"visible":true, | |||
"width":0, | |||
"x":0, | |||
"y":0 | |||
}, | |||
{ | |||
"draworder":"topdown", | |||
"height":0, | |||
"name":"objects", | |||
"objects":[ | |||
{ | |||
"height":19, | |||
"id":7, | |||
"name":"dick", | |||
"rotation":0, | |||
"type":"", | |||
"visible":true, | |||
"width":21, | |||
"x":197, | |||
"y":361 | |||
}, | |||
{ | |||
"height":19, | |||
"id":8, | |||
"name":"sunglasses", | |||
"rotation":0, | |||
"type":"", | |||
"visible":true, | |||
"width":18, | |||
"x":326, | |||
"y":199 | |||
}], | |||
"opacity":1, | |||
"type":"objectgroup", | |||
"visible":true, | |||
"width":0, | |||
"x":0, | |||
"y":0 | |||
}, | |||
{ | |||
"draworder":"topdown", | |||
"height":14, | |||
"name":"gates", | |||
"objects":[ | |||
{ | |||
"height":27, | |||
"id":9, | |||
"name":"level2", | |||
"rotation":0, | |||
"type":"", | |||
"visible":true, | |||
"width":30, | |||
"x":47, | |||
"y":9 | |||
}], | |||
"opacity":1, | |||
"type":"objectgroup", | |||
"visible":true, | |||
"width":18, | |||
"x":0, | |||
"y":0 | |||
}], | |||
"nextobjectid":12, | |||
"orientation":"orthogonal", | |||
"renderorder":"left-down", | |||
"tileheight":32, | |||
"tilesets":[ | |||
{ | |||
"firstgid":1, | |||
"source":"..\/..\/..\/tilemap\/tile-set-dungeon.tsx" | |||
}], | |||
"tilewidth":32, | |||
"version":1, | |||
"width":18 | |||
} |
@@ -0,0 +1,94 @@ | |||
{ "height":30, | |||
"layers":[ | |||
{ | |||
"data":[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 1, 1, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 1, 1, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 1, 1, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 1, 1, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 1, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 1, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 1, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 1, 1, 1, 1, 1, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 2, 1, 2, 1, 2, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 1, 1, 1, 1, 1, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 2, 1, 2, 1, 2, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 1, 1, 1, 1, 1, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 1, 2, 1, 2, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 1, 1, 1, 1, 1, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 221, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], | |||
"height":30, | |||
"name":"decors1", | |||
"opacity":0.300000011920929, | |||
"type":"tilelayer", | |||
"visible":true, | |||
"width":30, | |||
"x":0, | |||
"y":0 | |||
}, | |||
{ | |||
"data":[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 2, 0, 2, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 2, 0, 2, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 2, 0, 2, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 2, 0, 2, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 2, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 2, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 2, 1, 1, 2, 1, 1, 2, 2, 2, 1, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 2, 1, 1, 2, 1, 1, 2, 1, 1, 1, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 2, 1, 1, 2, 1, 1, 2, 1, 1, 1, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 2, 1, 1, 1, 1, 1, 2, 1, 1, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 2, 1, 1, 1, 1, 1, 2, 1, 1, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 2, 0, 0, 0, 0, 0, 0, 2, 1, 1, 1, 2, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 2, 1, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0], | |||
"height":30, | |||
"name":"decors2", | |||
"opacity":1, | |||
"type":"tilelayer", | |||
"visible":true, | |||
"width":30, | |||
"x":0, | |||
"y":0 | |||
}, | |||
{ | |||
"draworder":"topdown", | |||
"height":0, | |||
"name":"characters", | |||
"objects":[ | |||
{ | |||
"height":32, | |||
"id":1, | |||
"name":"playerstart", | |||
"rotation":0, | |||
"type":"", | |||
"visible":true, | |||
"width":32, | |||
"x":398, | |||
"y":80 | |||
}, | |||
{ | |||
"height":32, | |||
"id":2, | |||
"name":"anon", | |||
"rotation":0, | |||
"type":"", | |||
"visible":true, | |||
"width":32, | |||
"x":352, | |||
"y":670 | |||
}, | |||
{ | |||
"height":32, | |||
"id":9, | |||
"name":"anon", | |||
"rotation":0, | |||
"type":"", | |||
"visible":true, | |||
"width":32, | |||
"x":355, | |||
"y":607 | |||
}], | |||
"opacity":1, | |||
"type":"objectgroup", | |||
"visible":true, | |||
"width":0, | |||
"x":0, | |||
"y":0 | |||
}, | |||
{ | |||
"draworder":"topdown", | |||
"height":0, | |||
"name":"objects", | |||
"objects":[], | |||
"opacity":1, | |||
"type":"objectgroup", | |||
"visible":true, | |||
"width":0, | |||
"x":0, | |||
"y":0 | |||
}], | |||
"nextobjectid":10, | |||
"orientation":"orthogonal", | |||
"renderorder":"left-down", | |||
"tileheight":32, | |||
"tilesets":[ | |||
{ | |||
"firstgid":1, | |||
"source":"..\/..\/..\/tilemap\/tile-set-dungeon.tsx" | |||
}], | |||
"tilewidth":32, | |||
"version":1, | |||
"width":30 | |||
} |
@@ -0,0 +1,128 @@ | |||
{ "height":14, | |||
"layers":[ | |||
{ | |||
"data":[2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 2, 2, 1, 1, 2, 1, 1, 1, 1, 1, 2, 1, 193, 1, 1, 2, 1, 1, 2, 2, 1, 1, 2, 1, 1, 1, 1, 1, 2, 1, 2, 1, 1, 2, 1, 1, 2, 2, 1, 1, 2, 1, 1, 1, 1, 1, 2, 1, 2, 1, 1, 2, 1, 1, 2, 2, 1, 1, 2, 1, 1, 1, 1, 1, 2, 1, 2, 1, 1, 2, 1, 1, 2, 2, 1, 1, 2, 2, 2, 193, 2, 2, 2, 2, 2, 1, 1, 2, 1, 1, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 2, 1, 1, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 194, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2], | |||
"height":14, | |||
"name":"decors1", | |||
"opacity":1, | |||
"type":"tilelayer", | |||
"visible":true, | |||
"width":18, | |||
"x":0, | |||
"y":0 | |||
}, | |||
{ | |||
"draworder":"topdown", | |||
"height":0, | |||
"name":"characters", | |||
"objects":[ | |||
{ | |||
"height":32, | |||
"id":1, | |||
"name":"playerstart", | |||
"rotation":0, | |||
"type":"", | |||
"visible":true, | |||
"width":32, | |||
"x":189, | |||
"y":144 | |||
}, | |||
{ | |||
"height":32, | |||
"id":3, | |||
"name":"anon", | |||
"rotation":0, | |||
"type":"", | |||
"visible":true, | |||
"width":32, | |||
"x":384, | |||
"y":160 | |||
}, | |||
{ | |||
"height":32, | |||
"id":4, | |||
"name":"anon", | |||
"rotation":0, | |||
"type":"", | |||
"visible":true, | |||
"width":32, | |||
"x":417, | |||
"y":160 | |||
}], | |||
"opacity":1, | |||
"type":"objectgroup", | |||
"visible":true, | |||
"width":0, | |||
"x":0, | |||
"y":0 | |||
}, | |||
{ | |||
"draworder":"topdown", | |||
"height":0, | |||
"name":"objects", | |||
"objects":[], | |||
"opacity":1, | |||
"type":"objectgroup", | |||
"visible":true, | |||
"width":0, | |||
"x":0, | |||
"y":0 | |||
}, | |||
{ | |||
"draworder":"topdown", | |||
"height":0, | |||
"name":"gates", | |||
"objects":[ | |||
{ | |||
"height":19, | |||
"id":9, | |||
"name":"room5", | |||
"rotation":0, | |||
"type":"", | |||
"visible":true, | |||
"width":20, | |||
"x":54, | |||
"y":56 | |||
}, | |||
{ | |||
"height":18.5, | |||
"id":12, | |||
"name":"room2", | |||
"rotation":0, | |||
"type":"", | |||
"visible":true, | |||
"width":19, | |||
"x":55, | |||
"y":374 | |||
}, | |||
{ | |||
"height":20.5, | |||
"id":13, | |||
"name":"room3", | |||
"rotation":0, | |||
"type":"", | |||
"visible":true, | |||
"width":21, | |||
"x":325, | |||
"y":196.5 | |||
}], | |||
"opacity":1, | |||
"type":"objectgroup", | |||
"visible":true, | |||
"width":0, | |||
"x":0, | |||
"y":0 | |||
}], | |||
"nextobjectid":17, | |||
"orientation":"orthogonal", | |||
"renderorder":"left-down", | |||
"tileheight":32, | |||
"tilesets":[ | |||
{ | |||
"firstgid":1, | |||
"source":"..\/..\/..\/tilemap\/tile-set-dungeon.tsx" | |||
}], | |||
"tilewidth":32, | |||
"version":1, | |||
"width":18 | |||
} |
@@ -0,0 +1,106 @@ | |||
{ "height":14, | |||
"layers":[ | |||
{ | |||
"data":[2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 2, 2, 1, 1, 2, 2, 2, 2, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 2, 1, 1, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 2, 2, 2, 2, 1, 1, 1, 2, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 1, 2, 2, 1, 1, 1, 1, 2, 1, 1, 1, 66, 1, 2, 2, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 2, 2, 1, 1, 2, 2, 2, 2, 1, 1, 1, 1, 2, 2, 2, 2, 1, 66, 2, 2, 1, 1, 2, 1, 1, 2, 1, 1, 1, 1, 2, 1, 1, 1, 66, 1, 2, 2, 1, 1, 2, 2, 2, 2, 2, 2, 194, 2, 2, 66, 66, 66, 2, 1, 2, 2, 1, 1, 1, 1, 1, 1, 1, 66, 1, 1, 1, 1, 2, 66, 66, 1, 2, 2, 1, 1, 2, 2, 1, 1, 1, 1, 1, 66, 1, 66, 66, 66, 66, 66, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2], | |||
"height":14, | |||
"name":"decors1", | |||
"opacity":1, | |||
"type":"tilelayer", | |||
"visible":true, | |||
"width":18, | |||
"x":0, | |||
"y":0 | |||
}, | |||
{ | |||
"draworder":"topdown", | |||
"height":0, | |||
"name":"characters", | |||
"objects":[ | |||
{ | |||
"height":22, | |||
"id":17, | |||
"name":"anon", | |||
"rotation":0, | |||
"type":"", | |||
"visible":true, | |||
"width":21, | |||
"x":279, | |||
"y":180 | |||
}], | |||
"opacity":1, | |||
"type":"objectgroup", | |||
"visible":true, | |||
"width":0, | |||
"x":0, | |||
"y":0 | |||
}, | |||
{ | |||
"draworder":"topdown", | |||
"height":0, | |||
"name":"objects", | |||
"objects":[ | |||
{ | |||
"height":20, | |||
"id":18, | |||
"name":"Upload Ring", | |||
"rotation":0, | |||
"type":"ring", | |||
"visible":true, | |||
"width":21, | |||
"x":280, | |||
"y":218 | |||
}], | |||
"opacity":1, | |||
"type":"objectgroup", | |||
"visible":true, | |||
"width":0, | |||
"x":0, | |||
"y":0 | |||
}, | |||
{ | |||
"draworder":"topdown", | |||
"height":0, | |||
"name":"gates", | |||
"objects":[ | |||
{ | |||
"height":19, | |||
"id":9, | |||
"name":"room1", | |||
"rotation":0, | |||
"type":"", | |||
"visible":true, | |||
"width":23, | |||
"x":53, | |||
"y":57 | |||
}, | |||
{ | |||
"height":15.5, | |||
"id":13, | |||
"name":"room3", | |||
"rotation":0, | |||
"type":"", | |||
"visible":true, | |||
"width":19, | |||
"x":501, | |||
"y":55.5 | |||
}], | |||
"opacity":1, | |||
"type":"objectgroup", | |||
"visible":true, | |||
"width":0, | |||
"x":0, | |||
"y":0 | |||
}], | |||
"nextobjectid":19, | |||
"orientation":"orthogonal", | |||
"renderorder":"left-down", | |||
"tileheight":32, | |||
"tilesets":[ | |||
{ | |||
"firstgid":1, | |||
"source":"..\/..\/..\/tilemap\/tile-set-dungeon.tsx" | |||
}], | |||
"tilewidth":32, | |||
"version":1, | |||
"width":18 | |||
} |
@@ -0,0 +1,95 @@ | |||
{ "height":14, | |||
"layers":[ | |||
{ | |||
"data":[2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 1, 1, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 1, 1, 1, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 2, 1, 1, 1, 1, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 2, 0, 0, 2, 1, 1, 1, 1, 1, 1, 1, 41, 1, 1, 1, 1, 1, 1, 2, 0, 0, 2, 1, 1, 1, 1, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 2, 0, 0, 2, 1, 1, 1, 1, 2, 0, 0, 2, 1, 1, 1, 1, 1, 1, 2, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 2, 0, 0, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 0, 0, 0, 0, 0, 0, 2, 1, 1, 1, 1, 1, 1, 2, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 1, 1, 1, 1, 1, 41, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 1, 1, 1, 1, 1, 2, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0], | |||
"height":14, | |||
"name":"decors1", | |||
"opacity":1, | |||
"type":"tilelayer", | |||
"visible":true, | |||
"width":18, | |||
"x":0, | |||
"y":0 | |||
}, | |||
{ | |||
"draworder":"topdown", | |||
"height":0, | |||
"name":"characters", | |||
"objects":[], | |||
"opacity":1, | |||
"type":"objectgroup", | |||
"visible":true, | |||
"width":0, | |||
"x":0, | |||
"y":0 | |||
}, | |||
{ | |||
"draworder":"topdown", | |||
"height":0, | |||
"name":"objects", | |||
"objects":[], | |||
"opacity":1, | |||
"type":"objectgroup", | |||
"visible":true, | |||
"width":0, | |||
"x":0, | |||
"y":0 | |||
}, | |||
{ | |||
"draworder":"topdown", | |||
"height":0, | |||
"name":"gates", | |||
"objects":[ | |||
{ | |||
"height":18, | |||
"id":9, | |||
"name":"room1", | |||
"rotation":0, | |||
"type":"", | |||
"visible":true, | |||
"width":21, | |||
"x":42, | |||
"y":261 | |||
}, | |||
{ | |||
"height":19.5, | |||
"id":13, | |||
"name":"room2", | |||
"rotation":0, | |||
"type":"", | |||
"visible":true, | |||
"width":19, | |||
"x":390, | |||
"y":382 | |||
}, | |||
{ | |||
"height":19.5, | |||
"id":17, | |||
"name":"room5", | |||
"rotation":0, | |||
"type":"", | |||
"visible":true, | |||
"width":20, | |||
"x":385, | |||
"y":116.5 | |||
}], | |||
"opacity":1, | |||
"type":"objectgroup", | |||
"visible":true, | |||
"width":0, | |||
"x":0, | |||
"y":0 | |||
}], | |||
"nextobjectid":19, | |||
"orientation":"orthogonal", | |||
"renderorder":"left-down", | |||
"tileheight":32, | |||
"tilesets":[ | |||
{ | |||
"firstgid":1, | |||
"source":"..\/..\/..\/tilemap\/tile-set-dungeon.tsx" | |||
}], | |||
"tilewidth":32, | |||
"version":1, | |||
"width":18 | |||
} |
@@ -0,0 +1,84 @@ | |||
{ "height":14, | |||
"layers":[ | |||
{ | |||
"data":[2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 0, 0, 0, 0, 0, 0, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 2, 1, 1, 1, 1, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 1, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 1, 2, 2, 0, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 0, 0, 2, 1, 2, 0, 0, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 0, 2, 2, 41, 2, 2, 0, 2, 1, 1, 1, 1, 2, 194, 2, 1, 1, 2, 0, 2, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1, 1, 1, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 2, 2, 1, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 1, 1, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2], | |||
"height":14, | |||
"name":"decors1", | |||
"opacity":1, | |||
"type":"tilelayer", | |||
"visible":true, | |||
"width":18, | |||
"x":0, | |||
"y":0 | |||
}, | |||
{ | |||
"draworder":"topdown", | |||
"height":0, | |||
"name":"characters", | |||
"objects":[], | |||
"opacity":1, | |||
"type":"objectgroup", | |||
"visible":true, | |||
"width":0, | |||
"x":0, | |||
"y":0 | |||
}, | |||
{ | |||
"draworder":"topdown", | |||
"height":0, | |||
"name":"objects", | |||
"objects":[], | |||
"opacity":1, | |||
"type":"objectgroup", | |||
"visible":true, | |||
"width":0, | |||
"x":0, | |||
"y":0 | |||
}, | |||
{ | |||
"draworder":"topdown", | |||
"height":0, | |||
"name":"gates", | |||
"objects":[ | |||
{ | |||
"height":19, | |||
"id":9, | |||
"name":"room1", | |||
"rotation":0, | |||
"type":"", | |||
"visible":true, | |||
"width":20, | |||
"x":54, | |||
"y":373 | |||
}, | |||
{ | |||
"height":17.5, | |||
"id":13, | |||
"name":"room3", | |||
"rotation":0, | |||
"type":"", | |||
"visible":true, | |||
"width":20, | |||
"x":482, | |||
"y":361 | |||
}], | |||
"opacity":1, | |||
"type":"objectgroup", | |||
"visible":true, | |||
"width":0, | |||
"x":0, | |||
"y":0 | |||
}], | |||
"nextobjectid":19, | |||
"orientation":"orthogonal", | |||
"renderorder":"left-down", | |||
"tileheight":32, | |||
"tilesets":[ | |||
{ | |||
"firstgid":1, | |||
"source":"..\/..\/..\/tilemap\/tile-set-dungeon.tsx" | |||
}], | |||
"tilewidth":32, | |||
"version":1, | |||
"width":18 | |||
} |
@@ -0,0 +1,24 @@ | |||
<!doctype html> | |||
<html lang="en"> | |||
<head> | |||
<meta charset="utf-8"> | |||
<meta property="og:image" content="http://snuffchan.com/dungeon/assets/img/preview.jpeg"> | |||
<title>AnonIB💀3D</title> | |||
<meta name="description" content="Snuffchan is the very first anonymous imageboard sharing video game, in 3D, fully running in the web browser, and this without any form of subricption."> | |||
<base href="/"> | |||
<meta name="viewport" content="width=device-width, initial-scale=1"> | |||
<link rel="icon" type="image/x-icon" href="favicon.ico"> | |||
<script src="https://code.jquery.com/pep/0.4.3/pep.js"></script> | |||
</head> | |||
<body> | |||
<div class="wrapper"> | |||
<main> | |||
<app-root></app-root> | |||
</main> | |||
</div> | |||
<script type="text/javascript" src="runtime.js"></script><script type="text/javascript" src="polyfills.js"></script><script type="text/javascript" src="styles.js"></script><script type="text/javascript" src="vendor.js"></script><script type="text/javascript" src="main.js"></script></body> | |||
</html> |
@@ -0,0 +1,154 @@ | |||
/******/ (function(modules) { // webpackBootstrap | |||
/******/ // install a JSONP callback for chunk loading | |||
/******/ function webpackJsonpCallback(data) { | |||
/******/ var chunkIds = data[0]; | |||
/******/ var moreModules = data[1]; | |||
/******/ var executeModules = data[2]; | |||
/******/ | |||
/******/ // add "moreModules" to the modules object, | |||
/******/ // then flag all "chunkIds" as loaded and fire callback | |||
/******/ var moduleId, chunkId, i = 0, resolves = []; | |||
/******/ for(;i < chunkIds.length; i++) { | |||
/******/ chunkId = chunkIds[i]; | |||
/******/ if(installedChunks[chunkId]) { | |||
/******/ resolves.push(installedChunks[chunkId][0]); | |||
/******/ } | |||
/******/ installedChunks[chunkId] = 0; | |||
/******/ } | |||
/******/ for(moduleId in moreModules) { | |||
/******/ if(Object.prototype.hasOwnProperty.call(moreModules, moduleId)) { | |||
/******/ modules[moduleId] = moreModules[moduleId]; | |||
/******/ } | |||
/******/ } | |||
/******/ if(parentJsonpFunction) parentJsonpFunction(data); | |||
/******/ | |||
/******/ while(resolves.length) { | |||
/******/ resolves.shift()(); | |||
/******/ } | |||
/******/ | |||
/******/ // add entry modules from loaded chunk to deferred list | |||
/******/ deferredModules.push.apply(deferredModules, executeModules || []); | |||
/******/ | |||
/******/ // run deferred modules when all chunks ready | |||
/******/ return checkDeferredModules(); | |||
/******/ }; | |||
/******/ function checkDeferredModules() { | |||
/******/ var result; | |||
/******/ for(var i = 0; i < deferredModules.length; i++) { | |||
/******/ var deferredModule = deferredModules[i]; | |||
/******/ var fulfilled = true; | |||
/******/ for(var j = 1; j < deferredModule.length; j++) { | |||
/******/ var depId = deferredModule[j]; | |||
/******/ if(installedChunks[depId] !== 0) fulfilled = false; | |||
/******/ } | |||
/******/ if(fulfilled) { | |||
/******/ deferredModules.splice(i--, 1); | |||
/******/ result = __webpack_require__(__webpack_require__.s = deferredModule[0]); | |||
/******/ } | |||
/******/ } | |||
/******/ return result; | |||
/******/ } | |||
/******/ | |||
/******/ // The module cache | |||
/******/ var installedModules = {}; | |||
/******/ | |||
/******/ // object to store loaded and loading chunks | |||
/******/ // undefined = chunk not loaded, null = chunk preloaded/prefetched | |||
/******/ // Promise = chunk loading, 0 = chunk loaded | |||
/******/ var installedChunks = { | |||
/******/ "runtime": 0 | |||
/******/ }; | |||
/******/ | |||
/******/ var deferredModules = []; | |||
/******/ | |||
/******/ // The require function | |||
/******/ function __webpack_require__(moduleId) { | |||
/******/ | |||
/******/ // Check if module is in cache | |||
/******/ if(installedModules[moduleId]) { | |||
/******/ return installedModules[moduleId].exports; | |||
/******/ } | |||
/******/ // Create a new module (and put it into the cache) | |||
/******/ var module = installedModules[moduleId] = { | |||
/******/ i: moduleId, | |||
/******/ l: false, | |||
/******/ exports: {} | |||
/******/ }; | |||
/******/ | |||
/******/ // Execute the module function | |||
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); | |||
/******/ | |||
/******/ // Flag the module as loaded | |||
/******/ module.l = true; | |||
/******/ | |||
/******/ // Return the exports of the module | |||
/******/ return module.exports; | |||
/******/ } | |||
/******/ | |||
/******/ | |||
/******/ // expose the modules object (__webpack_modules__) | |||
/******/ __webpack_require__.m = modules; | |||
/******/ | |||
/******/ // expose the module cache | |||
/******/ __webpack_require__.c = installedModules; | |||
/******/ | |||
/******/ // define getter function for harmony exports | |||
/******/ __webpack_require__.d = function(exports, name, getter) { | |||
/******/ if(!__webpack_require__.o(exports, name)) { | |||
/******/ Object.defineProperty(exports, name, { enumerable: true, get: getter }); | |||
/******/ } | |||
/******/ }; | |||
/******/ | |||
/******/ // define __esModule on exports | |||
/******/ __webpack_require__.r = function(exports) { | |||
/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { | |||
/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); | |||
/******/ } | |||
/******/ Object.defineProperty(exports, '__esModule', { value: true }); | |||
/******/ }; | |||
/******/ | |||
/******/ // create a fake namespace object | |||
/******/ // mode & 1: value is a module id, require it | |||
/******/ // mode & 2: merge all properties of value into the ns | |||
/******/ // mode & 4: return value when already ns object | |||
/******/ // mode & 8|1: behave like require | |||
/******/ __webpack_require__.t = function(value, mode) { | |||
/******/ if(mode & 1) value = __webpack_require__(value); | |||
/******/ if(mode & 8) return value; | |||
/******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value; | |||
/******/ var ns = Object.create(null); | |||
/******/ __webpack_require__.r(ns); | |||
/******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value }); | |||
/******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key)); | |||
/******/ return ns; | |||
/******/ }; | |||
/******/ | |||
/******/ // getDefaultExport function for compatibility with non-harmony modules | |||
/******/ __webpack_require__.n = function(module) { | |||
/******/ var getter = module && module.__esModule ? | |||
/******/ function getDefault() { return module['default']; } : | |||
/******/ function getModuleExports() { return module; }; | |||
/******/ __webpack_require__.d(getter, 'a', getter); | |||
/******/ return getter; | |||
/******/ }; | |||
/******/ | |||
/******/ // Object.prototype.hasOwnProperty.call | |||
/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; | |||
/******/ | |||
/******/ // __webpack_public_path__ | |||
/******/ __webpack_require__.p = ""; | |||
/******/ | |||
/******/ var jsonpArray = window["webpackJsonp"] = window["webpackJsonp"] || []; | |||
/******/ var oldJsonpFunction = jsonpArray.push.bind(jsonpArray); | |||
/******/ jsonpArray.push = webpackJsonpCallback; | |||
/******/ jsonpArray = jsonpArray.slice(); | |||
/******/ for(var i = 0; i < jsonpArray.length; i++) webpackJsonpCallback(jsonpArray[i]); | |||
/******/ var parentJsonpFunction = oldJsonpFunction; | |||
/******/ | |||
/******/ | |||
/******/ // run deferred modules from other chunks | |||
/******/ checkDeferredModules(); | |||
/******/ }) | |||
/************************************************************************/ | |||
/******/ ([]); | |||
//# sourceMappingURL=runtime.js.map |
@@ -0,0 +1,60 @@ | |||
.post-ui-message{ | |||
padding : 10px; | |||
margin-bottom : 18px; | |||
background: rgb(189, 198, 247); | |||
border-style: solid; | |||
border-width: 1px; | |||
border-color: #a99ec7; | |||
border-radius: 5px; | |||
} | |||
div { | |||
margin-bottom: 8px; | |||
} | |||
.ascii{ | |||
display: inline-block; | |||
font-family: "Lucida Console", Monaco, monospace; | |||
} | |||
textarea | |||
{ | |||
width: 100%; | |||
margin: 0; | |||
} | |||
.post-message { | |||
padding : 10px; | |||
margin-bottom : 18px; | |||
background: rgb(228, 221, 221); | |||
border-style: solid; | |||
border-width: 1px; | |||
border-color: rgb(131, 123, 123); | |||
border-radius: 5px; | |||
} | |||
.post-torrent-info{ | |||
font-family: 'Courier New', Courier, monospace; | |||
font-size: small; | |||
padding : 8px; | |||
color: white; | |||
background:rgb(70, 61, 56); | |||
border-radius: 5px; | |||
} | |||
.post-message img { | |||
max-width: 650px; | |||
width: 100%; | |||
height: auto; | |||
} | |||
.post-message video { | |||
max-width: 650px; | |||
width: 100%; | |||
height: auto; | |||
} | |||
.post-message audio { | |||
max-width: 650px; | |||
width: 100%; | |||
} |
@@ -0,0 +1,6 @@ | |||
Options +FollowSymlinks | |||
RewriteEngine on | |||
RewriteRule ^([a-z0-9-_]+).jpeg ?name=$1.jpeg | |||
RewriteRule ^([a-z0-9-_]+).jpg ?name=$1.jpg | |||
RewriteRule ^([a-z0-9-_]+).gif ?name=$1.gif | |||
RewriteRule ^([a-z0-9-_]+).png ?name=$1.png |
@@ -0,0 +1,29 @@ | |||
<?php | |||
//Load the DB | |||
require_once "../php/Utils/Constants.php"; | |||
$uploaddir = '../php/'.Constants::CONST_IMAGE_UPLOAD_FOLDER.'/'; | |||
use Lazer\Classes\Database as Lazer; | |||
define('LAZER_DATA_PATH', '../php/'.realpath(dirname(__FILE__)).'/'.Constants::CONST_DB_FOLDER.'/'); | |||
$name = $_GET['name']; // Assuming the file name is in the URL for this example | |||
$parsed = explode("_",$name); | |||
if(count($parsed) != 2) return; | |||
$mapKey = $parsed[0].'/'; | |||
$name = $parsed[1]; | |||
$ext = pathinfo($name)['extension']; | |||
$mimeType = 'image/'.$ext; | |||
$handle = fopen($uploaddir.$mapKey.$name , "rb"); | |||
$contents = fread($handle, filesize($uploaddir.$mapKey.$name )); | |||
fclose($handle); | |||
header("content-type: image/".$ext); | |||
echo $contents; | |||
?> |
@@ -0,0 +1,30 @@ | |||
<!doctype html> | |||
<html> | |||
<head> | |||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> | |||
<title>AnonIB-3D Server</title> | |||
<!-- Required meta tags --> | |||
<meta charset="utf-8"> | |||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> | |||
<!--meta property="og:image" content="img/breadchan_preview.png"> | |||
<meta property="og:description" content="The bittorrent imageboard. Powered by Webtorrent.io"--> | |||
<!-- Bootstrap CSS --> | |||
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous"> | |||
<link rel="stylesheet" href="css/style.css" > | |||
</head> | |||
<body> | |||
<!--img src="peerchan_tilte.png"--> | |||
<div class="container"> | |||
<div class="py-5 text-center"> | |||
<h1 class="title">Welcome on AnonIB-3D server-side!</h1> | |||
</div> | |||
</body> | |||
</html> |
@@ -0,0 +1 @@ | |||
!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var r;r="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this,r.blobUtil=e()}}(function(){return function e(r,n,t){function o(u,f){if(!n[u]){if(!r[u]){var a="function"==typeof require&&require;if(!f&&a)return a(u,!0);if(i)return i(u,!0);var c=new Error("Cannot find module '"+u+"'");throw c.code="MODULE_NOT_FOUND",c}var d=n[u]={exports:{}};r[u][0].call(d.exports,function(e){var n=r[u][1][e];return o(n?n:e)},d,d.exports,e,r,n,t)}return n[u].exports}for(var i="function"==typeof require&&require,u=0;u<t.length;u++)o(t[u]);return o}({1:[function(e,r,n){"use strict";function t(e,r){return new Promise(function(n,t){var o=new Image;r&&(o.crossOrigin=r),o.onload=function(){n(o)},o.onerror=t,o.src=e})}function o(e){var r=document.createElement("canvas");r.width=e.width,r.height=e.height;var n=r.getContext("2d");return n.drawImage(e,0,0,e.width,e.height,0,0,e.width,e.height),r}function i(e,r){e=e||[],r=r||{},"string"==typeof r&&(r={type:r});try{return new Blob(e,r)}catch(i){if("TypeError"!==i.name)throw i;for(var n="undefined"!=typeof BlobBuilder?BlobBuilder:"undefined"!=typeof MSBlobBuilder?MSBlobBuilder:"undefined"!=typeof MozBlobBuilder?MozBlobBuilder:WebKitBlobBuilder,t=new n,o=0;o<e.length;o+=1)t.append(e[o]);return t.getBlob(r.type)}}function u(e){return("undefined"!=typeof URL?URL:webkitURL).createObjectURL(e)}function f(e){return("undefined"!=typeof URL?URL:webkitURL).revokeObjectURL(e)}function a(e){return new Promise(function(r,n){var t=new FileReader,o="function"==typeof t.readAsBinaryString;t.onloadend=function(){var e=t.result||"";return o?r(e):void r(w(e))},t.onerror=n,o?t.readAsBinaryString(e):t.readAsArrayBuffer(e)})}function c(e,r){var n=[v(atob(e))];return r?i(n,{type:r}):i(n)}function d(e,r){return c(btoa(e),r)}function l(e){return a(e).then(btoa)}function b(e){var r=e.match(/data:([^;]+)/)[1],n=e.replace(/^[^,]+,/,""),t=v(atob(n));return i([t],{type:r})}function y(e){return l(e).then(function(r){return"data:"+e.type+";base64,"+r})}function B(e,r,n,i){return r=r||"image/png",t(e,n).then(o).then(function(e){return e.toDataURL(r,i)})}function s(e,r,n){return"function"==typeof e.toBlob?new Promise(function(t){e.toBlob(t,r,n)}):Promise.resolve(b(e.toDataURL(r,n)))}function p(e,r,n,i){return r=r||"image/png",t(e,n).then(o).then(function(e){return s(e,r,i)})}function g(e,r){return i([e],r)}function h(e){return new Promise(function(r,n){var t=new FileReader;t.onloadend=function(){var e=t.result||new ArrayBuffer(0);r(e)},t.onerror=n,t.readAsArrayBuffer(e)})}function w(e){for(var r="",n=new Uint8Array(e),t=n.byteLength,o=-1;++o<t;)r+=String.fromCharCode(n[o]);return r}function v(e){for(var r=e.length,n=new ArrayBuffer(r),t=new Uint8Array(n),o=-1;++o<r;)t[o]=e.charCodeAt(o);return n}Object.defineProperty(n,"__esModule",{value:!0}),n.createBlob=i,n.createObjectURL=u,n.revokeObjectURL=f,n.blobToBinaryString=a,n.base64StringToBlob=c,n.binaryStringToBlob=d,n.blobToBase64String=l,n.dataURLToBlob=b,n.blobToDataURL=y,n.imgSrcToDataURL=B,n.canvasToBlob=s,n.imgSrcToBlob=p,n.arrayBufferToBlob=g,n.blobToArrayBuffer=h,n.arrayBufferToBinaryString=w,n.binaryStringToArrayBuffer=v},{}]},{},[1])(1)}); |
@@ -0,0 +1,913 @@ | |||
/* | |||
### jQuery Multiple File Selection Plugin v2.2.2 - 2016-06-16 ### | |||
* Home: http://www.fyneworks.com/jquery/multifile/ | |||
* Code: https://github.com/fyneworks/multifile | |||
* | |||
* Licensed under http://en.wikipedia.org/wiki/MIT_License | |||
*/ | |||
/*# AVOID COLLISIONS #*/ | |||
; | |||
if (window.jQuery)(function ($) { | |||
"use strict"; | |||
/*# AVOID COLLISIONS #*/ | |||
// size label function (shows kb and mb where accordingly) | |||
function sl(x) { | |||
return x > 1048576 ? (x / 1048576).toFixed(1) + 'Mb' : (x==1024?'1Mb': (x / 1024).toFixed(1) + 'Kb' ) | |||
}; | |||
// utility function to return an array of | |||
function FILE_LIST(x){ | |||
return ((x.files&&x.files.length) ? x.files : null) || [{ | |||
name: x.value, | |||
size: 0, | |||
type: ((x.value || '').match(/[^\.]+$/i) || [''])[0] | |||
}]; | |||
}; | |||
// plugin initialization | |||
$.fn.MultiFile = function (options) { | |||
if (this.length == 0) return this; // quick fail | |||
// Handle API methods | |||
if (typeof arguments[0] == 'string') { | |||
// Perform API methods on individual elements | |||
if (this.length > 1) { | |||
var args = arguments; | |||
return this.each(function () { | |||
$.fn.MultiFile.apply($(this), args); | |||
}); | |||
}; | |||
// Invoke API method handler (and return whatever it wants to return) | |||
return $.fn.MultiFile[arguments[0]].apply(this, $.makeArray(arguments).slice(1) || []); | |||
}; | |||
// Accept number | |||
if (typeof options == 'number') { | |||
options = {max: options}; | |||
}; | |||
// Initialize options for this call | |||
var options = $.extend({} /* new object */ , | |||
$.fn.MultiFile.options /* default options */ , | |||
options || {} /* just-in-time options */ | |||
); | |||
// Empty Element Fix!!! | |||
// this code will automatically intercept native form submissions | |||
// and disable empty file elements | |||
$('form') | |||
.not('MultiFile-intercepted') | |||
.addClass('MultiFile-intercepted') | |||
.submit($.fn.MultiFile.disableEmpty); | |||
//### http://plugins.jquery.com/node/1363 | |||
// utility method to integrate this plugin with others... | |||
if ($.fn.MultiFile.options.autoIntercept) { | |||
$.fn.MultiFile.intercept($.fn.MultiFile.options.autoIntercept /* array of methods to intercept */ ); | |||
$.fn.MultiFile.options.autoIntercept = null; /* only run this once */ | |||
}; | |||
// loop through each matched element | |||
this | |||
.not('.MultiFile-applied') | |||
.addClass('MultiFile-applied') | |||
.each(function () { | |||
//##################################################################### | |||
// MAIN PLUGIN FUNCTIONALITY - START | |||
//##################################################################### | |||
// BUG 1251 FIX: http://plugins.jquery.com/project/comments/add/1251 | |||
// variable group_count would repeat itself on multiple calls to the plugin. | |||
// this would cause a conflict with multiple elements | |||
// changes scope of variable to global so id will be unique over n calls | |||
window.MultiFile = (window.MultiFile || 0) + 1; | |||
var group_count = window.MultiFile; | |||
// Copy parent attributes - Thanks to Jonas Wagner | |||
// we will use this one to create new input elements | |||
var MultiFile = { | |||
e: this, | |||
E: $(this), | |||
clone: $(this).clone() | |||
}; | |||
//=== | |||
//# USE CONFIGURATION | |||
var o = $.extend({}, | |||
$.fn.MultiFile.options, | |||
options || {}, ($.metadata ? MultiFile.E.metadata() : ($.meta ? MultiFile.E.data() : null)) || {}, /* metadata options */ {} /* internals */ | |||
); | |||
// limit number of files that can be selected? | |||
if (!(o.max > 0) /*IsNull(MultiFile.max)*/ ) { | |||
o.max = MultiFile.E.attr('maxlength'); | |||
}; | |||
if (!(o.max > 0) /*IsNull(MultiFile.max)*/ ) { | |||
o.max = (String(MultiFile.e.className.match(/\b(max|limit)\-([0-9]+)\b/gi) || ['']).match(/[0-9]+/gi) || [''])[0]; | |||
if (!(o.max > 0)) o.max = -1; | |||
else o.max = String(o.max).match(/[0-9]+/gi)[0]; | |||
}; | |||
o.max = new Number(o.max); | |||
// limit extensions? | |||
o.accept = o.accept || MultiFile.E.attr('accept') || ''; | |||
if (!o.accept) { | |||
o.accept = (MultiFile.e.className.match(/\b(accept\-[\w\|]+)\b/gi)) || ''; | |||
o.accept = new String(o.accept).replace(/^(accept|ext)\-/i, ''); | |||
}; | |||
// limit total pay load size | |||
o.maxsize = o.maxsize>0?o.maxsize:null || MultiFile.E.data('maxsize') || 0; | |||
if (!(o.maxsize > 0) /*IsNull(MultiFile.maxsize)*/ ) { | |||
o.maxsize = (String(MultiFile.e.className.match(/\b(maxsize|maxload|size)\-([0-9]+)\b/gi) || ['']).match(/[0-9]+/gi) || [''])[0]; | |||
if (!(o.maxsize > 0)) o.maxsize = -1; | |||
else o.maxsize = String(o.maxsize).match(/[0-9]+/gi)[0]; | |||
}; | |||
// limit individual file size | |||
o.maxfile = o.maxfile>0?o.maxfile:null || MultiFile.E.data('maxfile') || 0; | |||
if (!(o.maxfile > 0) /*IsNull(MultiFile.maxfile)*/ ) { | |||
o.maxfile = (String(MultiFile.e.className.match(/\b(maxfile|filemax)\-([0-9]+)\b/gi) || ['']).match(/[0-9]+/gi) || [''])[0]; | |||
if (!(o.maxfile > 0)) o.maxfile = -1; | |||
else o.maxfile = String(o.maxfile).match(/[0-9]+/gi)[0]; | |||
}; | |||
//=== | |||
// size options are accepted in kylobytes, so multiple them by 1024 | |||
if(o.maxfile>1) o.maxfile = o.maxfile * 1024; | |||
if(o.maxsize>1) o.maxsize = o.maxsize * 1024; | |||
//=== | |||
// HTML5: enforce multiple selection to be enabled, except when explicitly disabled | |||
if (o.multiple !== false) { | |||
if (o.max > 1) MultiFile.E.attr('multiple', 'multiple').prop('multiple', true); | |||
} | |||
//=== | |||
// APPLY CONFIGURATION | |||
$.extend(MultiFile, o || {}); | |||
MultiFile.STRING = $.extend({}, $.fn.MultiFile.options.STRING, MultiFile.STRING); | |||
//=== | |||
//######################################### | |||
// PRIVATE PROPERTIES/METHODS | |||
$.extend(MultiFile, { | |||
n: 0, // How many elements are currently selected? | |||
slaves: [], | |||
files: [], | |||
instanceKey: MultiFile.e.id || 'MultiFile' + String(group_count), // Instance Key? | |||
generateID: function (z) { | |||
return MultiFile.instanceKey + (z > 0 ? '_F' + String(z) : ''); | |||
}, | |||
trigger: function (event, element, MultiFile, files) { | |||
var rv, handler = MultiFile[event] || MultiFile['on'+event] ; | |||
if (handler){ | |||
files = files || MultiFile.files || FILE_LIST(this); | |||
; | |||
$.each(files,function(i, file){ | |||
// execute function in element's context, so 'this' variable is current element | |||
rv = handler.apply(MultiFile.wrapper, [element, file.name, MultiFile, file]); | |||
}); | |||
return rv; | |||
}; | |||
} | |||
}); | |||
//=== | |||
// Setup dynamic regular expression for extension validation | |||
// - thanks to John-Paul Bader: http://smyck.de/2006/08/11/javascript-dynamic-regular-expresions/ | |||
if (String(MultiFile.accept).length > 1) { | |||
MultiFile.accept = MultiFile.accept.replace(/\W+/g, '|').replace(/^\W|\W$/g, ''); | |||
MultiFile.rxAccept = new RegExp('\\.(' + (MultiFile.accept ? MultiFile.accept : '') + ')$', 'gi'); | |||
}; | |||
//=== | |||
// Create wrapper to hold our file list | |||
MultiFile.wrapID = MultiFile.instanceKey;// + '_wrap'; // Wrapper ID? | |||
MultiFile.E.wrap('<div class="MultiFile-wrap" id="' + MultiFile.wrapID + '"></div>'); | |||
MultiFile.wrapper = $('#' + MultiFile.wrapID + ''); | |||
//=== | |||
// MultiFile MUST have a name - default: file1[], file2[], file3[] | |||
MultiFile.e.name = MultiFile.e.name || 'file' + group_count + '[]'; | |||
//=== | |||
if (!MultiFile.list) { | |||
// Create a wrapper for the list | |||
// * OPERA BUG: NO_MODIFICATION_ALLOWED_ERR ('list' is a read-only property) | |||
// this change allows us to keep the files in the order they were selected | |||
MultiFile.wrapper.append('<div class="MultiFile-list" id="' + MultiFile.wrapID + '_list"></div>'); | |||
MultiFile.list = $('#' + MultiFile.wrapID + '_list'); | |||
}; | |||
MultiFile.list = $(MultiFile.list); | |||
//=== | |||
// Bind a new element | |||
MultiFile.addSlave = function (slave, slave_count) { | |||
//if(window.console) console.log('MultiFile.addSlave',slave_count); | |||
// Keep track of how many elements have been displayed | |||
MultiFile.n++; | |||
// Add reference to master element | |||
slave.MultiFile = MultiFile; | |||
// BUG FIX: http://plugins.jquery.com/node/1495 | |||
// Clear identifying properties from clones | |||
slave.id = slave.name = ''; | |||
// Define element's ID and name (upload components need this!) | |||
//slave.id = slave.id || MultiFile.generateID(slave_count); | |||
slave.id = MultiFile.generateID(slave_count); | |||
//FIX for: http://code.google.com/p/jquery-multifile-plugin/issues/detail?id=23 | |||
//CHANGE v2.2.1 - change ID of all file elements, keep original ID in wrapper | |||
// 2008-Apr-29: New customizable naming convention (see url below) | |||
// http://groups.google.com/group/jquery-dev/browse_frm/thread/765c73e41b34f924# | |||
slave.name = String(MultiFile.namePattern | |||
/*master name*/ | |||
.replace(/\$name/gi, $(MultiFile.clone).attr('name')) | |||
/*master id */ | |||
.replace(/\$id/gi, $(MultiFile.clone).attr('id')) | |||
/*group count*/ | |||
.replace(/\$g/gi, group_count) //(group_count>0?group_count:'')) | |||
/*slave count*/ | |||
.replace(/\$i/gi, slave_count) //(slave_count>0?slave_count:'')) | |||
); | |||
// If we've reached maximum number, disable input slave | |||
var disable_slave; | |||
if ((MultiFile.max > 0) && ((MultiFile.files.length) > (MultiFile.max))) { | |||
slave.disabled = true; | |||
disable_slave = true; | |||
}; | |||
// Remember most recent slave | |||
MultiFile.current = slave; | |||
// We'll use jQuery from now on | |||
slave = $(slave); | |||
// Clear value | |||
slave.val('').attr('value', '')[0].value = ''; | |||
// Stop plugin initializing on slaves | |||
slave.addClass('MultiFile-applied'); | |||
// Triggered when a file is selected | |||
slave.change(function (a, b, c) { | |||
//if(window.console) console.log('MultiFile.slave.change',slave_count); | |||
//if(window.console) console.log('MultiFile.slave.change',this.files); | |||
// Lose focus to stop IE7 firing onchange again | |||
$(this).blur(); | |||
//# NEW 2014-04-14 - accept multiple file selection, HTML5 | |||
var e = this, | |||
prevs = MultiFile.files || [], | |||
files = this.files || [{ | |||
name: this.value, | |||
size: 0, | |||
type: ((this.value || '').match(/[^\.]+$/i) || [''])[0] | |||
}], | |||
newfs = [], | |||
newfs_size = 0, | |||
total_size = MultiFile.total_size || 0/*, | |||
html5_multi_mode = this.files && $(this).attr('multiple')*/ | |||
; | |||
// recap | |||
//console.log('START '+ prevs.length + ' files @ '+ sl(total_size) +'.', prevs); | |||
//# Retrive value of selected file from element | |||
var ERROR = []; //, v = String(this.value || ''); | |||
// make a normal array | |||
$.each(files, function (i, file) { | |||
newfs[newfs.length] = file; | |||
}); | |||
//# Trigger Event! onFileSelect | |||
MultiFile.trigger('FileSelect', this, MultiFile, newfs); | |||
//# End Event! | |||
// validate individual files | |||
$.each(files, function (i, file) { | |||
// pop local variables out of array/file object | |||
var v = file.name.replace(/^C:\\fakepath\\/gi,''), | |||
s = file.size, | |||
p = function(z){ | |||
return z | |||
.replace('$ext', String(v.match(/[^\.]+$/i) || '')) | |||
.replace('$file', v.match(/[^\/\\]+$/gi)) | |||
.replace('$size', sl(s) + ' > ' + sl(MultiFile.maxfile)) | |||
} | |||
; | |||
// check extension | |||
if (MultiFile.accept && v && !v.match(MultiFile.rxAccept)) { | |||
ERROR[ERROR.length] = p(MultiFile.STRING.denied); | |||
MultiFile.trigger('FileInvalid', this, MultiFile, [file]); | |||
}; | |||
// Disallow duplicates | |||
$(MultiFile.wrapper).find('input[type=file]').not(e).each(function(){ | |||
// go through each file in each slave | |||
$.each(FILE_LIST(this), function (i, file) { | |||
if(file.name){ | |||
//console.log('MultiFile.debug> Duplicate?', file.name, v); | |||
var x = (file.name || '').replace(/^C:\\fakepath\\/gi,''); | |||
if ( v == x || v == x.substr(x.length - v.length)) { | |||
ERROR[ERROR.length] = p(MultiFile.STRING.duplicate); | |||
MultiFile.trigger('FileDuplicate', e, MultiFile, [file]); | |||
}; | |||
}; | |||
}); | |||
}); | |||
// limit the max size of individual files selected | |||
if (MultiFile.maxfile>0 && s>0 && s>MultiFile.maxfile) { | |||
ERROR[ERROR.length] = p(MultiFile.STRING.toobig); | |||
MultiFile.trigger('FileTooBig', this, MultiFile, [file]); | |||
}; | |||
// check extension | |||
var customError = MultiFile.trigger('FileValidate', this, MultiFile, [file]); | |||
if(customError && customError!=''){ | |||
ERROR[ERROR.length] = p(customError); | |||
}; | |||
// add up size of files selected | |||
newfs_size += file.size; | |||
}); | |||
// add up total for all files selected (existing and new) | |||
total_size += newfs_size; | |||
// put some useful information in the file array | |||
newfs.size = newfs_size; | |||
newfs.total = total_size; | |||
newfs.total_length = newfs.length + prevs.length; | |||
// limit the number of files selected | |||
if (MultiFile.max>0 && prevs.length + files.length > MultiFile.max) { | |||
ERROR[ERROR.length] = MultiFile.STRING.toomany.replace('$max', MultiFile.max); | |||
MultiFile.trigger('FileTooMany', this, MultiFile, newfs); | |||
}; | |||
// limit the max size of files selected | |||
if (MultiFile.maxsize > 0 && total_size > MultiFile.maxsize) { | |||
ERROR[ERROR.length] = MultiFile.STRING.toomuch.replace('$size', sl(total_size) + ' > ' + sl(MultiFile.maxsize)); | |||
MultiFile.trigger('FileTooMuch', this, MultiFile, newfs); | |||
}; | |||
// Create a new file input element | |||
var newEle = $(MultiFile.clone).clone(); // Copy parent attributes - Thanks to Jonas Wagner | |||
//# Let's remember which input we've generated so | |||
// we can disable the empty ones before submission | |||
// See: http://plugins.jquery.com/node/1495 | |||
newEle.addClass('MultiFile'); | |||
// Handle error | |||
if (ERROR.length > 0) { | |||
// Handle error | |||
MultiFile.error(ERROR.join('\n\n')); | |||
// 2007-06-24: BUG FIX - Thanks to Adrian Wróbel <adrian [dot] wrobel [at] gmail.com> | |||
// Ditch the trouble maker and add a fresh new element | |||
MultiFile.n--; | |||
MultiFile.addSlave(newEle[0], slave_count); | |||
slave.parent().prepend(newEle); | |||
slave.remove(); | |||
return false; | |||
} | |||
else { // if no errors have been found | |||
// remember total size | |||
MultiFile.total_size = total_size; | |||
// merge arrays | |||
files = prevs.concat(newfs); | |||
// put some useful information in the file array | |||
files.size = total_size; | |||
files.size_label = sl(total_size); | |||
// recap | |||
//console.log('NOW '+ files.length + ' files @ '+ sl(total_size) +'.', files); | |||
// remember files | |||
MultiFile.files = files; | |||
// Hide this element (NB: display:none is evil!) | |||
$(this).css({ | |||
position: 'absolute', | |||
top: '-3000px' | |||
}); | |||
// Add new element to the form | |||
slave.after(newEle); | |||
// Bind functionality | |||
MultiFile.addSlave(newEle[0], slave_count + 1); | |||
// Update list | |||
MultiFile.addToList(this, slave_count, newfs); | |||
//# Trigger Event! afterFileSelect | |||
MultiFile.trigger('afterFileSelect', this, MultiFile, newfs); | |||
//# End Event! | |||
}; // no errors detected | |||
}); // slave.change() | |||
// point to wrapper | |||
$(slave).data('MultiFile-wrap', MultiFile.wrapper); | |||
// store contorl's settings and file info in wrapper | |||
$(MultiFile.wrapper).data('MultiFile',MultiFile); | |||
// disable? | |||
if(disable_slave) $(slave).attr('disabled','disabled').prop('disabled',true); | |||
}; // MultiFile.addSlave | |||
// Bind a new element | |||
// Add a new file to the list | |||
MultiFile.addToList = function (slave, slave_count, files) { | |||
//if(window.console) console.log('MultiFile.addToList',slave_count); | |||
//# Trigger Event! onFileAppend | |||
MultiFile.trigger('FileAppend', slave, MultiFile, files); | |||
//# End Event! | |||
var names = $('<span/>'); | |||
$.each(files, function (i, file) { | |||
var v = String(file.name || '' ).replace(/[&<>'"]/g, function(c) { return '&#'+c.charCodeAt()+';'; }), | |||
S = MultiFile.STRING, | |||
n = S.label || S.file || S.name, | |||
t = S.title || S.tooltip || S.selected, | |||
p = file.type.substr(0,6) == 'image/' ? '<img class="MultiFile-preview" style="'+ MultiFile.previewCss+'"/>' : '', | |||
label = $( | |||
( | |||
'<span class="MultiFile-label" title="' + t + '">'+ | |||
'<span class="MultiFile-title">'+ n +'</span>'+ | |||
(MultiFile.preview || $(slave).is('.with-preview') ? p : '' )+ | |||
'</span>' | |||
) | |||
.replace(/\$(file|name)/gi, (v.match(/[^\/\\]+$/gi)||[v])[0]) | |||
.replace(/\$(ext|extension|type)/gi, (v.match(/[^\.]+$/gi)||[''])[0]) | |||
.replace(/\$(size)/gi, sl(file.size || 0)) | |||
.replace(/\$(preview)/gi, p) | |||
.replace(/\$(i)/gi, i) | |||
); | |||
// now supports preview via locale string. | |||
// just add an <img class='MultiFile-preview'/> anywhere within the "file" string | |||
label.find('img.MultiFile-preview').each(function(){ | |||
var t = this; | |||
var oFReader = new FileReader(); | |||
oFReader.readAsDataURL(file); | |||
oFReader.onload = function (oFREvent) { | |||
t.src = oFREvent.target.result; | |||
}; | |||
}); | |||
// append file label to list | |||
if(i>0) names.append(', '); | |||
names.append(label); | |||
var v = String(file.name || '' ); | |||
names[names.length] = | |||
( | |||
'<span class="MultiFile-title" title="' + MultiFile.STRING.selected + '">' | |||
+ MultiFile.STRING.file + | |||
'</span>' | |||
) | |||
.replace(/\$(file|name)/gi, (v.match(/[^\/\\]+$/gi)||[v])[0]) | |||
.replace(/\$(ext|extension|type)/gi, (v.match(/[^\.]+$/gi)||[''])[0]) | |||
.replace(/\$(size)/gi, sl(file.size || 0)) | |||
.replace(/\$(i)/gi, i) | |||
; | |||
}); | |||
//$.each(files, function (i, file) { | |||
// Create label elements | |||
var | |||
r = $('<div class="MultiFile-label"></div>'), | |||
b = $('<a class="MultiFile-remove" href="#' + MultiFile.wrapID + '">' + MultiFile.STRING.remove + '</a>') | |||
// ******** | |||
// TODO: | |||
// refactor this as a single event listener on the control's | |||
// wrapper for better performance and cleaner code | |||
// ******** | |||
.click(function () { | |||
// get list of files being removed | |||
var files_being_removed = FILE_LIST(slave); | |||
//# Trigger Event! onFileRemove | |||
MultiFile.trigger('FileRemove', slave, MultiFile, files_being_removed); | |||
//# End Event! | |||
MultiFile.n--; | |||
MultiFile.current.disabled = false; | |||
// remove the relevant <input type="file"/> element | |||
$(slave).remove(); | |||
// remove the relevant label | |||
$(this).parent().remove(); | |||
// Show most current element again (move into view) and clear selection | |||
$(MultiFile.current).css({ | |||
position: '', | |||
top: '' | |||
}); | |||
$(MultiFile.current).reset().val('').attr('value', '')[0].value = ''; | |||
// point to currently visible element (always true, not necessary) | |||
//MultiFile.current = MultiFile.wrapper.find('[type=file]:visible'); | |||
// rebuild array with the files that are left. | |||
var files_remaining = [], remain_size = 0; | |||
// go through each slave | |||
$(MultiFile.wrapper).find('input[type=file]').each(function(){ | |||
// go through each file in each slave | |||
$.each(FILE_LIST(this), function (i, file) { | |||
if(file.name){ | |||
//console.log('MultiFile.debug> FileRemove> remaining file', file.size, file); | |||
// fresh file array | |||
files_remaining[files_remaining.length] = file; | |||
// fresh size count | |||
remain_size += file.size; | |||
}; | |||
}); | |||
}); | |||
// update MultiFile object | |||
MultiFile.files = files_remaining; | |||
MultiFile.total_size = remain_size; | |||
MultiFile.size_label = sl(remain_size); | |||
// update current control's reference to MultiFile object | |||
$(MultiFile.wrapper).data('MultiFile', MultiFile); | |||
//# Trigger Event! afterFileRemove | |||
MultiFile.trigger('afterFileRemove', slave, MultiFile, files_being_removed); | |||
//# End Event! | |||
//# Trigger Event! onFileChange | |||
MultiFile.trigger('FileChange', MultiFile.current, MultiFile, files_remaining); | |||
//# End Event! | |||
return false; | |||
}); | |||
// Insert label | |||
MultiFile.list.append( | |||
r.append(b, ' ', names) | |||
); | |||
//}); // each file? | |||
//# Trigger Event! afterFileAppend | |||
MultiFile.trigger('afterFileAppend', slave, MultiFile, files); | |||
//# End Event! | |||
//# Trigger Event! onFileChange | |||
MultiFile.trigger('FileChange', slave, MultiFile, MultiFile.files); | |||
//# End Event! | |||
}; // MultiFile.addToList | |||
// Add element to selected files list | |||
// Bind functionality to the first element | |||
if (!MultiFile.MultiFile) MultiFile.addSlave(MultiFile.e, 0); | |||
// Increment control count | |||
//MultiFile.I++; // using window.MultiFile | |||
MultiFile.n++; | |||
// deprecated: contorl's data now stored in wrapper because it is never removed. | |||
// improved performance and lower memory comsumption | |||
// Save control to element | |||
//MultiFile.E.data('MultiFile', MultiFile); | |||
//##################################################################### | |||
// MAIN PLUGIN FUNCTIONALITY - END | |||
//##################################################################### | |||
}); // each element | |||
}; | |||
/*--------------------------------------------------------*/ | |||
/* | |||
### Core functionality and API ### | |||
*/ | |||
$.extend($.fn.MultiFile, { | |||
/** | |||
* This method exposes the all the control's data | |||
* | |||
* Returns an object with various settings and properties of the selected files | |||
* for this particular instance of the control. stored in the control's wrapper | |||
* | |||
* @name data | |||
* @type Object | |||
* @cat Plugins/MultiFile | |||
* @author Diego A. (http://www.fyneworks.com/) | |||
* | |||
* @example $('#selector').MultiFile('data'); | |||
*/ | |||
data: function () { | |||
// analyse this element | |||
var e = $(this), b = e.is('.MultiFile-wrap'); | |||
// get control wrapper | |||
var wp = b ? e : e.data('MultiFile-wrap'); | |||
if(!wp || !wp.length) | |||
return !console.error('Could not find MultiFile control wrapper'); | |||
// get control data from wrapper | |||
var mf = wp.data('MultiFile'); | |||
if(!mf) | |||
return !console.error('Could not find MultiFile data in wrapper'); | |||
// return data | |||
return mf || {}; | |||
}, | |||
/** | |||
* This method removes all selected files | |||
* | |||
* Returns a jQuery collection of all affected elements. | |||
* | |||
* @name reset | |||
* @type jQuery | |||
* @cat Plugins/MultiFile | |||
* @author Diego A. (http://www.fyneworks.com/) | |||
* | |||
* @example $.fn.MultiFile.reset(); | |||
*/ | |||
reset: function () { | |||
var mf = this.MultiFile('data'); | |||
if (mf) $(mf.list).find('a.MultiFile-remove').click(); | |||
return $(this); | |||
}, | |||
/** | |||
* This method exposes the array of selected files | |||
* | |||
* Returns an array of file objects | |||
* | |||
* @name files | |||
* @type Array | |||
* @cat Plugins/MultiFile | |||
* @author Diego A. (http://www.fyneworks.com/) | |||
* | |||
* @example $('#selector').MultiFile('files'); | |||
*/ | |||
files: function () { | |||
var mf = this.MultiFile('data'); | |||
if(!mf) return !console.log('MultiFile plugin not initialized'); | |||
return mf.files || []; | |||
}, | |||
/** | |||
* This method exposes the plugin's sum of the sizes of all files selected | |||
* | |||
* Returns size (in bytes) of files selected | |||
* | |||
* @name size | |||
* @type Number | |||
* @cat Plugins/MultiFile | |||
* @author Diego A. (http://www.fyneworks.com/) | |||
* | |||
* @example $('#selector').MultiFile('size'); | |||
*/ | |||
size: function () { | |||
var mf = this.MultiFile('data'); | |||
if(!mf) return !console.log('MultiFile plugin not initialized'); | |||
return mf.total_size || 0; | |||
}, | |||
/** | |||
* This method exposes the plugin's tally of how many files have been selected | |||
* | |||
* Returns number (a count) of files selected | |||
* | |||
* @name count | |||
* @type Number | |||
* @cat Plugins/MultiFile | |||
* @author Diego A. (http://www.fyneworks.com/) | |||
* | |||
* @example $('#selector').MultiFile('size'); | |||
*/ | |||
count: function () { | |||
var mf = this.MultiFile('data'); | |||
if(!mf) return !console.log('MultiFile plugin not initialized'); | |||
return mf.files ? mf.files.length || 0 : 0; | |||
}, | |||
/** | |||
* This utility makes it easy to disable all 'empty' file elements in the document before submitting a form. | |||
* It marks the affected elements so they can be easily re-enabled after the form submission or validation. | |||
* | |||
* Returns a jQuery collection of all affected elements. | |||
* | |||
* @name disableEmpty | |||
* @type jQuery | |||
* @cat Plugins/MultiFile | |||
* @author Diego A. (http://www.fyneworks.com/) | |||
* | |||
* @example $.fn.MultiFile.disableEmpty(); | |||
* @param String class (optional) A string specifying a class to be applied to all affected elements - Default: 'mfD'. | |||
*/ | |||
disableEmpty: function (klass) { | |||
klass = (typeof (klass) == 'string' ? klass : '') || 'mfD'; | |||
var o = []; | |||
$('input:file.MultiFile').each(function () { | |||
if ($(this).val() == '') o[o.length] = this; | |||
}); | |||
// automatically re-enable for novice users | |||
window.clearTimeout($.fn.MultiFile.reEnableTimeout); | |||
$.fn.MultiFile.reEnableTimeout = window.setTimeout($.fn.MultiFile.reEnableEmpty, 500); | |||
return $(o).each(function () { | |||
this.disabled = true | |||
}).addClass(klass); | |||
}, | |||
/** | |||
* This method re-enables 'empty' file elements that were disabled (and marked) with the $.fn.MultiFile.disableEmpty method. | |||
* | |||
* Returns a jQuery collection of all affected elements. | |||
* | |||
* @name reEnableEmpty | |||
* @type jQuery | |||
* @cat Plugins/MultiFile | |||
* @author Diego A. (http://www.fyneworks.com/) | |||
* | |||
* @example $.fn.MultiFile.reEnableEmpty(); | |||
* @param String klass (optional) A string specifying the class that was used to mark affected elements - Default: 'mfD'. | |||
*/ | |||
reEnableEmpty: function (klass) { | |||
klass = (typeof (klass) == 'string' ? klass : '') || 'mfD'; | |||
return $('input:file.' + klass).removeClass(klass).each(function () { | |||
this.disabled = false | |||
}); | |||
}, | |||
/** | |||
* This method will intercept other jQuery plugins and disable empty file input elements prior to form submission | |||
* | |||
* @name intercept | |||
* @cat Plugins/MultiFile | |||
* @author Diego A. (http://www.fyneworks.com/) | |||
* | |||
* @example $.fn.MultiFile.intercept(); | |||
* @param Array methods (optional) Array of method names to be intercepted | |||
*/ | |||
intercepted: {}, | |||
intercept: function (methods, context, args) { | |||
var method, value; | |||
args = args || []; | |||
if (args.constructor.toString().indexOf("Array") < 0) args = [args]; | |||
if (typeof (methods) == 'function') { | |||
$.fn.MultiFile.disableEmpty(); | |||
value = methods.apply(context || window, args); | |||
//SEE-http://code.google.com/p/jquery-multifile-plugin/issues/detail?id=27 | |||
setTimeout(function () { | |||
$.fn.MultiFile.reEnableEmpty() | |||
}, 1000); | |||
return value; | |||
}; | |||
if (methods.constructor.toString().indexOf("Array") < 0) methods = [methods]; | |||
for (var i = 0; i < methods.length; i++) { | |||
method = methods[i] + ''; // make sure that we have a STRING | |||
if (method)(function (method) { // make sure that method is ISOLATED for the interception | |||
$.fn.MultiFile.intercepted[method] = $.fn[method] || function () {}; | |||
$.fn[method] = function () { | |||
$.fn.MultiFile.disableEmpty(); | |||
value = $.fn.MultiFile.intercepted[method].apply(this, arguments); | |||
//SEE http://code.google.com/p/jquery-multifile-plugin/issues/detail?id=27 | |||
setTimeout(function () { | |||
$.fn.MultiFile.reEnableEmpty() | |||
}, 1000); | |||
return value; | |||
}; // interception | |||
})(method); // MAKE SURE THAT method IS ISOLATED for the interception | |||
}; // for each method | |||
} // $.fn.MultiFile.intercept | |||
}); | |||
/*--------------------------------------------------------*/ | |||
/* | |||
### Default Settings ### | |||
eg.: You can override default control like this: | |||
$.fn.MultiFile.options.accept = 'gif|jpg'; | |||
*/ | |||
$.fn.MultiFile.options = { //$.extend($.fn.MultiFile, { options: { | |||
accept: '', // accepted file extensions | |||
max: -1, // maximum number of selectable files | |||
maxfile: -1, // maximum size of a single file | |||
maxsize: -1, // maximum size of entire payload | |||
// name to use for newly created elements | |||
namePattern: '$name', // same name by default (which creates an array) | |||
/*master name*/ // use $name | |||
/*master id */ // use $id | |||
/*group count*/ // use $g | |||
/*slave count*/ // use $i | |||
/*other */ // use any combination of he above, eg.: $name_file$i | |||
// previews | |||
preview: false, | |||
previewCss: 'max-height:100px; max-width:100px;', | |||
// STRING: collection lets you show messages in different languages | |||
STRING: { | |||
remove: 'x', | |||
denied: 'You cannot select a $ext file.\nTry again...', | |||
file: '$file', | |||
selected: 'File selected: $file', | |||
duplicate: 'This file has already been selected:\n$file', | |||
toomuch: 'The files selected exceed the maximum size permited ($size)', | |||
toomany: 'Too many files selected (max: $max)', | |||
toobig: '$file is too big (max $size)' | |||
}, | |||
// name of methods that should be automcatically intercepted so the plugin can disable | |||
// extra file elements that are empty before execution and automatically re-enable them afterwards | |||
autoIntercept: ['submit', 'ajaxSubmit', 'ajaxForm', 'validate', 'valid' /* array of methods to intercept */ ], | |||
// error handling function | |||
error: function (s) { | |||
if(typeof console != 'undefined') console.log(s); | |||
// TODO: add various dialog handlers here? | |||
alert(s); | |||
} | |||
}; //} }); | |||
/*--------------------------------------------------------*/ | |||
/* | |||
### Additional Methods ### | |||
Required functionality outside the plugin's scope | |||
*/ | |||
// Native input reset method - because this alone doesn't always work: $(element).val('').attr('value', '')[0].value = ''; | |||
$.fn.reset = $.fn.reset || function () { | |||
return this.each(function () { | |||
try { | |||
this.reset(); | |||
} catch (e) {} | |||
}); | |||
}; | |||
/*--------------------------------------------------------*/ | |||
/* | |||
### Default implementation ### | |||
The plugin will attach itself to file inputs | |||
with the class 'multi' when the page loads | |||
*/ | |||
$(function () { | |||
//$("input:file.multi").MultiFile(); | |||
$("input[type=file].multi").MultiFile(); | |||
}); | |||
/*# AVOID COLLISIONS #*/ | |||
})(jQuery); | |||
/*# AVOID COLLISIONS #*/ |
@@ -0,0 +1,614 @@ | |||
/** | |||
* @fileoverview | |||
* - Using the 'QRCode for Javascript library' | |||
* - Fixed dataset of 'QRCode for Javascript library' for support full-spec. | |||
* - this library has no dependencies. | |||
* | |||
* @author davidshimjs | |||
* @see <a href="http://www.d-project.com/" target="_blank">http://www.d-project.com/</a> | |||
* @see <a href="http://jeromeetienne.github.com/jquery-qrcode/" target="_blank">http://jeromeetienne.github.com/jquery-qrcode/</a> | |||
*/ | |||
var QRCode; | |||
(function () { | |||
//--------------------------------------------------------------------- | |||
// QRCode for JavaScript | |||
// | |||
// Copyright (c) 2009 Kazuhiko Arase | |||
// | |||
// URL: http://www.d-project.com/ | |||
// | |||
// Licensed under the MIT license: | |||
// http://www.opensource.org/licenses/mit-license.php | |||
// | |||
// The word "QR Code" is registered trademark of | |||
// DENSO WAVE INCORPORATED | |||
// http://www.denso-wave.com/qrcode/faqpatent-e.html | |||
// | |||
//--------------------------------------------------------------------- | |||
function QR8bitByte(data) { | |||
this.mode = QRMode.MODE_8BIT_BYTE; | |||
this.data = data; | |||
this.parsedData = []; | |||
// Added to support UTF-8 Characters | |||
for (var i = 0, l = this.data.length; i < l; i++) { | |||
var byteArray = []; | |||
var code = this.data.charCodeAt(i); | |||
if (code > 0x10000) { | |||
byteArray[0] = 0xF0 | ((code & 0x1C0000) >>> 18); | |||
byteArray[1] = 0x80 | ((code & 0x3F000) >>> 12); | |||
byteArray[2] = 0x80 | ((code & 0xFC0) >>> 6); | |||
byteArray[3] = 0x80 | (code & 0x3F); | |||
} else if (code > 0x800) { | |||
byteArray[0] = 0xE0 | ((code & 0xF000) >>> 12); | |||
byteArray[1] = 0x80 | ((code & 0xFC0) >>> 6); | |||
byteArray[2] = 0x80 | (code & 0x3F); | |||
} else if (code > 0x80) { | |||
byteArray[0] = 0xC0 | ((code & 0x7C0) >>> 6); | |||
byteArray[1] = 0x80 | (code & 0x3F); | |||
} else { | |||
byteArray[0] = code; | |||
} | |||
this.parsedData.push(byteArray); | |||
} | |||
this.parsedData = Array.prototype.concat.apply([], this.parsedData); | |||
if (this.parsedData.length != this.data.length) { | |||
this.parsedData.unshift(191); | |||
this.parsedData.unshift(187); | |||
this.parsedData.unshift(239); | |||
} | |||
} | |||
QR8bitByte.prototype = { | |||
getLength: function (buffer) { | |||
return this.parsedData.length; | |||
}, | |||
write: function (buffer) { | |||
for (var i = 0, l = this.parsedData.length; i < l; i++) { | |||
buffer.put(this.parsedData[i], 8); | |||
} | |||
} | |||
}; | |||
function QRCodeModel(typeNumber, errorCorrectLevel) { | |||
this.typeNumber = typeNumber; | |||
this.errorCorrectLevel = errorCorrectLevel; | |||
this.modules = null; | |||
this.moduleCount = 0; | |||
this.dataCache = null; | |||
this.dataList = []; | |||
} | |||
QRCodeModel.prototype={addData:function(data){var newData=new QR8bitByte(data);this.dataList.push(newData);this.dataCache=null;},isDark:function(row,col){if(row<0||this.moduleCount<=row||col<0||this.moduleCount<=col){throw new Error(row+","+col);} | |||
return this.modules[row][col];},getModuleCount:function(){return this.moduleCount;},make:function(){this.makeImpl(false,this.getBestMaskPattern());},makeImpl:function(test,maskPattern){this.moduleCount=this.typeNumber*4+17;this.modules=new Array(this.moduleCount);for(var row=0;row<this.moduleCount;row++){this.modules[row]=new Array(this.moduleCount);for(var col=0;col<this.moduleCount;col++){this.modules[row][col]=null;}} | |||
this.setupPositionProbePattern(0,0);this.setupPositionProbePattern(this.moduleCount-7,0);this.setupPositionProbePattern(0,this.moduleCount-7);this.setupPositionAdjustPattern();this.setupTimingPattern();this.setupTypeInfo(test,maskPattern);if(this.typeNumber>=7){this.setupTypeNumber(test);} | |||
if(this.dataCache==null){this.dataCache=QRCodeModel.createData(this.typeNumber,this.errorCorrectLevel,this.dataList);} | |||
this.mapData(this.dataCache,maskPattern);},setupPositionProbePattern:function(row,col){for(var r=-1;r<=7;r++){if(row+r<=-1||this.moduleCount<=row+r)continue;for(var c=-1;c<=7;c++){if(col+c<=-1||this.moduleCount<=col+c)continue;if((0<=r&&r<=6&&(c==0||c==6))||(0<=c&&c<=6&&(r==0||r==6))||(2<=r&&r<=4&&2<=c&&c<=4)){this.modules[row+r][col+c]=true;}else{this.modules[row+r][col+c]=false;}}}},getBestMaskPattern:function(){var minLostPoint=0;var pattern=0;for(var i=0;i<8;i++){this.makeImpl(true,i);var lostPoint=QRUtil.getLostPoint(this);if(i==0||minLostPoint>lostPoint){minLostPoint=lostPoint;pattern=i;}} | |||
return pattern;},createMovieClip:function(target_mc,instance_name,depth){var qr_mc=target_mc.createEmptyMovieClip(instance_name,depth);var cs=1;this.make();for(var row=0;row<this.modules.length;row++){var y=row*cs;for(var col=0;col<this.modules[row].length;col++){var x=col*cs;var dark=this.modules[row][col];if(dark){qr_mc.beginFill(0,100);qr_mc.moveTo(x,y);qr_mc.lineTo(x+cs,y);qr_mc.lineTo(x+cs,y+cs);qr_mc.lineTo(x,y+cs);qr_mc.endFill();}}} | |||
return qr_mc;},setupTimingPattern:function(){for(var r=8;r<this.moduleCount-8;r++){if(this.modules[r][6]!=null){continue;} | |||
this.modules[r][6]=(r%2==0);} | |||
for(var c=8;c<this.moduleCount-8;c++){if(this.modules[6][c]!=null){continue;} | |||
this.modules[6][c]=(c%2==0);}},setupPositionAdjustPattern:function(){var pos=QRUtil.getPatternPosition(this.typeNumber);for(var i=0;i<pos.length;i++){for(var j=0;j<pos.length;j++){var row=pos[i];var col=pos[j];if(this.modules[row][col]!=null){continue;} | |||
for(var r=-2;r<=2;r++){for(var c=-2;c<=2;c++){if(r==-2||r==2||c==-2||c==2||(r==0&&c==0)){this.modules[row+r][col+c]=true;}else{this.modules[row+r][col+c]=false;}}}}}},setupTypeNumber:function(test){var bits=QRUtil.getBCHTypeNumber(this.typeNumber);for(var i=0;i<18;i++){var mod=(!test&&((bits>>i)&1)==1);this.modules[Math.floor(i/3)][i%3+this.moduleCount-8-3]=mod;} | |||
for(var i=0;i<18;i++){var mod=(!test&&((bits>>i)&1)==1);this.modules[i%3+this.moduleCount-8-3][Math.floor(i/3)]=mod;}},setupTypeInfo:function(test,maskPattern){var data=(this.errorCorrectLevel<<3)|maskPattern;var bits=QRUtil.getBCHTypeInfo(data);for(var i=0;i<15;i++){var mod=(!test&&((bits>>i)&1)==1);if(i<6){this.modules[i][8]=mod;}else if(i<8){this.modules[i+1][8]=mod;}else{this.modules[this.moduleCount-15+i][8]=mod;}} | |||
for(var i=0;i<15;i++){var mod=(!test&&((bits>>i)&1)==1);if(i<8){this.modules[8][this.moduleCount-i-1]=mod;}else if(i<9){this.modules[8][15-i-1+1]=mod;}else{this.modules[8][15-i-1]=mod;}} | |||
this.modules[this.moduleCount-8][8]=(!test);},mapData:function(data,maskPattern){var inc=-1;var row=this.moduleCount-1;var bitIndex=7;var byteIndex=0;for(var col=this.moduleCount-1;col>0;col-=2){if(col==6)col--;while(true){for(var c=0;c<2;c++){if(this.modules[row][col-c]==null){var dark=false;if(byteIndex<data.length){dark=(((data[byteIndex]>>>bitIndex)&1)==1);} | |||
var mask=QRUtil.getMask(maskPattern,row,col-c);if(mask){dark=!dark;} | |||
this.modules[row][col-c]=dark;bitIndex--;if(bitIndex==-1){byteIndex++;bitIndex=7;}}} | |||
row+=inc;if(row<0||this.moduleCount<=row){row-=inc;inc=-inc;break;}}}}};QRCodeModel.PAD0=0xEC;QRCodeModel.PAD1=0x11;QRCodeModel.createData=function(typeNumber,errorCorrectLevel,dataList){var rsBlocks=QRRSBlock.getRSBlocks(typeNumber,errorCorrectLevel);var buffer=new QRBitBuffer();for(var i=0;i<dataList.length;i++){var data=dataList[i];buffer.put(data.mode,4);buffer.put(data.getLength(),QRUtil.getLengthInBits(data.mode,typeNumber));data.write(buffer);} | |||
var totalDataCount=0;for(var i=0;i<rsBlocks.length;i++){totalDataCount+=rsBlocks[i].dataCount;} | |||
if(buffer.getLengthInBits()>totalDataCount*8){throw new Error("code length overflow. (" | |||
+buffer.getLengthInBits() | |||
+">" | |||
+totalDataCount*8 | |||
+")");} | |||
if(buffer.getLengthInBits()+4<=totalDataCount*8){buffer.put(0,4);} | |||
while(buffer.getLengthInBits()%8!=0){buffer.putBit(false);} | |||
while(true){if(buffer.getLengthInBits()>=totalDataCount*8){break;} | |||
buffer.put(QRCodeModel.PAD0,8);if(buffer.getLengthInBits()>=totalDataCount*8){break;} | |||
buffer.put(QRCodeModel.PAD1,8);} | |||
return QRCodeModel.createBytes(buffer,rsBlocks);};QRCodeModel.createBytes=function(buffer,rsBlocks){var offset=0;var maxDcCount=0;var maxEcCount=0;var dcdata=new Array(rsBlocks.length);var ecdata=new Array(rsBlocks.length);for(var r=0;r<rsBlocks.length;r++){var dcCount=rsBlocks[r].dataCount;var ecCount=rsBlocks[r].totalCount-dcCount;maxDcCount=Math.max(maxDcCount,dcCount);maxEcCount=Math.max(maxEcCount,ecCount);dcdata[r]=new Array(dcCount);for(var i=0;i<dcdata[r].length;i++){dcdata[r][i]=0xff&buffer.buffer[i+offset];} | |||
offset+=dcCount;var rsPoly=QRUtil.getErrorCorrectPolynomial(ecCount);var rawPoly=new QRPolynomial(dcdata[r],rsPoly.getLength()-1);var modPoly=rawPoly.mod(rsPoly);ecdata[r]=new Array(rsPoly.getLength()-1);for(var i=0;i<ecdata[r].length;i++){var modIndex=i+modPoly.getLength()-ecdata[r].length;ecdata[r][i]=(modIndex>=0)?modPoly.get(modIndex):0;}} | |||
var totalCodeCount=0;for(var i=0;i<rsBlocks.length;i++){totalCodeCount+=rsBlocks[i].totalCount;} | |||
var data=new Array(totalCodeCount);var index=0;for(var i=0;i<maxDcCount;i++){for(var r=0;r<rsBlocks.length;r++){if(i<dcdata[r].length){data[index++]=dcdata[r][i];}}} | |||
for(var i=0;i<maxEcCount;i++){for(var r=0;r<rsBlocks.length;r++){if(i<ecdata[r].length){data[index++]=ecdata[r][i];}}} | |||
return data;};var QRMode={MODE_NUMBER:1<<0,MODE_ALPHA_NUM:1<<1,MODE_8BIT_BYTE:1<<2,MODE_KANJI:1<<3};var QRErrorCorrectLevel={L:1,M:0,Q:3,H:2};var QRMaskPattern={PATTERN000:0,PATTERN001:1,PATTERN010:2,PATTERN011:3,PATTERN100:4,PATTERN101:5,PATTERN110:6,PATTERN111:7};var QRUtil={PATTERN_POSITION_TABLE:[[],[6,18],[6,22],[6,26],[6,30],[6,34],[6,22,38],[6,24,42],[6,26,46],[6,28,50],[6,30,54],[6,32,58],[6,34,62],[6,26,46,66],[6,26,48,70],[6,26,50,74],[6,30,54,78],[6,30,56,82],[6,30,58,86],[6,34,62,90],[6,28,50,72,94],[6,26,50,74,98],[6,30,54,78,102],[6,28,54,80,106],[6,32,58,84,110],[6,30,58,86,114],[6,34,62,90,118],[6,26,50,74,98,122],[6,30,54,78,102,126],[6,26,52,78,104,130],[6,30,56,82,108,134],[6,34,60,86,112,138],[6,30,58,86,114,142],[6,34,62,90,118,146],[6,30,54,78,102,126,150],[6,24,50,76,102,128,154],[6,28,54,80,106,132,158],[6,32,58,84,110,136,162],[6,26,54,82,110,138,166],[6,30,58,86,114,142,170]],G15:(1<<10)|(1<<8)|(1<<5)|(1<<4)|(1<<2)|(1<<1)|(1<<0),G18:(1<<12)|(1<<11)|(1<<10)|(1<<9)|(1<<8)|(1<<5)|(1<<2)|(1<<0),G15_MASK:(1<<14)|(1<<12)|(1<<10)|(1<<4)|(1<<1),getBCHTypeInfo:function(data){var d=data<<10;while(QRUtil.getBCHDigit(d)-QRUtil.getBCHDigit(QRUtil.G15)>=0){d^=(QRUtil.G15<<(QRUtil.getBCHDigit(d)-QRUtil.getBCHDigit(QRUtil.G15)));} | |||
return((data<<10)|d)^QRUtil.G15_MASK;},getBCHTypeNumber:function(data){var d=data<<12;while(QRUtil.getBCHDigit(d)-QRUtil.getBCHDigit(QRUtil.G18)>=0){d^=(QRUtil.G18<<(QRUtil.getBCHDigit(d)-QRUtil.getBCHDigit(QRUtil.G18)));} | |||
return(data<<12)|d;},getBCHDigit:function(data){var digit=0;while(data!=0){digit++;data>>>=1;} | |||
return digit;},getPatternPosition:function(typeNumber){return QRUtil.PATTERN_POSITION_TABLE[typeNumber-1];},getMask:function(maskPattern,i,j){switch(maskPattern){case QRMaskPattern.PATTERN000:return(i+j)%2==0;case QRMaskPattern.PATTERN001:return i%2==0;case QRMaskPattern.PATTERN010:return j%3==0;case QRMaskPattern.PATTERN011:return(i+j)%3==0;case QRMaskPattern.PATTERN100:return(Math.floor(i/2)+Math.floor(j/3))%2==0;case QRMaskPattern.PATTERN101:return(i*j)%2+(i*j)%3==0;case QRMaskPattern.PATTERN110:return((i*j)%2+(i*j)%3)%2==0;case QRMaskPattern.PATTERN111:return((i*j)%3+(i+j)%2)%2==0;default:throw new Error("bad maskPattern:"+maskPattern);}},getErrorCorrectPolynomial:function(errorCorrectLength){var a=new QRPolynomial([1],0);for(var i=0;i<errorCorrectLength;i++){a=a.multiply(new QRPolynomial([1,QRMath.gexp(i)],0));} | |||
return a;},getLengthInBits:function(mode,type){if(1<=type&&type<10){switch(mode){case QRMode.MODE_NUMBER:return 10;case QRMode.MODE_ALPHA_NUM:return 9;case QRMode.MODE_8BIT_BYTE:return 8;case QRMode.MODE_KANJI:return 8;default:throw new Error("mode:"+mode);}}else if(type<27){switch(mode){case QRMode.MODE_NUMBER:return 12;case QRMode.MODE_ALPHA_NUM:return 11;case QRMode.MODE_8BIT_BYTE:return 16;case QRMode.MODE_KANJI:return 10;default:throw new Error("mode:"+mode);}}else if(type<41){switch(mode){case QRMode.MODE_NUMBER:return 14;case QRMode.MODE_ALPHA_NUM:return 13;case QRMode.MODE_8BIT_BYTE:return 16;case QRMode.MODE_KANJI:return 12;default:throw new Error("mode:"+mode);}}else{throw new Error("type:"+type);}},getLostPoint:function(qrCode){var moduleCount=qrCode.getModuleCount();var lostPoint=0;for(var row=0;row<moduleCount;row++){for(var col=0;col<moduleCount;col++){var sameCount=0;var dark=qrCode.isDark(row,col);for(var r=-1;r<=1;r++){if(row+r<0||moduleCount<=row+r){continue;} | |||
for(var c=-1;c<=1;c++){if(col+c<0||moduleCount<=col+c){continue;} | |||
if(r==0&&c==0){continue;} | |||
if(dark==qrCode.isDark(row+r,col+c)){sameCount++;}}} | |||
if(sameCount>5){lostPoint+=(3+sameCount-5);}}} | |||
for(var row=0;row<moduleCount-1;row++){for(var col=0;col<moduleCount-1;col++){var count=0;if(qrCode.isDark(row,col))count++;if(qrCode.isDark(row+1,col))count++;if(qrCode.isDark(row,col+1))count++;if(qrCode.isDark(row+1,col+1))count++;if(count==0||count==4){lostPoint+=3;}}} | |||
for(var row=0;row<moduleCount;row++){for(var col=0;col<moduleCount-6;col++){if(qrCode.isDark(row,col)&&!qrCode.isDark(row,col+1)&&qrCode.isDark(row,col+2)&&qrCode.isDark(row,col+3)&&qrCode.isDark(row,col+4)&&!qrCode.isDark(row,col+5)&&qrCode.isDark(row,col+6)){lostPoint+=40;}}} | |||
for(var col=0;col<moduleCount;col++){for(var row=0;row<moduleCount-6;row++){if(qrCode.isDark(row,col)&&!qrCode.isDark(row+1,col)&&qrCode.isDark(row+2,col)&&qrCode.isDark(row+3,col)&&qrCode.isDark(row+4,col)&&!qrCode.isDark(row+5,col)&&qrCode.isDark(row+6,col)){lostPoint+=40;}}} | |||
var darkCount=0;for(var col=0;col<moduleCount;col++){for(var row=0;row<moduleCount;row++){if(qrCode.isDark(row,col)){darkCount++;}}} | |||
var ratio=Math.abs(100*darkCount/moduleCount/moduleCount-50)/5;lostPoint+=ratio*10;return lostPoint;}};var QRMath={glog:function(n){if(n<1){throw new Error("glog("+n+")");} | |||
return QRMath.LOG_TABLE[n];},gexp:function(n){while(n<0){n+=255;} | |||
while(n>=256){n-=255;} | |||
return QRMath.EXP_TABLE[n];},EXP_TABLE:new Array(256),LOG_TABLE:new Array(256)};for(var i=0;i<8;i++){QRMath.EXP_TABLE[i]=1<<i;} | |||
for(var i=8;i<256;i++){QRMath.EXP_TABLE[i]=QRMath.EXP_TABLE[i-4]^QRMath.EXP_TABLE[i-5]^QRMath.EXP_TABLE[i-6]^QRMath.EXP_TABLE[i-8];} | |||
for(var i=0;i<255;i++){QRMath.LOG_TABLE[QRMath.EXP_TABLE[i]]=i;} | |||
function QRPolynomial(num,shift){if(num.length==undefined){throw new Error(num.length+"/"+shift);} | |||
var offset=0;while(offset<num.length&&num[offset]==0){offset++;} | |||
this.num=new Array(num.length-offset+shift);for(var i=0;i<num.length-offset;i++){this.num[i]=num[i+offset];}} | |||
QRPolynomial.prototype={get:function(index){return this.num[index];},getLength:function(){return this.num.length;},multiply:function(e){var num=new Array(this.getLength()+e.getLength()-1);for(var i=0;i<this.getLength();i++){for(var j=0;j<e.getLength();j++){num[i+j]^=QRMath.gexp(QRMath.glog(this.get(i))+QRMath.glog(e.get(j)));}} | |||
return new QRPolynomial(num,0);},mod:function(e){if(this.getLength()-e.getLength()<0){return this;} | |||
var ratio=QRMath.glog(this.get(0))-QRMath.glog(e.get(0));var num=new Array(this.getLength());for(var i=0;i<this.getLength();i++){num[i]=this.get(i);} | |||
for(var i=0;i<e.getLength();i++){num[i]^=QRMath.gexp(QRMath.glog(e.get(i))+ratio);} | |||
return new QRPolynomial(num,0).mod(e);}};function QRRSBlock(totalCount,dataCount){this.totalCount=totalCount;this.dataCount=dataCount;} | |||
QRRSBlock.RS_BLOCK_TABLE=[[1,26,19],[1,26,16],[1,26,13],[1,26,9],[1,44,34],[1,44,28],[1,44,22],[1,44,16],[1,70,55],[1,70,44],[2,35,17],[2,35,13],[1,100,80],[2,50,32],[2,50,24],[4,25,9],[1,134,108],[2,67,43],[2,33,15,2,34,16],[2,33,11,2,34,12],[2,86,68],[4,43,27],[4,43,19],[4,43,15],[2,98,78],[4,49,31],[2,32,14,4,33,15],[4,39,13,1,40,14],[2,121,97],[2,60,38,2,61,39],[4,40,18,2,41,19],[4,40,14,2,41,15],[2,146,116],[3,58,36,2,59,37],[4,36,16,4,37,17],[4,36,12,4,37,13],[2,86,68,2,87,69],[4,69,43,1,70,44],[6,43,19,2,44,20],[6,43,15,2,44,16],[4,101,81],[1,80,50,4,81,51],[4,50,22,4,51,23],[3,36,12,8,37,13],[2,116,92,2,117,93],[6,58,36,2,59,37],[4,46,20,6,47,21],[7,42,14,4,43,15],[4,133,107],[8,59,37,1,60,38],[8,44,20,4,45,21],[12,33,11,4,34,12],[3,145,115,1,146,116],[4,64,40,5,65,41],[11,36,16,5,37,17],[11,36,12,5,37,13],[5,109,87,1,110,88],[5,65,41,5,66,42],[5,54,24,7,55,25],[11,36,12],[5,122,98,1,123,99],[7,73,45,3,74,46],[15,43,19,2,44,20],[3,45,15,13,46,16],[1,135,107,5,136,108],[10,74,46,1,75,47],[1,50,22,15,51,23],[2,42,14,17,43,15],[5,150,120,1,151,121],[9,69,43,4,70,44],[17,50,22,1,51,23],[2,42,14,19,43,15],[3,141,113,4,142,114],[3,70,44,11,71,45],[17,47,21,4,48,22],[9,39,13,16,40,14],[3,135,107,5,136,108],[3,67,41,13,68,42],[15,54,24,5,55,25],[15,43,15,10,44,16],[4,144,116,4,145,117],[17,68,42],[17,50,22,6,51,23],[19,46,16,6,47,17],[2,139,111,7,140,112],[17,74,46],[7,54,24,16,55,25],[34,37,13],[4,151,121,5,152,122],[4,75,47,14,76,48],[11,54,24,14,55,25],[16,45,15,14,46,16],[6,147,117,4,148,118],[6,73,45,14,74,46],[11,54,24,16,55,25],[30,46,16,2,47,17],[8,132,106,4,133,107],[8,75,47,13,76,48],[7,54,24,22,55,25],[22,45,15,13,46,16],[10,142,114,2,143,115],[19,74,46,4,75,47],[28,50,22,6,51,23],[33,46,16,4,47,17],[8,152,122,4,153,123],[22,73,45,3,74,46],[8,53,23,26,54,24],[12,45,15,28,46,16],[3,147,117,10,148,118],[3,73,45,23,74,46],[4,54,24,31,55,25],[11,45,15,31,46,16],[7,146,116,7,147,117],[21,73,45,7,74,46],[1,53,23,37,54,24],[19,45,15,26,46,16],[5,145,115,10,146,116],[19,75,47,10,76,48],[15,54,24,25,55,25],[23,45,15,25,46,16],[13,145,115,3,146,116],[2,74,46,29,75,47],[42,54,24,1,55,25],[23,45,15,28,46,16],[17,145,115],[10,74,46,23,75,47],[10,54,24,35,55,25],[19,45,15,35,46,16],[17,145,115,1,146,116],[14,74,46,21,75,47],[29,54,24,19,55,25],[11,45,15,46,46,16],[13,145,115,6,146,116],[14,74,46,23,75,47],[44,54,24,7,55,25],[59,46,16,1,47,17],[12,151,121,7,152,122],[12,75,47,26,76,48],[39,54,24,14,55,25],[22,45,15,41,46,16],[6,151,121,14,152,122],[6,75,47,34,76,48],[46,54,24,10,55,25],[2,45,15,64,46,16],[17,152,122,4,153,123],[29,74,46,14,75,47],[49,54,24,10,55,25],[24,45,15,46,46,16],[4,152,122,18,153,123],[13,74,46,32,75,47],[48,54,24,14,55,25],[42,45,15,32,46,16],[20,147,117,4,148,118],[40,75,47,7,76,48],[43,54,24,22,55,25],[10,45,15,67,46,16],[19,148,118,6,149,119],[18,75,47,31,76,48],[34,54,24,34,55,25],[20,45,15,61,46,16]];QRRSBlock.getRSBlocks=function(typeNumber,errorCorrectLevel){var rsBlock=QRRSBlock.getRsBlockTable(typeNumber,errorCorrectLevel);if(rsBlock==undefined){throw new Error("bad rs block @ typeNumber:"+typeNumber+"/errorCorrectLevel:"+errorCorrectLevel);} | |||
var length=rsBlock.length/3;var list=[];for(var i=0;i<length;i++){var count=rsBlock[i*3+0];var totalCount=rsBlock[i*3+1];var dataCount=rsBlock[i*3+2];for(var j=0;j<count;j++){list.push(new QRRSBlock(totalCount,dataCount));}} | |||
return list;};QRRSBlock.getRsBlockTable=function(typeNumber,errorCorrectLevel){switch(errorCorrectLevel){case QRErrorCorrectLevel.L:return QRRSBlock.RS_BLOCK_TABLE[(typeNumber-1)*4+0];case QRErrorCorrectLevel.M:return QRRSBlock.RS_BLOCK_TABLE[(typeNumber-1)*4+1];case QRErrorCorrectLevel.Q:return QRRSBlock.RS_BLOCK_TABLE[(typeNumber-1)*4+2];case QRErrorCorrectLevel.H:return QRRSBlock.RS_BLOCK_TABLE[(typeNumber-1)*4+3];default:return undefined;}};function QRBitBuffer(){this.buffer=[];this.length=0;} | |||
QRBitBuffer.prototype={get:function(index){var bufIndex=Math.floor(index/8);return((this.buffer[bufIndex]>>>(7-index%8))&1)==1;},put:function(num,length){for(var i=0;i<length;i++){this.putBit(((num>>>(length-i-1))&1)==1);}},getLengthInBits:function(){return this.length;},putBit:function(bit){var bufIndex=Math.floor(this.length/8);if(this.buffer.length<=bufIndex){this.buffer.push(0);} | |||
if(bit){this.buffer[bufIndex]|=(0x80>>>(this.length%8));} | |||
this.length++;}};var QRCodeLimitLength=[[17,14,11,7],[32,26,20,14],[53,42,32,24],[78,62,46,34],[106,84,60,44],[134,106,74,58],[154,122,86,64],[192,152,108,84],[230,180,130,98],[271,213,151,119],[321,251,177,137],[367,287,203,155],[425,331,241,177],[458,362,258,194],[520,412,292,220],[586,450,322,250],[644,504,364,280],[718,560,394,310],[792,624,442,338],[858,666,482,382],[929,711,509,403],[1003,779,565,439],[1091,857,611,461],[1171,911,661,511],[1273,997,715,535],[1367,1059,751,593],[1465,1125,805,625],[1528,1190,868,658],[1628,1264,908,698],[1732,1370,982,742],[1840,1452,1030,790],[1952,1538,1112,842],[2068,1628,1168,898],[2188,1722,1228,958],[2303,1809,1283,983],[2431,1911,1351,1051],[2563,1989,1423,1093],[2699,2099,1499,1139],[2809,2213,1579,1219],[2953,2331,1663,1273]]; | |||
function _isSupportCanvas() { | |||
return typeof CanvasRenderingContext2D != "undefined"; | |||
} | |||
// android 2.x doesn't support Data-URI spec | |||
function _getAndroid() { | |||
var android = false; | |||
var sAgent = navigator.userAgent; | |||
if (/android/i.test(sAgent)) { // android | |||
android = true; | |||
var aMat = sAgent.toString().match(/android ([0-9]\.[0-9])/i); | |||
if (aMat && aMat[1]) { | |||
android = parseFloat(aMat[1]); | |||
} | |||
} | |||
return android; | |||
} | |||
var svgDrawer = (function() { | |||
var Drawing = function (el, htOption) { | |||
this._el = el; | |||
this._htOption = htOption; | |||
}; | |||
Drawing.prototype.draw = function (oQRCode) { | |||
var _htOption = this._htOption; | |||
var _el = this._el; | |||
var nCount = oQRCode.getModuleCount(); | |||
var nWidth = Math.floor(_htOption.width / nCount); | |||
var nHeight = Math.floor(_htOption.height / nCount); | |||
this.clear(); | |||
function makeSVG(tag, attrs) { | |||
var el = document.createElementNS('http://www.w3.org/2000/svg', tag); | |||
for (var k in attrs) | |||
if (attrs.hasOwnProperty(k)) el.setAttribute(k, attrs[k]); | |||
return el; | |||
} | |||
var svg = makeSVG("svg" , {'viewBox': '0 0 ' + String(nCount) + " " + String(nCount), 'width': '100%', 'height': '100%', 'fill': _htOption.colorLight}); | |||
svg.setAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns:xlink", "http://www.w3.org/1999/xlink"); | |||
_el.appendChild(svg); | |||
svg.appendChild(makeSVG("rect", {"fill": _htOption.colorLight, "width": "100%", "height": "100%"})); | |||
svg.appendChild(makeSVG("rect", {"fill": _htOption.colorDark, "width": "1", "height": "1", "id": "template"})); | |||
for (var row = 0; row < nCount; row++) { | |||
for (var col = 0; col < nCount; col++) { | |||
if (oQRCode.isDark(row, col)) { | |||
var child = makeSVG("use", {"x": String(col), "y": String(row)}); | |||
child.setAttributeNS("http://www.w3.org/1999/xlink", "href", "#template") | |||
svg.appendChild(child); | |||
} | |||
} | |||
} | |||
}; | |||
Drawing.prototype.clear = function () { | |||
while (this._el.hasChildNodes()) | |||
this._el.removeChild(this._el.lastChild); | |||
}; | |||
return Drawing; | |||
})(); | |||
var useSVG = document.documentElement.tagName.toLowerCase() === "svg"; | |||
// Drawing in DOM by using Table tag | |||
var Drawing = useSVG ? svgDrawer : !_isSupportCanvas() ? (function () { | |||
var Drawing = function (el, htOption) { | |||
this._el = el; | |||
this._htOption = htOption; | |||
}; | |||
/** | |||
* Draw the QRCode | |||
* | |||
* @param {QRCode} oQRCode | |||
*/ | |||
Drawing.prototype.draw = function (oQRCode) { | |||
var _htOption = this._htOption; | |||
var _el = this._el; | |||
var nCount = oQRCode.getModuleCount(); | |||
var nWidth = Math.floor(_htOption.width / nCount); | |||
var nHeight = Math.floor(_htOption.height / nCount); | |||
var aHTML = ['<table style="border:0;border-collapse:collapse;">']; | |||
for (var row = 0; row < nCount; row++) { | |||
aHTML.push('<tr>'); | |||
for (var col = 0; col < nCount; col++) { | |||
aHTML.push('<td style="border:0;border-collapse:collapse;padding:0;margin:0;width:' + nWidth + 'px;height:' + nHeight + 'px;background-color:' + (oQRCode.isDark(row, col) ? _htOption.colorDark : _htOption.colorLight) + ';"></td>'); | |||
} | |||
aHTML.push('</tr>'); | |||
} | |||
aHTML.push('</table>'); | |||
_el.innerHTML = aHTML.join(''); | |||
// Fix the margin values as real size. | |||
var elTable = _el.childNodes[0]; | |||
var nLeftMarginTable = (_htOption.width - elTable.offsetWidth) / 2; | |||
var nTopMarginTable = (_htOption.height - elTable.offsetHeight) / 2; | |||
if (nLeftMarginTable > 0 && nTopMarginTable > 0) { | |||
elTable.style.margin = nTopMarginTable + "px " + nLeftMarginTable + "px"; | |||
} | |||
}; | |||
/** | |||
* Clear the QRCode | |||
*/ | |||
Drawing.prototype.clear = function () { | |||
this._el.innerHTML = ''; | |||
}; | |||
return Drawing; | |||
})() : (function () { // Drawing in Canvas | |||
function _onMakeImage() { | |||
this._elImage.src = this._elCanvas.toDataURL("image/png"); | |||
this._elImage.style.display = "block"; | |||
this._elCanvas.style.display = "none"; | |||
} | |||
// Android 2.1 bug workaround | |||
// http://code.google.com/p/android/issues/detail?id=5141 | |||
if (this._android && this._android <= 2.1) { | |||
var factor = 1 / window.devicePixelRatio; | |||
var drawImage = CanvasRenderingContext2D.prototype.drawImage; | |||
CanvasRenderingContext2D.prototype.drawImage = function (image, sx, sy, sw, sh, dx, dy, dw, dh) { | |||
if (("nodeName" in image) && /img/i.test(image.nodeName)) { | |||
for (var i = arguments.length - 1; i >= 1; i--) { | |||
arguments[i] = arguments[i] * factor; | |||
} | |||
} else if (typeof dw == "undefined") { | |||
arguments[1] *= factor; | |||
arguments[2] *= factor; | |||
arguments[3] *= factor; | |||
arguments[4] *= factor; | |||
} | |||
drawImage.apply(this, arguments); | |||
}; | |||
} | |||
/** | |||
* Check whether the user's browser supports Data URI or not | |||
* | |||
* @private | |||
* @param {Function} fSuccess Occurs if it supports Data URI | |||
* @param {Function} fFail Occurs if it doesn't support Data URI | |||
*/ | |||
function _safeSetDataURI(fSuccess, fFail) { | |||
var self = this; | |||
self._fFail = fFail; | |||
self._fSuccess = fSuccess; | |||
// Check it just once | |||
if (self._bSupportDataURI === null) { | |||
var el = document.createElement("img"); | |||
var fOnError = function() { | |||
self._bSupportDataURI = false; | |||
if (self._fFail) { | |||
self._fFail.call(self); | |||
} | |||
}; | |||
var fOnSuccess = function() { | |||
self._bSupportDataURI = true; | |||
if (self._fSuccess) { | |||
self._fSuccess.call(self); | |||
} | |||
}; | |||
el.onabort = fOnError; | |||
el.onerror = fOnError; | |||
el.onload = fOnSuccess; | |||
el.src = "data:image/gif;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg=="; // the Image contains 1px data. | |||
return; | |||
} else if (self._bSupportDataURI === true && self._fSuccess) { | |||
self._fSuccess.call(self); | |||
} else if (self._bSupportDataURI === false && self._fFail) { | |||
self._fFail.call(self); | |||
} | |||
}; | |||
/** | |||
* Drawing QRCode by using canvas | |||
* | |||
* @constructor | |||
* @param {HTMLElement} el | |||
* @param {Object} htOption QRCode Options | |||
*/ | |||
var Drawing = function (el, htOption) { | |||
this._bIsPainted = false; | |||
this._android = _getAndroid(); | |||
this._htOption = htOption; | |||
this._elCanvas = document.createElement("canvas"); | |||
this._elCanvas.width = htOption.width; | |||
this._elCanvas.height = htOption.height; | |||
el.appendChild(this._elCanvas); | |||
this._el = el; | |||
this._oContext = this._elCanvas.getContext("2d"); | |||
this._bIsPainted = false; | |||
this._elImage = document.createElement("img"); | |||
this._elImage.alt = "Scan me!"; | |||
this._elImage.style.display = "none"; | |||
this._el.appendChild(this._elImage); | |||
this._bSupportDataURI = null; | |||
}; | |||
/** | |||
* Draw the QRCode | |||
* | |||
* @param {QRCode} oQRCode | |||
*/ | |||
Drawing.prototype.draw = function (oQRCode) { | |||
var _elImage = this._elImage; | |||
var _oContext = this._oContext; | |||
var _htOption = this._htOption; | |||
var nCount = oQRCode.getModuleCount(); | |||
var nWidth = _htOption.width / nCount; | |||
var nHeight = _htOption.height / nCount; | |||
var nRoundedWidth = Math.round(nWidth); | |||
var nRoundedHeight = Math.round(nHeight); | |||
_elImage.style.display = "none"; | |||
this.clear(); | |||
for (var row = 0; row < nCount; row++) { | |||
for (var col = 0; col < nCount; col++) { | |||
var bIsDark = oQRCode.isDark(row, col); | |||
var nLeft = col * nWidth; | |||
var nTop = row * nHeight; | |||
_oContext.strokeStyle = bIsDark ? _htOption.colorDark : _htOption.colorLight; | |||
_oContext.lineWidth = 1; | |||
_oContext.fillStyle = bIsDark ? _htOption.colorDark : _htOption.colorLight; | |||
_oContext.fillRect(nLeft, nTop, nWidth, nHeight); | |||
// 안티 앨리어싱 방지 처리 | |||
_oContext.strokeRect( | |||
Math.floor(nLeft) + 0.5, | |||
Math.floor(nTop) + 0.5, | |||
nRoundedWidth, | |||
nRoundedHeight | |||
); | |||
_oContext.strokeRect( | |||
Math.ceil(nLeft) - 0.5, | |||
Math.ceil(nTop) - 0.5, | |||
nRoundedWidth, | |||
nRoundedHeight | |||
); | |||
} | |||
} | |||
this._bIsPainted = true; | |||
}; | |||
/** | |||
* Make the image from Canvas if the browser supports Data URI. | |||
*/ | |||
Drawing.prototype.makeImage = function () { | |||
if (this._bIsPainted) { | |||
_safeSetDataURI.call(this, _onMakeImage); | |||
} | |||
}; | |||
/** | |||
* Return whether the QRCode is painted or not | |||
* | |||
* @return {Boolean} | |||
*/ | |||
Drawing.prototype.isPainted = function () { | |||
return this._bIsPainted; | |||
}; | |||
/** | |||
* Clear the QRCode | |||
*/ | |||
Drawing.prototype.clear = function () { | |||
this._oContext.clearRect(0, 0, this._elCanvas.width, this._elCanvas.height); | |||
this._bIsPainted = false; | |||
}; | |||
/** | |||
* @private | |||
* @param {Number} nNumber | |||
*/ | |||
Drawing.prototype.round = function (nNumber) { | |||
if (!nNumber) { | |||
return nNumber; | |||
} | |||
return Math.floor(nNumber * 1000) / 1000; | |||
}; | |||
return Drawing; | |||
})(); | |||
/** | |||
* Get the type by string length | |||
* | |||
* @private | |||
* @param {String} sText | |||
* @param {Number} nCorrectLevel | |||
* @return {Number} type | |||
*/ | |||
function _getTypeNumber(sText, nCorrectLevel) { | |||
var nType = 1; | |||
var length = _getUTF8Length(sText); | |||
for (var i = 0, len = QRCodeLimitLength.length; i <= len; i++) { | |||
var nLimit = 0; | |||
switch (nCorrectLevel) { | |||
case QRErrorCorrectLevel.L : | |||
nLimit = QRCodeLimitLength[i][0]; | |||
break; | |||
case QRErrorCorrectLevel.M : | |||
nLimit = QRCodeLimitLength[i][1]; | |||
break; | |||
case QRErrorCorrectLevel.Q : | |||
nLimit = QRCodeLimitLength[i][2]; | |||
break; | |||
case QRErrorCorrectLevel.H : | |||
nLimit = QRCodeLimitLength[i][3]; | |||
break; | |||
} | |||
if (length <= nLimit) { | |||
break; | |||
} else { | |||
nType++; | |||
} | |||
} | |||
if (nType > QRCodeLimitLength.length) { | |||
throw new Error("Too long data"); | |||
} | |||
return nType; | |||
} | |||
function _getUTF8Length(sText) { | |||
var replacedText = encodeURI(sText).toString().replace(/\%[0-9a-fA-F]{2}/g, 'a'); | |||
return replacedText.length + (replacedText.length != sText ? 3 : 0); | |||
} | |||
/** | |||
* @class QRCode | |||
* @constructor | |||
* @example | |||
* new QRCode(document.getElementById("test"), "http://jindo.dev.naver.com/collie"); | |||
* | |||
* @example | |||
* var oQRCode = new QRCode("test", { | |||
* text : "http://naver.com", | |||
* width : 128, | |||
* height : 128 | |||
* }); | |||
* | |||
* oQRCode.clear(); // Clear the QRCode. | |||
* oQRCode.makeCode("http://map.naver.com"); // Re-create the QRCode. | |||
* | |||
* @param {HTMLElement|String} el target element or 'id' attribute of element. | |||
* @param {Object|String} vOption | |||
* @param {String} vOption.text QRCode link data | |||
* @param {Number} [vOption.width=256] | |||
* @param {Number} [vOption.height=256] | |||
* @param {String} [vOption.colorDark="#000000"] | |||
* @param {String} [vOption.colorLight="#ffffff"] | |||
* @param {QRCode.CorrectLevel} [vOption.correctLevel=QRCode.CorrectLevel.H] [L|M|Q|H] | |||
*/ | |||
QRCode = function (el, vOption) { | |||
this._htOption = { | |||
width : 256, | |||
height : 256, | |||
typeNumber : 4, | |||
colorDark : "#000000", | |||
colorLight : "#ffffff", | |||
correctLevel : QRErrorCorrectLevel.H | |||
}; | |||
if (typeof vOption === 'string') { | |||
vOption = { | |||
text : vOption | |||
}; | |||
} | |||
// Overwrites options | |||
if (vOption) { | |||
for (var i in vOption) { | |||
this._htOption[i] = vOption[i]; | |||
} | |||
} | |||
if (typeof el == "string") { | |||
el = document.getElementById(el); | |||
} | |||
if (this._htOption.useSVG) { | |||
Drawing = svgDrawer; | |||
} | |||
this._android = _getAndroid(); | |||
this._el = el; | |||
this._oQRCode = null; | |||
this._oDrawing = new Drawing(this._el, this._htOption); | |||
if (this._htOption.text) { | |||
this.makeCode(this._htOption.text); | |||
} | |||
}; | |||
/** | |||
* Make the QRCode | |||
* | |||
* @param {String} sText link data | |||
*/ | |||
QRCode.prototype.makeCode = function (sText) { | |||
this._oQRCode = new QRCodeModel(_getTypeNumber(sText, this._htOption.correctLevel), this._htOption.correctLevel); | |||
this._oQRCode.addData(sText); | |||
this._oQRCode.make(); | |||
this._el.title = sText; | |||
this._oDrawing.draw(this._oQRCode); | |||
this.makeImage(); | |||
}; | |||
/** | |||
* Make the Image from Canvas element | |||
* - It occurs automatically | |||
* - Android below 3 doesn't support Data-URI spec. | |||
* | |||
* @private | |||
*/ | |||
QRCode.prototype.makeImage = function () { | |||
if (typeof this._oDrawing.makeImage == "function" && (!this._android || this._android >= 3)) { | |||
this._oDrawing.makeImage(); | |||
} | |||
}; | |||
/** | |||
* Clear the QRCode | |||
*/ | |||
QRCode.prototype.clear = function () { | |||
this._oDrawing.clear(); | |||
}; | |||
/** | |||
* @name QRCode.CorrectLevel | |||
*/ | |||
QRCode.CorrectLevel = QRErrorCorrectLevel; | |||
})(); |
@@ -0,0 +1,60 @@ | |||
<?php | |||
session_start(); | |||
require_once "Utils/Constants.php"; | |||
require_once 'Utils/Helpers.php'; | |||
Class AdminController { | |||
function validPassword($password){ | |||
$passwordFile = file_get_contents(Constants::CONST_PASSWORD_FOLDER."/".Constants::CONST_PASSWORD_FILE, FILE_USE_INCLUDE_PATH); | |||
if( Helpers::verify_pw($password, $passwordFile)){ | |||
$_SESSION['superadmin'] = true; | |||
return true; | |||
} else { | |||
$_SESSION['superadmin'] = false; | |||
return false; | |||
} | |||
} | |||
function unlog(){ | |||
$_SESSION['superadmin'] = false; | |||
return true; | |||
} | |||
function isAdminLogged(){ | |||
if(!isset( $_SESSION['superadmin'])) return false; | |||
return $_SESSION['superadmin']; | |||
} | |||
function setPassword($password){ | |||
if($this->isPassword()) return false; | |||
$hash = Helpers::hash_pw($password); | |||
//Test if the folder exist | |||
if (!file_exists(Constants::CONST_PASSWORD_FOLDER.'/')) { | |||
mkdir(Constants::CONST_PASSWORD_FOLDER, 0777, true); | |||
} | |||
//Record the hash | |||
$fp = fopen(Constants::CONST_PASSWORD_FOLDER."/".Constants::CONST_PASSWORD_FILE, 'w'); | |||
fwrite($fp, $hash); | |||
fclose($fp); | |||
return true; | |||
} | |||
function isPassword(){ | |||
if (!file_exists(Constants::CONST_PASSWORD_FOLDER.'/')) return false; | |||
if (!file_exists(Constants::CONST_PASSWORD_FOLDER.'/'.Constants::CONST_PASSWORD_FILE)) return false; | |||
return true; | |||
} | |||
} |
@@ -0,0 +1,389 @@ | |||
<?php | |||
/* | |||
________ _ _______ | |||
/ ____/ /_ ____ _____ | | / / ___/ | |||
/ / / __ \/ __ `/ __ \ | | /| / /\__ \ | |||
/ /___/ / / / /_/ / / / / | |/ |/ /___/ / | |||
\____/_/ /_/\__,_/_/ /_/ |__/|__//____/ | |||
Chan WEBSERVICES | |||
reception of the webservice for chan | |||
*/ | |||
require_once 'ChanController.php'; | |||
require_once 'AdminController.php'; | |||
require_once 'Models/Post.php'; | |||
$action = ""; | |||
if(isset($_POST["action"])) | |||
$action = $_POST["action"]; | |||
/* | |||
controls the RESTful services | |||
URL mapping | |||
*/ | |||
switch($action){ | |||
//************************************** | |||
// * WS ADMIN | |||
// ************************************* | |||
case "setAdminPassword": | |||
$password = ""; | |||
if( isset($_POST['password']) ) $password = $_POST['password']; | |||
$AdminController = new AdminController(); | |||
$result = $AdminController -> setPassword($password); | |||
Helpers::makeGenericResponse(true, $result, null); | |||
break; | |||
case "validAdmin": | |||
$password = ""; | |||
if( isset($_POST['password']) ) $password = $_POST['password']; | |||
$AdminController = new AdminController(); | |||
$result = $AdminController -> validPassword($password); | |||
Helpers::makeGenericResponse(true, $result, null); | |||
break; | |||
case "testAdminSession": | |||
$AdminController = new AdminController(); | |||
$result = $AdminController -> isAdminLogged(); | |||
Helpers::makeGenericResponse(true, $result, null); | |||
break; | |||
case "unLog": | |||
$AdminController = new AdminController(); | |||
$result = $AdminController -> unlog(); | |||
Helpers::makeGenericResponse(true, $result, null); | |||
break; | |||
case "deletePost": | |||
$chanController = new ChanController(); | |||
$mapKey = ""; | |||
$postId = -1; | |||
if( isset($_POST['map_key']) ) $mapKey = $_POST['map_key']; | |||
if( isset($_POST['post_id']) ) $postId = $_POST['post_id']; | |||
$result = $chanController -> deletePost($mapKey ,$postId ); | |||
Helpers::makeGenericResponse(true, $result, null); | |||
break; | |||
case "setBan": | |||
$chanController = new ChanController(); | |||
$mapKey = ""; | |||
$postId = -1; | |||
if( isset($_POST['post_id']) ) $postId = $_POST['post_id']; | |||
$result = $chanController -> setBan($postId ); | |||
Helpers::makeGenericResponse(true, $result, null); | |||
break; | |||
case "deletePostForVal": | |||
$chanController = new ChanController(); | |||
$val = ""; | |||
$result = false; | |||
if( isset($_POST['val']) ){ | |||
$val = $_POST['val']; | |||
$result = $chanController -> deletePostForVal($val); | |||
} | |||
Helpers::makeGenericResponse(true, $result, null); | |||
break; | |||
case "setPostUrlToFile": | |||
$chanController = new ChanController(); | |||
$mapKey = ""; | |||
$postId = -1; | |||
if( isset($_POST['post_id']) ) $postId = $_POST['post_id']; | |||
$result = $chanController -> setPostUrlToFile($postId ); | |||
Helpers::makeGenericResponse(true, $result, null); | |||
break; | |||
case "setPostCanon": | |||
$chanController = new ChanController(); | |||
$mapKey = ""; | |||
$postId = -1; | |||
if( isset($_POST['map_key']) ) $mapKey = $_POST['map_key']; | |||
if( isset($_POST['post_id']) ) $postId = $_POST['post_id']; | |||
$result = $chanController -> setPostCanon($mapKey ,$postId ); | |||
Helpers::makeGenericResponse(true, $result, null); | |||
break; | |||
/* | |||
case "banUser": | |||
$chanController = new ChanController(); | |||
$mapKey = ""; | |||
$reason = ""; | |||
$durationD = 0; | |||
$postId = -1; | |||
if( isset($_POST['map_key']) ) $mapKey = $_POST['map_key']; | |||
if( isset($_POST['post_id']) ) $postId = $_POST['post_id']; | |||
if( isset($_POST['durationD']) ) $durationD = $_POST['durationD']; | |||
if( isset($_POST['reason']) ) $reason = $_POST['reason']; | |||
$result = $chanController -> banForPost($mapKey, $postId, $reason, $durationD); | |||
Helpers::makeGenericResponse(true, $result, null); | |||
break;*/ | |||
case "getAllPost": | |||
$chanController = new ChanController(); | |||
$result = $chanController -> getAllPost(); | |||
Helpers::makeGenericResponse(true, $result, null); | |||
break; | |||
case "getAllMaps": | |||
$chanController = new ChanController(); | |||
$result = $chanController -> getAllMaps(); | |||
Helpers::makeGenericResponse(true, $result, null); | |||
break; | |||
case "getAllTiles": | |||
$chanController = new ChanController(); | |||
$result = $chanController -> getAllTiles(); | |||
Helpers::makeGenericResponse(true, $result, null); | |||
break; | |||
case "saveMapModel": | |||
$mapKey = ""; | |||
$levelData = ""; | |||
if( isset($_POST['id']) ) $mapKey = $_POST['key']; | |||
if( isset($_POST['level_data']) ) $levelData = $_POST['level_data']; | |||
$chanController = new ChanController(); | |||
$result = $chanController -> saveMapModel($mapKey, $levelData); | |||
Helpers::makeGenericResponse(true, $result, null); | |||
break; | |||
//************************************** | |||
// * WS for PUR CHAN | |||
// * Actual version | |||
// ************************************* | |||
case "getDungeonSettings": | |||
$chanController = new ChanController(); | |||
$result = $chanController -> getSettings(); | |||
Helpers::makeGenericResponse(true, $result, null); | |||
break; | |||
case "getMapPosts": | |||
$chanController = new ChanController(); | |||
$result = $chanController -> getMapPosts(); | |||
Helpers::makeGenericResponse(true, $result, null); | |||
break; | |||
/* | |||
case "getAllPost": | |||
$chanController = new ChanController(); | |||
$result = $chanController -> getAllPost(); | |||
Helpers::makeGenericResponse(true, $result, null); | |||
break;*/ | |||
case "getReplies": | |||
if( isset($_POST['post_id']) ) $postId = $_POST['post_id']; | |||
$chanController = new ChanController(); | |||
$result = $chanController -> getReplies($postId); | |||
Helpers::makeGenericResponse(true, $result, null); | |||
break; | |||
case "createPost": | |||
$chanController = new ChanController(); | |||
$torrentBytes = NULL; | |||
$file = NULL; | |||
$img = NULL; | |||
if( isset($_FILES['file']) ) $file = $_FILES['file']; | |||
if( isset($_POST['torrent']) ) $torrentBytes = $_POST['torrent']; | |||
if( isset($_POST['image_data']) ) $img = $_POST['image_data']; | |||
$postModel = new Post(); | |||
$postModel -> fillWithPostData(); | |||
$result = $chanController -> createPost($postModel,$file, $img); | |||
Helpers::makeGenericResponse(true, $result, null); | |||
break; | |||
//************************************** | |||
// * WS PLAYER | |||
// ************************************* | |||
case "getActions": | |||
$chanController = new ChanController(); | |||
$result = $chanController -> getActions(); | |||
Helpers::makeGenericResponse(true, $result, null); | |||
break; | |||
case "setAction": | |||
if( isset($_POST['player_action']) ) $player_action = $_POST['player_action']; | |||
if( isset($_POST['value']) ) $value = $_POST['value']; | |||
$chanController = new ChanController(); | |||
$result = $chanController -> setAction($player_action,$value); | |||
Helpers::makeGenericResponse(true, $result, null); | |||
break; | |||
case "initPlayer": | |||
$chanController = new ChanController(); | |||
$playerId = null; | |||
$playerKey = null; | |||
$mapKey = null; | |||
$playerPassword = null; | |||
if( isset($_POST['player_id']) ) $playerId = $_POST['player_id']; | |||
if( isset($_POST['player_key']) ) $playerKey = $_POST['player_key']; | |||
if( isset($_POST['player_password']) ) $playerPassword = $_POST['player_password']; | |||
if( isset($_POST['map_key']) ) $mapKey = $_POST['map_key']; | |||
$playerData = $chanController->init( $playerId, $playerKey, $playerPassword, $mapKey ); | |||
//$playerId = null; | |||
//if(array_key_exists ("id", $playerData)) $playerId = $playerData["id"]; | |||
//return the player postion | |||
//$playersList = $chanController->getAllPlayers($playerId); | |||
//$arts = $chanController->getArtByMap($playerData); | |||
/* | |||
$result = array ( | |||
'list' => $playersList, | |||
'player' => $playerData | |||
);*/ | |||
Helpers::makeGenericResponse(true, $playerData, null); | |||
break; | |||
case "changeMapPlayer": | |||
$chanController = new ChanController(); | |||
$mapKey = null; | |||
if( isset($_POST['map_key']) ) $mapKey = $_POST['map_key']; | |||
$chanController->setPlayerMapKey( $mapKey ); | |||
$result = $chanController -> getMapPosts(); | |||
Helpers::makeGenericResponse(true, $result, null); | |||
break; | |||
case "changeMapPlayerName": | |||
$chanController = new ChanController(); | |||
$mapName = null; | |||
if( isset($_POST['map_name']) ) $mapName = $_POST['map_name']; | |||
$chanController->setPlayerMapName( $mapName ); | |||
$result = $chanController -> getMapPosts(); | |||
Helpers::makeGenericResponse(true, $result, null); | |||
break; | |||
case "changeMapRandom": | |||
$chanController = new ChanController(); | |||
$secret = true; | |||
if( isset($_POST['secret']) ) $secret = $_POST['secret']; | |||
$chanController->setPlayerMapRand( $secret ); | |||
$result = $chanController -> getMapPosts(); | |||
Helpers::makeGenericResponse(true, $result, null); | |||
break; | |||
case "setPlayerItem": | |||
$chanController = new ChanController(); | |||
$itemKey = null; | |||
if( isset($_POST['item_key']) ) $itemKey = $_POST['item_key']; | |||
$chanController->setItem( $itemKey ); | |||
$result = $chanController -> getMapPosts(); | |||
Helpers::makeGenericResponse(true, $result, null); | |||
break; | |||
/* | |||
case "movePlayer": | |||
$chanController = new ChanController(); | |||
$playerId = null; | |||
$playerKey = null; | |||
$playerPassword = null; | |||
if( isset($_POST['player_id']) ) $playerId = $_POST['player_id']; | |||
if( isset($_POST['player_key']) ) $playerKey = $_POST['player_key']; | |||
if( isset($_POST['player_password']) ) $playerPassword = $_POST['player_password']; | |||
//position in 3D to get | |||
$playerData = array(); | |||
if( isset($_POST['position_x']) ) $playerData['position_x'] = $_POST['position_x']; | |||
if( isset($_POST['position_y']) ) $playerData['position_y'] = $_POST['position_y']; | |||
if( isset($_POST['position_z']) ) $playerData['position_z'] = $_POST['position_z']; | |||
if( isset($_POST['map_key']) ) $playerData['map_key'] = $_POST['map_key']; | |||
$playerResult = $chanController->move( $playerId, $playerKey, $playerPassword, $playerData); | |||
if($playerResult == null){ | |||
//PLAYER DONT EXIST ANYMORE!!! | |||
$playerResult = $chanController->init( $playerId, $playerKey, $playerPassword ); | |||
$playerId = null; | |||
if(array_key_exists ("id", $playerResult)) $playerId = $playerResult["id"]; | |||
} | |||
//return the player postion | |||
$playersList = $chanController->getAllPlayers($playerId); | |||
//Gte post datas | |||
$postsList = $chanController->getArtByMap($playerData); | |||
//IS the player Null??? if yes | |||
$result = array( | |||
'user' => $playerResult, | |||
'players' => $playersList, | |||
'arts' => $postsList | |||
); | |||
Helpers::makeGenericResponse(true,$result, null); | |||
break; | |||
*/ | |||
} |
@@ -0,0 +1,311 @@ | |||
<?php | |||
/* | |||
____ __ __ _ _______ | |||
/ __ \____ _/ /_____ _/ /_ ____ _________ | | / / ___/ | |||
/ / / / __ `/ __/ __ `/ __ \/ __ `/ ___/ _ \ | | /| / /\__ \ | |||
/ /_/ / /_/ / /_/ /_/ / /_/ / /_/ (__ ) __/ | |/ |/ /___/ / | |||
/_____/\__,_/\__/\__,_/_.___/\__,_/____/\___/ |__/|__//____/ | |||
Database WS | |||
*/ | |||
ini_set('display_errors', 1); | |||
require_once "Utils/Constants.php"; | |||
require_once "Imports/LazerImports.php"; | |||
require_once 'MapController.php'; | |||
require_once 'AdminController.php'; | |||
use Lazer\Classes\Database as Lazer; | |||
defined('LAZER_DATA_PATH') or define('LAZER_DATA_PATH', realpath(dirname(__FILE__)).'/'.Constants::CONST_DB_FOLDER.'/'); | |||
//Admin password | |||
$password = ""; | |||
if(isset($_POST["password"])) $password = $_POST["password"]; | |||
$adminController = new AdminController(); | |||
if(!$adminController ->validPassword($password)){ | |||
echo "bad password!!"; | |||
exit; | |||
} | |||
//Create an autoloader | |||
$action = ""; | |||
if(isset($_POST["action"])) | |||
$action = $_POST["action"]; | |||
switch($action){ | |||
case "initDB": | |||
//************************************** | |||
// * DB MAIN | |||
// ************************************* | |||
try{ | |||
$banExtist = false; | |||
try{ | |||
$banExtist = \Lazer\Classes\Helpers\Validate::table(Constants::CONST_TABLE_BANS)->exists(); | |||
} catch(\Lazer\Classes\LazerException $e){ | |||
//Database doesn't exist | |||
} | |||
if(!$banExtist){ | |||
Lazer::create(Constants::CONST_TABLE_BANS, array( | |||
'id' => 'integer', | |||
'reason' => 'string', | |||
'id_post' => 'integer', | |||
//'thread_key' => 'string', | |||
'map_key' => 'string', | |||
'date' => 'integer', | |||
'duration' => 'integer', | |||
'player_ip' => 'string' | |||
)); | |||
echo 'Ban created'; | |||
} | |||
Lazer::create(Constants::CONST_TABLE_FILES, array( | |||
'id' => 'integer', | |||
'id_post' => 'integer', | |||
'map_key' => 'string', | |||
'fake_path' => 'string', | |||
'fake_name' => 'string', | |||
'file_name' => 'string' | |||
)); | |||
echo 'Forum creation succed'; | |||
} catch(\Lazer\Classes\LazerException $e){ | |||
echo 'exception'.$e; | |||
} | |||
try{ | |||
Lazer::create(Constants::CONST_TABLE_PLAYERS, array( | |||
'id' => 'integer', | |||
'name' => 'string', | |||
'talk' => 'string', | |||
'is_admin' => 'boolean', | |||
'player_key' => 'string', | |||
'hp' => 'integer', | |||
'money' => 'integer', | |||
'map_key' => 'string', | |||
'last_action' => 'integer', | |||
'position_x' => 'double', | |||
'position_y' => 'double', | |||
'position_z' => 'double' | |||
)); | |||
Lazer::create(Constants::CONST_TABLE_ITEMS, array( | |||
'id' => 'integer', | |||
'key' => 'string', | |||
'player_id' => 'integer', | |||
'action' => 'string', | |||
'type' => 'string', | |||
'name' => 'string', | |||
'description' => 'string', | |||
'map_key' => 'string', | |||
'x' => 'double', | |||
'y' => 'double', | |||
'is_expendable' => 'boolean', | |||
'value' => 'integer' | |||
)); | |||
Lazer::create(Constants::CONST_TABLE_LOGS, array( | |||
'id' => 'integer', | |||
'map_key' => 'string', | |||
'last_action'=> 'integer', | |||
'ip' => 'string', | |||
'to' => 'integer', | |||
'name' => 'string', | |||
'player_id' => 'integer', | |||
'value' => 'string', | |||
'action' => 'string' | |||
)); | |||
echo 'PLAYER creation succed'; | |||
} catch(\Lazer\Classes\LazerException $e){ | |||
echo 'exception'.$e; | |||
} | |||
break; | |||
//************************************** | |||
// * DB MAPS AND POST | |||
// ************************************* | |||
//init the data base | |||
case "initMapsAndPosts": | |||
try{ | |||
Lazer::create(Constants::CONST_TABLE_POSTS, array( | |||
'id' => 'integer', | |||
'show' => 'boolean', | |||
'key' => 'string', | |||
'scale' => 'integer', | |||
'date' => 'integer', | |||
'reply' => 'integer', | |||
'player_ip' => 'string', | |||
'player_id' => 'integer', | |||
'is_canon' => 'boolean', | |||
'is_admin' => 'boolean', | |||
'nsfw' => 'boolean', | |||
'graffiti' => 'boolean', | |||
'preview' => 'string', | |||
'player_name' => 'string', | |||
//'thread_key' => 'string', | |||
'map_key' => 'string', | |||
'canvas_key' => 'string', | |||
'message' => 'string', | |||
'url' => 'string', | |||
'magnet' => 'string', | |||
'torrent' => 'string', | |||
'hash' => 'string' | |||
)); | |||
//Map creation | |||
Lazer::create(Constants::CONST_TABLE_MAP, array( | |||
'id' => 'integer', | |||
'key' => 'string', | |||
'name' => 'string', | |||
'description' => 'string', | |||
'theme' => 'string', | |||
'width' => 'integer', | |||
'height' => 'integer', | |||
'x' => 'integer', | |||
'y' => 'integer', | |||
'door_key_n' => 'string', | |||
'door_key_e' => 'string', | |||
'door_key_s' => 'string', | |||
'door_key_w' => 'string', | |||
'level_data' => 'string', | |||
'num_post_max' => 'integer', | |||
'fast_travel' => 'boolean', | |||
'is_safe' => 'boolean', | |||
'is_chan' => 'boolean', | |||
'is_secret' => 'boolean' | |||
)); | |||
$mapController = new MapController(); | |||
$mapController -> generateWorld(); | |||
echo 'MAP creation succed'; | |||
} catch(\Lazer\Classes\LazerException $e){ | |||
echo 'exception'.$e; | |||
} | |||
break; | |||
//init the data base | |||
case "initBans": | |||
$banExtist = false; | |||
try{ | |||
$banExtist = \Lazer\Classes\Helpers\Validate::table(Constants::CONST_TABLE_BANS)->exists(); | |||
} catch(\Lazer\Classes\LazerException $e){ | |||
//Database doesn't exist | |||
} | |||
if(!$banExtist){ | |||
Lazer::create(Constants::CONST_TABLE_BANS, array( | |||
'id' => 'integer', | |||
'reason' => 'string', | |||
'id_post' => 'integer', | |||
//'thread_key' => 'string', | |||
'map_key' => 'string', | |||
'date' => 'integer', | |||
'duration' => 'integer', | |||
'player_ip' => 'string' | |||
)); | |||
echo 'Ban created'; | |||
} | |||
break; | |||
case "destroyBans": | |||
Lazer::remove(Constants::CONST_TABLE_BANS); | |||
echo 'ban destroyed'; | |||
break; | |||
//init the data base | |||
case "destroyDB": | |||
try{ | |||
//Lazer::remove(Constants::CONST_TABLE_BANS); | |||
Lazer::remove(Constants::CONST_TABLE_FILES); | |||
Lazer::remove(Constants::CONST_TABLE_PLAYERS); | |||
Lazer::remove(Constants::CONST_TABLE_ITEMS); | |||
Lazer::remove(Constants::CONST_TABLE_LOGS); | |||
echo 'DB erase succed'; | |||
} catch(\Lazer\Classes\LazerException $e){ | |||
echo 'exception'.$e; | |||
} | |||
break; | |||
//init the data base | |||
case "destroyMapsAndPosts": | |||
try{ | |||
Lazer::remove(Constants::CONST_TABLE_POSTS); | |||
Lazer::remove(Constants::CONST_TABLE_MAP); | |||
echo 'Maps and Posts erase succed'; | |||
} catch(\Lazer\Classes\LazerException $e){ | |||
echo 'exception'.$e; | |||
} | |||
break; | |||
//init the data base | |||
/* | |||
case "cleanDB": | |||
try{ | |||
Lazer::table(Constants::CONST_TABLE_POSTS)->delete(); | |||
Lazer::table(Constants::CONST_TABLE_BANS)->delete(); | |||
Lazer::table(Constants::CONST_TABLE_PLAYERS)->delete(); | |||
Lazer::table(Constants::CONST_TABLE_FILES)->delete(); | |||
Lazer::table(Constants::CONST_TABLE_ITEMS)->delete(); | |||
//Lazer::table(Constants::CONST_TABLE_LOOT)->delete(); | |||
Lazer::table(Constants::CONST_TABLE_MAP)->delete(); | |||
echo 'DB erase succed'; | |||
} catch(\Lazer\Classes\LazerException $e){ | |||
echo 'exception'.$e; | |||
} | |||
break;*/ | |||
} |
@@ -0,0 +1,10 @@ | |||
<? | |||
include_once "Libs/Lazer/Classes/Database.php"; | |||
include_once "Libs/Lazer/Classes/Helpers/Data.php"; | |||
include_once "Libs/Lazer/Classes/Helpers/Config.php"; | |||
//include "Libs/Lazer/Classes/Helpers/File.php"; | |||
//include "Libs/Lazer/Classes/Helpers/FileInterface.php"; | |||
//include "Libs/Lazer/Classes/LazerException.php"; | |||
//include "Libs/Lazer/Classes/Relations.php"; | |||
//include "Libs/Lazer/Classes/Helpers/Validate.php"; |
@@ -0,0 +1,961 @@ | |||
<?php | |||
namespace Lazer\Classes; | |||
include "Libs/Lazer/Classes/Helpers/Validate.php"; | |||
include "Libs/Lazer/Classes/LazerException.php"; | |||
use Lazer\Classes\LazerException; | |||
use Lazer\Classes\Database; | |||
use Lazer\Classes\Relation; | |||
use Lazer\Classes\Helpers; | |||
/** | |||
* Core class of Lazer. | |||
* | |||
* There are classes to use JSON files like file database. | |||
* | |||
* Using style was inspired by ORM classes. | |||
* | |||
* @category Core | |||
* @author Grzegorz Kuźnik | |||
* @copyright (c) 2013, Grzegorz Kuźnik | |||
* @license http://opensource.org/licenses/MIT The MIT License | |||
* @link https://github.com/Greg0/Lazer-Database GitHub Repository | |||
*/ | |||
abstract class Core_Database implements \IteratorAggregate, \Countable { | |||
/** | |||
* Contain returned data from file as object or array of objects | |||
* @var mixed Data from table | |||
*/ | |||
protected $data; | |||
/** | |||
* Name of file (table) | |||
* @var string Name of table | |||
*/ | |||
protected $name; | |||
/** | |||
* Object with setted data | |||
* @var object Setted data | |||
*/ | |||
protected $set; | |||
/** | |||
* ID of current row if setted | |||
* @var integer Current ID | |||
*/ | |||
protected $currentId; | |||
/** | |||
* Key if current row if setted | |||
* @var integer Current key | |||
*/ | |||
protected $currentKey; | |||
/** | |||
* Pending functions with values | |||
* @see \Lazer\Classes\Core_Database::setPending() | |||
* @var array | |||
*/ | |||
protected $pending; | |||
/** | |||
* Information about to reset keys in array or not to | |||
* @var integer | |||
*/ | |||
protected $resetKeys = 1; | |||
/** | |||
* Factory pattern | |||
* @param string $name Name of table | |||
* @return \Lazer\Classes\Database | |||
* @throws LazerException If there's problems with load file | |||
*/ | |||
public static function table($name) | |||
{ | |||
Helpers\Validate::table($name)->exists(); | |||
$self = new Database; | |||
$self->name = $name; | |||
$self->setFields(); | |||
$self->setPending(); | |||
return $self; | |||
} | |||
/** | |||
* Get rows from table | |||
* @uses Lazer\Classes\Helpers\Data::get() to get data from file | |||
* @return array | |||
*/ | |||
protected function getData() | |||
{ | |||
return Helpers\Data::table($this->name)->get(); | |||
} | |||
/** | |||
* Setting data to Database::$data | |||
*/ | |||
protected function setData() | |||
{ | |||
$this->data = $this->getData(); | |||
} | |||
/** | |||
* Returns array key of row with specified ID | |||
* @param integer $id Row ID | |||
* @return integer Row key | |||
* @throws LazerException If there's no data with that ID | |||
*/ | |||
protected function getRowKey($id) | |||
{ | |||
foreach ($this->getData() as $key => $data) | |||
{ | |||
if ($data->id == $id) | |||
{ | |||
return $key; | |||
break; | |||
} | |||
} | |||
throw new LazerException('No data found with ID: ' . $id); | |||
} | |||
/** | |||
* Set NULL for currentId and currentKey | |||
*/ | |||
protected function clearKeyInfo() | |||
{ | |||
$this->currentId = $this->currentKey = NULL; | |||
} | |||
/** | |||
* Setting fields with default values | |||
* @uses Lazer\Classes\Helpers\Validate::isNumeric() to check if type of field is numeric | |||
*/ | |||
protected function setFields() | |||
{ | |||
$this->set = new \stdClass(); | |||
$schema = $this->schema(); | |||
foreach ($schema as $field => $type) | |||
{ | |||
if (Helpers\Validate::isNumeric($type) AND $field != 'id') | |||
{ | |||
$this->set->{$field} = 0; | |||
} | |||
else | |||
{ | |||
$this->set->{$field} = null; | |||
} | |||
} | |||
} | |||
/** | |||
* Set pending functions in right order with default values (Empty). | |||
*/ | |||
protected function setPending() | |||
{ | |||
$this->pending = array( | |||
'where' => array(), | |||
'orderBy' => array(), | |||
'limit' => array(), | |||
'with' => array(), | |||
'groupBy' => array(), | |||
); | |||
} | |||
/** | |||
* Clear info about previous queries | |||
*/ | |||
protected function clearQuery() | |||
{ | |||
$this->setPending(); | |||
$this->clearKeyInfo(); | |||
} | |||
/** | |||
* Validating fields and setting variables to current operations | |||
* @uses Lazer\Classes\Helpers\Validate::field() to check that field exist | |||
* @uses Lazer\Classes\Helpers\Validate::type() to check that field type is correct | |||
* @param string $name Field name | |||
* @param mixed $value Field value | |||
*/ | |||
public function __set($name, $value) | |||
{ | |||
if (Helpers\Validate::table($this->name)->field($name) && Helpers\Validate::table($this->name)->type($name, $value)) | |||
{ | |||
$this->set->{$name} = $value; | |||
} | |||
} | |||
/** | |||
* Returning variable from Object | |||
* @param string $name Field name | |||
* @return mixed Field value | |||
* @throws LazerException | |||
*/ | |||
public function __get($name) | |||
{ | |||
if (isset($this->set->{$name})) | |||
return $this->set->{$name}; | |||
throw new LazerException('There is no data'); | |||
} | |||
/** | |||
* Check if the given field exists | |||
* @param string $name Field name | |||
* @return boolean True if the field exists, false otherwise | |||
*/ | |||
public function __isset($name) | |||
{ | |||
return isset($this->set->{$name}); | |||
} | |||
/** | |||
* Execute pending functions | |||
*/ | |||
protected function pending() | |||
{ | |||
$this->setData(); | |||
foreach ($this->pending as $func => $args) | |||
{ | |||
if (!empty($args)) | |||
{ | |||
call_user_func(array($this, $func . 'Pending')); | |||
} | |||
} | |||
//clear pending values after executed query | |||
$this->clearQuery(); | |||
} | |||
/** | |||
* Creating new table | |||
* | |||
* For example few fields: | |||
* | |||
* Database::create('news', array( | |||
* 'title' => 'string', | |||
* 'content' => 'string', | |||
* 'rating' => 'double', | |||
* 'author' => 'integer' | |||
* )); | |||
* | |||
* Types of field: | |||
* - boolean | |||
* - integer | |||
* - string | |||
* - double (also for float type) | |||
* | |||
* ID field isn't required (it will be created automatically) but you can specify it at first place. | |||
* | |||
* @uses Lazer\Classes\Helpers\Data::arrToLower() to lower case keys and values of array | |||
* @uses Lazer\Classes\Helpers\Data::exists() to check if data file exists | |||
* @uses Lazer\Classes\Helpers\Config::exists() to check if config file exists | |||
* @uses Lazer\Classes\Helpers\Validate::types() to check if type of fields are correct | |||
* @uses Lazer\Classes\Helpers\Data::put() to save data file | |||
* @uses Lazer\Classes\Helpers\Config::put() to save config file | |||
* @param string $name Table name | |||
* @param array $fields Field configuration | |||
* @throws LazerException If table exist | |||
*/ | |||
public static function create($name, array $fields) | |||
{ | |||
$fields = Helpers\Validate::arrToLower($fields); | |||
if (Helpers\Data::table($name)->exists() && Helpers\Config::table($name)->exists()) | |||
{ | |||
throw new LazerException('helper\Table "' . $name . '" already exists'); | |||
} | |||
$types = array_values($fields); | |||
Helpers\Validate::types($types); | |||
if (!array_key_exists('id', $fields)) | |||
{ | |||
$fields = array('id' => 'integer') + $fields; | |||
} | |||
$data = new \stdClass(); | |||
$data->last_id = 0; | |||
$data->schema = $fields; | |||
$data->relations = new \stdClass(); | |||
Helpers\Data::table($name)->put(array()); | |||
Helpers\Config::table($name)->put($data); | |||
} | |||
/** | |||
* Removing table with config | |||
* @uses Lazer\Classes\Helpers\Data::remove() to remove data file | |||
* @uses Lazer\Classes\Helpers\Config::remove() to remove config file | |||
* @param string $name Table name | |||
* @return boolean|LazerException | |||
*/ | |||
public static function remove($name) | |||
{ | |||
if (Helpers\Data::table($name)->remove() && Helpers\Config::table($name)->remove()) | |||
{ | |||
return TRUE; | |||
} | |||
return FALSE; | |||
} | |||
/** | |||
* Grouping results by one field | |||
* @param string $column | |||
* @return \Lazer\Classes\Core_Database | |||
*/ | |||
public function groupBy($column) | |||
{ | |||
if (Helpers\Validate::table($this->name)->field($column)) | |||
{ | |||
$this->resetKeys = 0; | |||
$this->pending[__FUNCTION__] = $column; | |||
} | |||
return $this; | |||
} | |||
/** | |||
* Grouping array pending method | |||
*/ | |||
protected function groupByPending() | |||
{ | |||
$column = $this->pending['groupBy']; | |||
$grouped = array(); | |||
foreach ($this->data as $object) | |||
{ | |||
$grouped[$object->{$column}][] = $object; | |||
} | |||
$this->data = $grouped; | |||
} | |||
/** | |||
* JOIN other tables | |||
* @param string $table relations separated by : | |||
* @return \Lazer\Classes\Core_Database | |||
*/ | |||
public function with($table) | |||
{ | |||
$this->pending['with'][] = explode(':', $table); | |||
return $this; | |||
} | |||
/** | |||
* Pending function for with(), joining other tables to current | |||
*/ | |||
protected function withPending() | |||
{ | |||
$joins = $this->pending['with']; | |||
foreach ($joins as $join) | |||
{ | |||
$local = (count($join) > 1) ? array_slice($join, -2, 1)[0] : $this->name; | |||
$foreign = end($join); | |||
$relation = Relation::table($local)->with($foreign); | |||
$data = $this->data; | |||
foreach ($join as $part) | |||
{ | |||
$data = $relation->build($data, $part); | |||
} | |||
} | |||
} | |||
/** | |||
* Sorting data by field | |||
* @param string $key Field name | |||
* @param string $direction ASC|DESC | |||
* @return \Lazer\Classes\Core_Database | |||
*/ | |||
public function orderBy($key, $direction = 'ASC') | |||
{ | |||
if (Helpers\Validate::table($this->name)->field($key)) | |||
{ | |||
$directions = array( | |||
'ASC' => SORT_ASC, | |||
'DESC' => SORT_DESC | |||
); | |||
$this->pending[__FUNCTION__][$key] = isset($directions[$direction]) ? $directions[$direction] : 'ASC'; | |||
} | |||
return $this; | |||
} | |||
/** | |||
* Sort an array of objects by more than one field. | |||
* @ | |||
* @link http://blog.amnuts.com/2011/04/08/sorting-an-array-of-objects-by-one-or-more-object-property/ It's not mine algorithm | |||
*/ | |||
protected function orderByPending() | |||
{ | |||
$properties = $this->pending['orderBy']; | |||
uasort($this->data, function($a, $b) use ($properties) | |||
{ | |||
foreach ($properties as $column => $direction) | |||
{ | |||
if (is_int($column)) | |||
{ | |||
$column = $direction; | |||
$direction = SORT_ASC; | |||
} | |||
$collapse = function($node, $props) | |||
{ | |||
if (is_array($props)) | |||
{ | |||
foreach ($props as $prop) | |||
{ | |||
$node = (!isset($node->$prop)) ? null : $node->$prop; | |||
} | |||
return $node; | |||
} | |||
else | |||
{ | |||
return (!isset($node->$props)) ? null : $node->$props; | |||
} | |||
}; | |||
$aProp = $collapse($a, $column); | |||
$bProp = $collapse($b, $column); | |||
if ($aProp != $bProp) | |||
{ | |||
return ($direction == SORT_ASC) ? strnatcasecmp($aProp, $bProp) : strnatcasecmp($bProp, $aProp); | |||
} | |||
} | |||
return FALSE; | |||
}); | |||
} | |||
/** | |||
* Where function, like SQL | |||
* | |||
* Operators: | |||
* - Standard operators (=, !=, >, <, >=, <=) | |||
* - IN (only for array value) | |||
* - NOT IN (only for array value) | |||
* | |||
* @param string $field Field name | |||
* @param string $op Operator | |||
* @param mixed $value Field value | |||
* @return \Lazer\Classes\Core_Database | |||
*/ | |||
public function where($field, $op, $value) | |||
{ | |||
$this->pending['where'][] = array( | |||
'type' => 'and', | |||
'field' => $field, | |||
'op' => $op, | |||
'value' => $value, | |||
); | |||
return $this; | |||
} | |||
/** | |||
* Alias for where() | |||
* @param string $field Field name | |||
* @param string $op Operator | |||
* @param mixed $value Field value | |||
* @return \Lazer\Classes\Core_Database | |||
*/ | |||
public function andWhere($field, $op, $value) | |||
{ | |||
$this->where($field, $op, $value); | |||
return $this; | |||
} | |||
/** | |||
* Alias for where(), setting OR for searching | |||
* @param string $field Field name | |||
* @param string $op Operator | |||
* @param mixed $value Field value | |||
* @return \Lazer\Classes\Core_Database | |||
*/ | |||
public function orWhere($field, $op, $value) | |||
{ | |||
$this->pending['where'][] = array( | |||
'type' => 'or', | |||
'field' => $field, | |||
'op' => $op, | |||
'value' => $value, | |||
); | |||
return $this; | |||
} | |||
/** | |||
* Filter function for array_filter() in where() | |||
* @return boolean | |||
*/ | |||
protected function wherePending() | |||
{ | |||
$operator = array( | |||
'=' => '==', | |||
'!=' => '!=', | |||
'>' => '>', | |||
'<' => '<', | |||
'>=' => '>=', | |||
'<=' => '<=', | |||
'and' => '&&', | |||
'or' => '||' | |||
); | |||
$this->data = array_filter($this->data, function($row) use ($operator) | |||
{ | |||
$clause = ''; | |||
$result = true; | |||
foreach ($this->pending['where'] as $key => $condition) | |||
{ | |||
extract($condition); | |||
if (is_array($value) && $op == 'IN') | |||
{ | |||
$value = (in_array($row->{$field}, $value)) ? 1 : 0; | |||
$op = '=='; | |||
$field = 1; | |||
} | |||
elseif (!is_array($value) && in_array($op, array('LIKE', 'like'))) | |||
{ | |||
$regex = "/^" . str_replace('%', '(.*?)', preg_quote($value)) . "$/si"; | |||
$value = preg_match($regex, $row->{$field}); | |||
$op = '=='; | |||
$field = 1; | |||
} | |||
elseif (!is_array($value) && $op != 'IN') | |||
{ | |||
$value = is_string($value) ? | |||
'\'' . mb_strtolower($value) . '\'' : | |||
$value; | |||
$op = $operator[$op]; | |||
$field = is_string($row->{$field}) ? | |||
'mb_strtolower($row->' . $field .')' : | |||
'$row->' . $field; | |||
} | |||
$type = (!$key) ? | |||
null : | |||
$operator[$type]; | |||
$query = array($type, $field, $op, $value); | |||
$clause .= implode(' ', $query) . ' '; | |||
eval('$result = ' . $clause . ';'); | |||
} | |||
return $result; | |||
}); | |||
} | |||
/** | |||
* Returning data as indexed or assoc array. | |||
* @param string $key Field that will be the key, NULL for Indexed | |||
* @param string $value Field that will be the value | |||
* @return array | |||
*/ | |||
public function asArray($key = null, $value = null) | |||
{ | |||
if (!is_null($key)) | |||
{ | |||
Helpers\Validate::table($this->name)->field($key); | |||
} | |||
if (!is_null($value)) | |||
{ | |||
Helpers\Validate::table($this->name)->field($value); | |||
} | |||
$datas = array(); | |||
if (!$this->resetKeys) | |||
{ | |||
if (is_null($key) && is_null($value)) | |||
{ | |||
return $this->data; | |||
} | |||
else | |||
{ | |||
foreach ($this->data as $rowKey => $data) | |||
{ | |||
$datas[$rowKey] = array(); | |||
foreach ($data as $row) | |||
{ | |||
if (is_null($key)) | |||
{ | |||
$datas[$rowKey][] = $row->{$value}; | |||
} | |||
elseif (is_null($value)) | |||
{ | |||
$datas[$rowKey][$row->{$key}] = $row; | |||
} | |||
else | |||
{ | |||
$datas[$rowKey][$row->{$key}] = $row->{$value}; | |||
} | |||
} | |||
} | |||
} | |||
} | |||
else | |||
{ | |||
if (is_null($key) && is_null($value)) | |||
{ | |||
foreach ($this->data as $data) | |||
{ | |||
$datas[] = get_object_vars($data); | |||
} | |||
} | |||
else | |||
{ | |||
foreach ($this->data as $data) | |||
{ | |||
if (is_null($key)) | |||
{ | |||
$datas[] = $data->{$value}; | |||
} | |||
elseif (is_null($value)) | |||
{ | |||
$datas[$data->{$key}] = $data; | |||
} | |||
else | |||
{ | |||
$datas[$data->{$key}] = $data->{$value}; | |||
} | |||
} | |||
} | |||
} | |||
return $datas; | |||
} | |||
/** | |||
* Limit returned data | |||
* | |||
* Should be used at the end of chain, before end method | |||
* @param integer $number Limit number | |||
* @param integer $offset Offset number | |||
* @return \Lazer\Classes\Core_Database | |||
*/ | |||
public function limit($number, $offset = 0) | |||
{ | |||
$this->pending['limit'] = array( | |||
'offset' => $offset, | |||
'number' => $number | |||
); | |||
return $this; | |||
} | |||
/** | |||
* Pending function for limit() | |||
*/ | |||
protected function limitPending() | |||
{ | |||
$offset = $this->pending['limit']['offset']; | |||
$num = $this->pending['limit']['number']; | |||
$this->data = array_slice($this->data, $offset, $num); | |||
} | |||
/** | |||
* Add new fields to table, array schema like in create() function | |||
* @param array $fields Associative array | |||
*/ | |||
public function addFields(array $fields) | |||
{ | |||
$fields = Helpers\Validate::arrToLower($fields); | |||
Helpers\Validate::types(array_values($fields)); | |||
$schema = $this->schema(); | |||
$fields = array_diff_assoc($fields, $schema); | |||
if (!empty($fields)) | |||
{ | |||
$config = $this->config(); | |||
$config->schema = array_merge($schema, $fields); | |||
$data = $this->getData(); | |||
foreach ($data as $key => $object) | |||
{ | |||
foreach ($fields as $name => $type) | |||
{ | |||
if (Helpers\Validate::isNumeric($type)) | |||
$data[$key]->{$name} = 0; | |||
else | |||
$data[$key]->{$name} = null; | |||
} | |||
} | |||
Helpers\Data::table($this->name)->put($data); | |||
Helpers\Config::table($this->name)->put($config); | |||
} | |||
} | |||
/** | |||
* Delete fields from array | |||
* @param array $fields Indexed array | |||
*/ | |||
public function deleteFields(array $fields) | |||
{ | |||
$fields = Helpers\Validate::arrToLower($fields); | |||
Helpers\Validate::table($this->name)->fields($fields); | |||
$config = $this->config(); | |||
$config->schema = array_diff_key($this->schema(), array_flip($fields)); | |||
$data = $this->getData(); | |||
foreach ($data as $key => $object) | |||
{ | |||
foreach ($fields as $name) | |||
{ | |||
unset($data[$key]->{$name}); | |||
} | |||
} | |||
Helpers\Data::table($this->name)->put($data); | |||
Helpers\Config::table($this->name)->put($config); | |||
} | |||
/** | |||
* Returns table name | |||
* @return string table name | |||
*/ | |||
public function name() | |||
{ | |||
return $this->name; | |||
} | |||
/** | |||
* Returning object with config for table | |||
* @return object Config | |||
*/ | |||
public function config() | |||
{ | |||
return Helpers\Config::table($this->name)->get(); | |||
} | |||
/** | |||
* Return array with names of fields | |||
* @return array Fields | |||
*/ | |||
public function fields() | |||
{ | |||
return Helpers\Config::table($this->name)->fields(); | |||
} | |||
/** | |||
* Returning assoc array with types of fields | |||
* @return array Fields type | |||
*/ | |||
public function schema() | |||
{ | |||
return Helpers\Config::table($this->name)->schema(); | |||
} | |||
/** | |||
* Returning assoc array with relationed tables | |||
* @param string|null $tableName | |||
* @return array Fields type | |||
*/ | |||
public function relations($tableName = null) | |||
{ | |||
return Helpers\Config::table($this->name)->relations($tableName, true); | |||
} | |||
/** | |||
* Returning last ID from table | |||
* @return integer Last ID | |||
*/ | |||
public function lastId() | |||
{ | |||
return Helpers\Config::table($this->name)->lastId(); | |||
} | |||
/** | |||
* Saving inserted or updated data | |||
*/ | |||
public function save() | |||
{ | |||
$data = $this->getData(); | |||
if (!$this->currentId) | |||
{ | |||
$config = $this->config(); | |||
$config->last_id++; | |||
$this->set->id = $config->last_id; | |||
array_push($data, $this->set); | |||
Helpers\Config::table($this->name)->put($config); | |||
} | |||
else | |||
{ | |||
$this->set->id = $this->currentId; | |||
$data[$this->currentKey] = $this->set; | |||
} | |||
Helpers\Data::table($this->name)->put($data); | |||
// $this->setFields(); | |||
} | |||
/** | |||
* Deleting loaded data | |||
* @return boolean | |||
*/ | |||
public function delete() | |||
{ | |||
$data = $this->getData(); | |||
if (isset($this->currentId)) | |||
{ | |||
unset($data[$this->currentKey]); | |||
} | |||
else | |||
{ | |||
$this->pending(); | |||
$old = $data; | |||
$data = array_diff_key($old, $this->data); | |||
} | |||
$this->data = array_values($data); | |||
return Helpers\Data::table($this->name)->put($this->data) ? true : false; | |||
} | |||
/** | |||
* Return count in integer or array of integers (if grouped) | |||
* @return mixed | |||
*/ | |||
public function count() | |||
{ | |||
if (!$this->resetKeys) | |||
{ | |||
$count = array(); | |||
foreach ($this->data as $group => $data) | |||
{ | |||
$count[$group] = count($data); | |||
} | |||
} | |||
else | |||
{ | |||
$count = count($this->data); | |||
} | |||
return $count; | |||
} | |||
/** | |||
* Returns one row with specified ID | |||
* @param integer $id Row ID | |||
* @return \Lazer\Classes\Core_Database | |||
*/ | |||
public function find($id = NULL) | |||
{ | |||
if ($id !== NULL) | |||
{ | |||
$data = $this->getData(); | |||
$this->currentId = $id; | |||
$this->currentKey = $this->getRowKey($id); | |||
foreach ($data[$this->currentKey] as $field => $value) | |||
{ | |||
$this->set->{$field} = $value; | |||
} | |||
} | |||
else | |||
{ | |||
$this->limit(1)->findAll(); | |||
$data = $this->data; | |||
if (count($data)) | |||
{ | |||
foreach ($data[0] as $field => $value) | |||
{ | |||
$this->set->{$field} = $value; | |||
} | |||
$this->currentId = $this->set->id; | |||
$this->currentKey = $this->getRowKey($this->currentId); | |||
} | |||
} | |||
return clone $this; | |||
} | |||
/** | |||
* Make data ready to read | |||
*/ | |||
public function findAll() | |||
{ | |||
$this->pending(); | |||
$this->data = $this->resetKeys ? array_values($this->data) : $this->data; | |||
return clone $this; | |||
} | |||
/** | |||
* Iterator for Data | |||
* @return \ArrayIterator | |||
*/ | |||
public function getIterator() | |||
{ | |||
return new \ArrayIterator($this->data); | |||
} | |||
/** | |||
* Debug functions, prints whole query with values | |||
*/ | |||
public function debug() | |||
{ | |||
$print = "Lazer::table(" . $this->name . ")\n"; | |||
foreach ($this->pending as $function => $values) | |||
{ | |||
if (!empty($values)) | |||
{ | |||
if (is_array($values)) | |||
{ | |||
if (is_array(reset($values))) | |||
{ | |||
foreach ($values as $value) | |||
{ | |||
if ($function == 'where') | |||
{ | |||
array_shift($value); | |||
} | |||
if ($function == 'with') | |||
{ | |||
$params = implode(':', $value); | |||
} | |||
else | |||
{ | |||
$params = implode(', ', $value); | |||
} | |||
$print .= "\t" . '->' . $function . '(' . $params . ')' . "\n"; | |||
} | |||
} | |||
else | |||
{ | |||
$params = implode(', ', $values); | |||
$print .= "\t" . '->' . $function . '(' . $params . ')' . "\n"; | |||
} | |||
} | |||
else | |||
{ | |||
$print .= "\t" . '->' . $function . '(' . $values . ')' . "\n"; | |||
} | |||
} | |||
} | |||
echo '<pre>' . print_r($print, true) . '</pre>'; | |||
$this->clearQuery(); | |||
} | |||
} |
@@ -0,0 +1,394 @@ | |||
<?php | |||
namespace Lazer\Classes; | |||
use Lazer\Classes\Helpers\Validate; | |||
use Lazer\Classes\Helpers\Config; | |||
use Lazer\Classes\Database; | |||
use Lazer\Classes\LazerException; | |||
/** | |||
* Relation class of LAZER project. | |||
* | |||
* @category Core | |||
* @author Grzegorz Kuźnik | |||
* @copyright (c) 2013, Grzegorz Kuźnik | |||
* @license http://opensource.org/licenses/MIT The MIT License | |||
* @link https://github.com/Greg0/Lazer-Database GitHub Repository | |||
*/ | |||
abstract class Core_Relation { | |||
/** | |||
* Tables names | |||
* @var array tables | |||
*/ | |||
protected $tables = array( | |||
'local' => null, | |||
'foreign' => null | |||
); | |||
/** | |||
* Relation keys names | |||
* @var array keys | |||
*/ | |||
protected $keys = array( | |||
'local' => null, | |||
'foreign' => null | |||
); | |||
/** | |||
* Current relation type | |||
* @var string | |||
*/ | |||
protected $relationType; | |||
/** | |||
* All relations types | |||
* @var array | |||
*/ | |||
protected static $relations = array('belongsTo', 'hasMany', 'hasAndBelongsToMany'); | |||
/** | |||
* Factory method | |||
* @param string $name Name of table | |||
* @return \Lazer\Classes\Relation | |||
*/ | |||
public static function table($name) | |||
{ | |||
Validate::table($name)->exists(); | |||
$self = new Relation; | |||
$self->tables['local'] = $name; | |||
return $self; | |||
} | |||
/** | |||
* Getter of junction table name in many2many relation | |||
* @return boolean|string Name of junction table or false | |||
*/ | |||
public function getJunction() | |||
{ | |||
if ($this->relationType == 'hasAndBelongsToMany') | |||
{ | |||
$tables = $this->tables; | |||
sort($tables); | |||
return implode('_', $tables); | |||
} | |||
return false; | |||
} | |||
/** | |||
* Set relation type to field | |||
* @param string $relation Name of relation | |||
*/ | |||
protected function setRelationType($relation) | |||
{ | |||
Validate::relationType($relation); | |||
$this->relationType = $relation; | |||
} | |||
/** | |||
* Set table name | |||
* @param string $type local or foreign | |||
* @param string $name table name | |||
*/ | |||
protected function setTable($type, $name) | |||
{ | |||
Validate::table($name)->exists(); | |||
$this->tables[$type] = $name; | |||
} | |||
/** | |||
* Set key name | |||
* @param string $type local or foreign | |||
* @param string $key key name | |||
* @return \Lazer\Classes\Core_Relation | |||
* @throws LazerException First you must define tables name | |||
*/ | |||
protected function setKey($type, $key) | |||
{ | |||
if (!in_array(null, $this->tables)) | |||
{ | |||
Validate::table($this->tables[$type])->field($key); | |||
$this->keys[$type] = $key; | |||
return $this; | |||
} | |||
throw new LazerException('First you must define tables name'); | |||
} | |||
/** | |||
* Set local key name | |||
* @param string $key key name | |||
* @return \Lazer\Classes\Core_Relation | |||
* @throws LazerException First you must define tables name | |||
*/ | |||
public function localKey($key) | |||
{ | |||
return $this->setKey('local', $key); | |||
} | |||
/** | |||
* Set foreign key name | |||
* @param string $key key name | |||
* @return \Lazer\Classes\Core_Relation | |||
* @throws LazerException First you must define tables name | |||
*/ | |||
public function foreignKey($key) | |||
{ | |||
return $this->setKey('foreign', $key); | |||
} | |||
/** | |||
* Set relation one2many to table | |||
* @param string $table Table name | |||
* @return \Lazer\Classes\Core_Relation | |||
*/ | |||
public function belongsTo($table) | |||
{ | |||
$this->setTable('foreign', $table); | |||
$this->setRelationType(__FUNCTION__); | |||
return $this; | |||
} | |||
/** | |||
* Set relation many2one to table | |||
* @param string $table Table name | |||
* @return \Lazer\Classes\Core_Relation | |||
*/ | |||
public function hasMany($table) | |||
{ | |||
$this->setTable('foreign', $table); | |||
$this->setRelationType(__FUNCTION__); | |||
return $this; | |||
} | |||
/** | |||
* Set relation many2many to table | |||
* @param string $table Table name | |||
* @return \Lazer\Classes\Core_Relation | |||
*/ | |||
public function hasAndBelongsToMany($table) | |||
{ | |||
$this->setTable('foreign', $table); | |||
$this->setRelationType(__FUNCTION__); | |||
return $this; | |||
} | |||
/** | |||
* Use relation to table | |||
* @param string $table Table name | |||
* @return \Lazer\Classes\Core_Relation | |||
*/ | |||
public function with($table) | |||
{ | |||
Validate::relation($this->tables['local'], $table); | |||
$this->setTable('foreign', $table); | |||
$this->setRelationType(Config::table($this->tables['local'])->relations($this->tables['foreign'])->type); | |||
$this->setKey('local', Config::table($this->tables['local'])->relations($this->tables['foreign'])->keys->local); | |||
$this->setKey('foreign', Config::table($this->tables['local'])->relations($this->tables['foreign'])->keys->foreign); | |||
return $this; | |||
} | |||
/** | |||
* Set specified relation | |||
* @throws LazerException Tables names or keys missing | |||
*/ | |||
public function setRelation() | |||
{ | |||
if (!in_array(null, $this->tables) && !in_array(null, $this->keys)) | |||
{ | |||
$this->addRelation(); | |||
return true; | |||
} | |||
else | |||
{ | |||
throw new LazerException('Tables names or keys missing'); | |||
} | |||
} | |||
/** | |||
* Get relation information | |||
* @return array relation information | |||
*/ | |||
public function getRelation() | |||
{ | |||
return array( | |||
'tables' => $this->tables, | |||
'keys' => $this->keys, | |||
'type' => $this->relationType | |||
); | |||
} | |||
/** | |||
* Remove relation | |||
*/ | |||
public function removeRelation() | |||
{ | |||
if ($this->relationType == 'hasAndBelongsToMany') | |||
{ | |||
$junction = $this->getJunction(); | |||
$this->deleteRelationData($junction, $this->tables['local']); | |||
$this->deleteRelationData($junction, $this->tables['foreign']); | |||
} | |||
$this->deleteRelationData($this->tables['local'], $this->tables['foreign']); | |||
} | |||
/** | |||
* Add data to configs and create all necessary files | |||
*/ | |||
protected function addRelation() | |||
{ | |||
if ($this->relationType == 'hasAndBelongsToMany') | |||
{ | |||
$junction = $this->getJunction(); | |||
try | |||
{ | |||
Validate::table($junction)->exists(); | |||
} | |||
catch (LazerException $e) | |||
{ | |||
Database::create($junction, array( | |||
$this->tables['local'] . '_id' => 'integer', | |||
$this->tables['foreign'] . '_id' => 'integer', | |||
)); | |||
$this->insertRelationData($junction, $this->tables['local'], 'hasMany', array( | |||
'local' => $this->tables['local'] . '_id', | |||
'foreign' => $this->keys['local'] | |||
)); | |||
$this->insertRelationData($junction, $this->tables['foreign'], 'hasMany', array( | |||
'local' => $this->tables['foreign'] . '_id', | |||
'foreign' => $this->keys['foreign'] | |||
)); | |||
} | |||
} | |||
$this->insertRelationData($this->tables['local'], $this->tables['foreign'], $this->relationType, $this->keys); | |||
} | |||
/** | |||
* Inserts relation data to config file | |||
* @param string $from Local table | |||
* @param string $to Related table | |||
* @param string $type Relation type | |||
* @param array $keys Relationed keys | |||
*/ | |||
protected function insertRelationData($from, $to, $type, array $keys) | |||
{ | |||
$config = Config::table($from); | |||
$content = $config->get(); | |||
$content->relations->{$to} = array( | |||
'type' => $type, | |||
'keys' => $keys, | |||
); | |||
$config->put($content); | |||
} | |||
/** | |||
* Inserts relation data to config file | |||
* @param string $from Local table | |||
* @param string $to Related table | |||
*/ | |||
protected function deleteRelationData($from, $to) | |||
{ | |||
$config = Config::table($from); | |||
$content = $config->get(); | |||
unset($content->relations->{$to}); | |||
$config->put($content); | |||
} | |||
/** | |||
* Process query with joined data | |||
* @param object $row One row of data | |||
* @return Database | |||
*/ | |||
protected function join($row) | |||
{ | |||
$keys['local'] = $this->keys['local']; | |||
$keys['foreign'] = $this->keys['foreign']; | |||
if ($this->relationType == 'hasAndBelongsToMany') | |||
{ | |||
$join = Database::table($this->getJunction()) | |||
->groupBy($this->tables['local'] . '_id') | |||
->where($this->tables['local'] . '_id', '=', $row->{$keys['local']}) | |||
->findAll() | |||
->asArray(null, $this->tables['foreign'] . '_id'); | |||
if (empty($join)) | |||
return array(); | |||
return Database::table($this->tables['foreign']) | |||
->where($keys['foreign'], 'IN', $join[$row->{$keys['local']}]); | |||
} | |||
return Database::table($this->tables['foreign']) | |||
->where($keys['foreign'], '=', $row->{$keys['local']}); | |||
} | |||
/** | |||
* | |||
* @param array $array | |||
* @param string $part | |||
* @return array | |||
*/ | |||
public function build(array $array, $part) | |||
{ | |||
$return = array(); | |||
foreach ($array as $key => $row) | |||
{ | |||
if (is_object($row)) | |||
{ | |||
if ($row instanceof \stdClass) | |||
{ | |||
$part = ucfirst($part); | |||
if (!isset($row->{$part})) | |||
{ | |||
$query = $this->join($row); | |||
if ($this->relationType == 'belongsTo') | |||
{ | |||
$query = $query->findAll(); | |||
$query = reset($query)[0]; | |||
} | |||
$row->{$part} = $query; | |||
} | |||
$array[$key] = $row->{$part}; | |||
$return[] = $row->{$part}; | |||
} | |||
else | |||
{ | |||
$row->with($part); | |||
} | |||
} | |||
else | |||
{ | |||
$return = array_merge($return, $this->build($row, $part)); | |||
} | |||
} | |||
return $return; | |||
} | |||
/** | |||
* Get relations types | |||
* @return array | |||
*/ | |||
public static function relations() | |||
{ | |||
return self::$relations; | |||
} | |||
} |
@@ -0,0 +1,9 @@ | |||
<?php | |||
namespace Lazer\Classes; | |||
include "Core/Database.php"; | |||
class Database extends Core_Database { | |||
} |
@@ -0,0 +1,91 @@ | |||
<?php | |||
namespace Lazer\Classes\Helpers; | |||
/** | |||
* Config managing class | |||
* | |||
* @category Helpers | |||
* @author Grzegorz Kuźnik | |||
* @copyright (c) 2013, Grzegorz Kuźnik | |||
* @license http://opensource.org/licenses/MIT The MIT License | |||
* @link https://github.com/Greg0/Lazer-Database GitHub Repository | |||
*/ | |||
class Config extends File { | |||
/** | |||
* Get key from returned config | |||
* @param string $field key | |||
* @param bool $assoc | |||
* @return mixed | |||
*/ | |||
public function getKey($field, $assoc = false) | |||
{ | |||
return $assoc ? $this->get($assoc)[$field] : $this->get($assoc)->{$field}; | |||
} | |||
public static function table($name) | |||
{ | |||
$file = new Config; | |||
$file->name = $name; | |||
$file->setType('config'); | |||
return $file; | |||
} | |||
/** | |||
* Return array with names of fields | |||
* @return array | |||
*/ | |||
public function fields() | |||
{ | |||
return array_keys($this->getKey('schema', true)); | |||
} | |||
/** | |||
* Return relations configure | |||
* @param mixed $tableName null-all tables;array-few tables;string-one table relation informations | |||
* @param boolean $assoc Object or associative array | |||
* @return array|object | |||
*/ | |||
public function relations($tableName = null, $assoc = false) | |||
{ | |||
if (is_array($tableName)) | |||
{ | |||
$relations = $this->getKey('relations', $assoc); | |||
if ($assoc) | |||
{ | |||
return array_intersect_key($relations, array_flip($tableName)); | |||
} | |||
else | |||
{ | |||
return (object) array_intersect_key((array) $relations, array_flip($tableName)); | |||
} | |||
} | |||
elseif ($tableName !== null) | |||
{ | |||
return $assoc ? $this->getKey('relations', $assoc)[$tableName] : $this->getKey('relations', $assoc)->{$tableName}; | |||
} | |||
return $this->getKey('relations', $assoc); | |||
} | |||
/** | |||
* Returning assoc array with types of fields | |||
* @return array | |||
*/ | |||
public function schema() | |||
{ | |||
return $this->getKey('schema', true); | |||
} | |||
/** | |||
* Returning last ID from table | |||
* @return integer | |||
*/ | |||
public function lastId() | |||
{ | |||
return $this->getKey('last_id'); | |||
} | |||
} |
@@ -0,0 +1,27 @@ | |||
<?php | |||
namespace Lazer\Classes\Helpers; | |||
include "File.class.php"; | |||
/** | |||
* Data managing class | |||
* | |||
* @category Helpers | |||
* @author Grzegorz Kuźnik | |||
* @copyright (c) 2013, Grzegorz Kuźnik | |||
* @license http://opensource.org/licenses/MIT The MIT License | |||
* @link https://github.com/Greg0/Lazer-Database GitHub Repository | |||
*/ | |||
class Data extends File { | |||
public static function table($name) | |||
{ | |||
$file = new Data; | |||
$file->name = $name; | |||
$file->setType('data'); | |||
return $file; | |||
} | |||
} |
@@ -0,0 +1,88 @@ | |||
<?php | |||
namespace Lazer\Classes\Helpers; | |||
include "FileInterface.php"; | |||
use Lazer\Classes\LazerException; | |||
/** | |||
* File managing class | |||
* | |||
* @category Helpers | |||
* @author Grzegorz Kuźnik | |||
* @copyright (c) 2013, Grzegorz Kuźnik | |||
* @license http://opensource.org/licenses/MIT The MIT License | |||
* @link https://github.com/Greg0/Lazer-Database GitHub Repository | |||
*/ | |||
class File implements FileInterface { | |||
/** | |||
* File name | |||
* @var string | |||
*/ | |||
protected $name; | |||
/** | |||
* File type (data|config) | |||
* @var string | |||
*/ | |||
protected $type; | |||
public static function table($name) | |||
{ | |||
$file = new File; | |||
$file->name = $name; | |||
return $file; | |||
} | |||
public final function setType($type) | |||
{ | |||
$this->type = $type; | |||
} | |||
public final function getPath() | |||
{ | |||
if (!defined('LAZER_DATA_PATH')) | |||
{ | |||
throw new LazerException('Please define constant LAZER_DATA_PATH (check README.md)'); | |||
} | |||
else if (!empty($this->type)) | |||
{ | |||
return LAZER_DATA_PATH . $this->name . '.' . $this->type . '.json'; | |||
} | |||
else | |||
{ | |||
throw new LazerException('Please specify the type of file in class: ' . __CLASS__); | |||
} | |||
} | |||
public final function get($assoc = false) | |||
{ | |||
return json_decode(file_get_contents($this->getPath()), $assoc); | |||
} | |||
public final function put($data) | |||
{ | |||
return file_put_contents($this->getPath(), json_encode($data)); | |||
} | |||
public final function exists() | |||
{ | |||
return file_exists($this->getPath()); | |||
} | |||
public final function remove() | |||
{ | |||
$type = ucfirst($this->type); | |||
if ($this->exists()) | |||
{ | |||
if (unlink($this->getPath())) | |||
return TRUE; | |||
throw new LazerException($type . ': Deleting failed'); | |||
} | |||
throw new LazerException($type . ': File does not exists'); | |||
} | |||
} |
@@ -0,0 +1,55 @@ | |||
<?php | |||
namespace Lazer\Classes\Helpers; | |||
use Lazer\Classes\LazerException; | |||
interface FileInterface { | |||
/** | |||
* Setting name of table | |||
* @param string $name | |||
* @return File | |||
*/ | |||
public static function table($name); | |||
/** | |||
* Set the file type | |||
* @param string $type File type (data|config) | |||
*/ | |||
public function setType($type); | |||
/** | |||
* Returning path to file | |||
* @return string Path to file | |||
* @throws LazerException You must specify the type of file | |||
*/ | |||
public function getPath(); | |||
/** | |||
* Return decoded JSON | |||
* @param boolean $assoc Returns object if false; array if true | |||
* @return mixed (object|array) | |||
*/ | |||
public function get($assoc = false); | |||
/** | |||
* Saving encoded JSON to file | |||
* @param object|array $data | |||
* @return boolean | |||
*/ | |||
public function put($data); | |||
/** | |||
* Checking that file exists | |||
* @return boolean | |||
*/ | |||
public function exists(); | |||
/** | |||
* Removing file | |||
* @return boolean | |||
* @throws LazerException If file doesn't exists or there's problems with deleting files | |||
*/ | |||
public function remove(); | |||
} |
@@ -0,0 +1,207 @@ | |||
<?php | |||
namespace Lazer\Classes\Helpers; | |||
use Lazer\Classes\LazerException; | |||
use Lazer\Classes\Relation; | |||
/** | |||
* Validation for tables | |||
* | |||
* @category Helpers | |||
* @author Grzegorz Kuźnik | |||
* @copyright (c) 2013, Grzegorz Kuźnik | |||
* @license http://opensource.org/licenses/MIT The MIT License | |||
* @link https://github.com/Greg0/Lazer-Database GitHub Repository | |||
*/ | |||
class Validate { | |||
/** | |||
* Name of table | |||
* @var string | |||
*/ | |||
private $name; | |||
/** | |||
* Table name | |||
* @param string $name | |||
* @return Validate | |||
*/ | |||
public static function table($name) | |||
{ | |||
$validate = new Validate(); | |||
$validate->name = $name; | |||
return $validate; | |||
} | |||
/** | |||
* Checking that field type is numeric | |||
* @param string $type | |||
* @return boolean | |||
*/ | |||
public static function isNumeric($type) | |||
{ | |||
$defined = array('integer', 'double'); | |||
if (in_array($type, $defined)) | |||
{ | |||
return TRUE; | |||
} | |||
return FALSE; | |||
} | |||
/** | |||
* Checking that types from array matching with [boolean, integer, string, double] | |||
* @param array $types Indexed array | |||
* @return bool | |||
* @throws LazerException | |||
*/ | |||
public static function types(array $types) | |||
{ | |||
$defined = array('boolean', 'integer', 'string', 'double'); | |||
$diff = array_diff($types, $defined); | |||
if (empty($diff)) | |||
{ | |||
return TRUE; | |||
} | |||
throw new LazerException('Wrong types: "' . implode(', ', $diff) . '". Available "boolean, integer, string, double"'); | |||
} | |||
/** | |||
* Delete ID field from arrays | |||
* @param array $fields | |||
* @return array Fields without ID | |||
*/ | |||
public static function filter(array $fields) | |||
{ | |||
if (array_values($fields) === $fields) | |||
{ | |||
if (($key = array_search('id', $fields)) !== false) | |||
{ | |||
unset($fields[$key]); | |||
} | |||
} | |||
else | |||
{ | |||
unset($fields['id']); | |||
} | |||
return $fields; | |||
} | |||
/** | |||
* Change keys and values case to lower | |||
* @param array $array | |||
* @return array | |||
*/ | |||
public static function arrToLower(array $array) | |||
{ | |||
$array = array_change_key_case($array); | |||
$array = array_map('strtolower', $array); | |||
return $array; | |||
} | |||
/** | |||
* Checking that typed fields really exist in table | |||
* @param array $fields Indexed array | |||
* @return boolean | |||
* @throws LazerException If field(s) does not exist | |||
*/ | |||
public function fields(array $fields) | |||
{ | |||
$fields = self::filter($fields); | |||
$diff = array_diff($fields, Config::table($this->name)->fields()); | |||
if (empty($diff)) | |||
{ | |||
return TRUE; | |||
} | |||
throw new LazerException('Field(s) "' . implode(', ', $diff) . '" does not exists in table "' . $this->name . '"'); | |||
} | |||
/** | |||
* Checking that typed field really exist in table | |||
* @param string $name | |||
* @return boolean | |||
* @throws LazerException If field does not exist | |||
*/ | |||
public function field($name) | |||
{ | |||
if (in_array($name, Config::table($this->name)->fields())) | |||
{ | |||
return TRUE; | |||
} | |||
throw new LazerException('Field ' . $name . ' does not exists in table "' . $this->name . '"'); | |||
} | |||
/** | |||
* Checking that Table and Config exists and throw exceptions if not | |||
* @return boolean | |||
* @throws LazerException | |||
*/ | |||
public function exists() | |||
{ | |||
if (!Data::table($this->name)->exists()) | |||
throw new LazerException('Table "' . $this->name . '" does not exists'); | |||
if (!Config::table($this->name)->exists()) | |||
throw new LazerException('Config "' . $this->name . '" does not exists'); | |||
return TRUE; | |||
} | |||
/** | |||
* Checking that typed field have correct type of value | |||
* @param string $name | |||
* @param mixed $value | |||
* @return boolean | |||
* @throws LazerException If type is wrong | |||
*/ | |||
public function type($name, $value) | |||
{ | |||
$schema = Config::table($this->name)->schema(); | |||
if (array_key_exists($name, $schema) && $schema[$name] == gettype($value)) | |||
{ | |||
return TRUE; | |||
} | |||
throw new LazerException('Wrong data type'); | |||
} | |||
/** | |||
* Checking that relation between tables exists | |||
* @param string $local local table | |||
* @param string $foreign related table | |||
* @return bool relation exists | |||
* @throws LazerException | |||
*/ | |||
public static function relation($local, $foreign) | |||
{ | |||
$relations = Config::table($local)->relations(); | |||
if (isset($relations->{$foreign})) | |||
{ | |||
return TRUE; | |||
} | |||
throw new LazerException('Relation "' . $local . '" to "' . $foreign . '" doesn\'t exist'); | |||
} | |||
/** | |||
* Checking that relation type is correct | |||
* @param string $type | |||
* @return bool relation type | |||
* @throws LazerException Wrong relation type | |||
*/ | |||
public static function relationType($type) | |||
{ | |||
if (in_array($type, Relation::relations())) | |||
{ | |||
return true; | |||
} | |||
throw new LazerException('Wrong relation type'); | |||
} | |||
} |
@@ -0,0 +1,14 @@ | |||
<?php | |||
namespace Lazer\Classes; | |||
/** | |||
* Exception extend | |||
* | |||
* @category Exceptions | |||
* @author Grzegorz Kuźnik | |||
* @copyright (c) 2013, Grzegorz Kuźnik | |||
*/ | |||
class LazerException extends \Exception { | |||
} |
@@ -0,0 +1,9 @@ | |||
<?php | |||
namespace Lazer\Classes; | |||
include "Core/Relation.php"; | |||
class Relation extends Core_Relation { | |||
} |
@@ -0,0 +1,347 @@ | |||
<?php | |||
/* | |||
Copyright (c) 2008 Sebastián Grignoli | |||
All rights reserved. | |||
Redistribution and use in source and binary forms, with or without | |||
modification, are permitted provided that the following conditions | |||
are met: | |||
1. Redistributions of source code must retain the above copyright | |||
notice, this list of conditions and the following disclaimer. | |||
2. Redistributions in binary form must reproduce the above copyright | |||
notice, this list of conditions and the following disclaimer in the | |||
documentation and/or other materials provided with the distribution. | |||
3. Neither the name of copyright holders nor the names of its | |||
contributors may be used to endorse or promote products derived | |||
from this software without specific prior written permission. | |||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |||
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | |||
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |||
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS OR CONTRIBUTORS | |||
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |||
POSSIBILITY OF SUCH DAMAGE. | |||
*/ | |||
/** | |||
* @author "Sebastián Grignoli" <grignoli@gmail.com> | |||
* @package Encoding | |||
* @version 2.0 | |||
* @link https://github.com/neitanod/forceutf8 | |||
* @example https://github.com/neitanod/forceutf8 | |||
* @license Revised BSD | |||
*/ | |||
namespace ForceUTF8; | |||
class Encoding { | |||
const ICONV_TRANSLIT = "TRANSLIT"; | |||
const ICONV_IGNORE = "IGNORE"; | |||
const WITHOUT_ICONV = ""; | |||
protected static $win1252ToUtf8 = array( | |||
128 => "\xe2\x82\xac", | |||
130 => "\xe2\x80\x9a", | |||
131 => "\xc6\x92", | |||
132 => "\xe2\x80\x9e", | |||
133 => "\xe2\x80\xa6", | |||
134 => "\xe2\x80\xa0", | |||
135 => "\xe2\x80\xa1", | |||
136 => "\xcb\x86", | |||
137 => "\xe2\x80\xb0", | |||
138 => "\xc5\xa0", | |||
139 => "\xe2\x80\xb9", | |||
140 => "\xc5\x92", | |||
142 => "\xc5\xbd", | |||
145 => "\xe2\x80\x98", | |||
146 => "\xe2\x80\x99", | |||
147 => "\xe2\x80\x9c", | |||
148 => "\xe2\x80\x9d", | |||
149 => "\xe2\x80\xa2", | |||
150 => "\xe2\x80\x93", | |||
151 => "\xe2\x80\x94", | |||
152 => "\xcb\x9c", | |||
153 => "\xe2\x84\xa2", | |||
154 => "\xc5\xa1", | |||
155 => "\xe2\x80\xba", | |||
156 => "\xc5\x93", | |||
158 => "\xc5\xbe", | |||
159 => "\xc5\xb8" | |||
); | |||
protected static $brokenUtf8ToUtf8 = array( | |||
"\xc2\x80" => "\xe2\x82\xac", | |||
"\xc2\x82" => "\xe2\x80\x9a", | |||
"\xc2\x83" => "\xc6\x92", | |||
"\xc2\x84" => "\xe2\x80\x9e", | |||
"\xc2\x85" => "\xe2\x80\xa6", | |||
"\xc2\x86" => "\xe2\x80\xa0", | |||
"\xc2\x87" => "\xe2\x80\xa1", | |||
"\xc2\x88" => "\xcb\x86", | |||
"\xc2\x89" => "\xe2\x80\xb0", | |||
"\xc2\x8a" => "\xc5\xa0", | |||
"\xc2\x8b" => "\xe2\x80\xb9", | |||
"\xc2\x8c" => "\xc5\x92", | |||
"\xc2\x8e" => "\xc5\xbd", | |||
"\xc2\x91" => "\xe2\x80\x98", | |||
"\xc2\x92" => "\xe2\x80\x99", | |||
"\xc2\x93" => "\xe2\x80\x9c", | |||
"\xc2\x94" => "\xe2\x80\x9d", | |||
"\xc2\x95" => "\xe2\x80\xa2", | |||
"\xc2\x96" => "\xe2\x80\x93", | |||
"\xc2\x97" => "\xe2\x80\x94", | |||
"\xc2\x98" => "\xcb\x9c", | |||
"\xc2\x99" => "\xe2\x84\xa2", | |||
"\xc2\x9a" => "\xc5\xa1", | |||
"\xc2\x9b" => "\xe2\x80\xba", | |||
"\xc2\x9c" => "\xc5\x93", | |||
"\xc2\x9e" => "\xc5\xbe", | |||
"\xc2\x9f" => "\xc5\xb8" | |||
); | |||
protected static $utf8ToWin1252 = array( | |||
"\xe2\x82\xac" => "\x80", | |||
"\xe2\x80\x9a" => "\x82", | |||
"\xc6\x92" => "\x83", | |||
"\xe2\x80\x9e" => "\x84", | |||
"\xe2\x80\xa6" => "\x85", | |||
"\xe2\x80\xa0" => "\x86", | |||
"\xe2\x80\xa1" => "\x87", | |||
"\xcb\x86" => "\x88", | |||
"\xe2\x80\xb0" => "\x89", | |||
"\xc5\xa0" => "\x8a", | |||
"\xe2\x80\xb9" => "\x8b", | |||
"\xc5\x92" => "\x8c", | |||
"\xc5\xbd" => "\x8e", | |||
"\xe2\x80\x98" => "\x91", | |||
"\xe2\x80\x99" => "\x92", | |||
"\xe2\x80\x9c" => "\x93", | |||
"\xe2\x80\x9d" => "\x94", | |||
"\xe2\x80\xa2" => "\x95", | |||
"\xe2\x80\x93" => "\x96", | |||
"\xe2\x80\x94" => "\x97", | |||
"\xcb\x9c" => "\x98", | |||
"\xe2\x84\xa2" => "\x99", | |||
"\xc5\xa1" => "\x9a", | |||
"\xe2\x80\xba" => "\x9b", | |||
"\xc5\x93" => "\x9c", | |||
"\xc5\xbe" => "\x9e", | |||
"\xc5\xb8" => "\x9f" | |||
); | |||
static function toUTF8($text){ | |||
/** | |||
* Function \ForceUTF8\Encoding::toUTF8 | |||
* | |||
* This function leaves UTF8 characters alone, while converting almost all non-UTF8 to UTF8. | |||
* | |||
* It assumes that the encoding of the original string is either Windows-1252 or ISO 8859-1. | |||
* | |||
* It may fail to convert characters to UTF-8 if they fall into one of these scenarios: | |||
* | |||
* 1) when any of these characters: ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞß | |||
* are followed by any of these: ("group B") | |||
* ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶•¸¹º»¼½¾¿ | |||
* For example: %ABREPRESENT%C9%BB. «REPRESENTÉ» | |||
* The "«" (%AB) character will be converted, but the "É" followed by "»" (%C9%BB) | |||
* is also a valid unicode character, and will be left unchanged. | |||
* | |||
* 2) when any of these: àáâãäåæçèéêëìíîï are followed by TWO chars from group B, | |||
* 3) when any of these: ðñòó are followed by THREE chars from group B. | |||
* | |||
* @name toUTF8 | |||
* @param string $text Any string. | |||
* @return string The same string, UTF8 encoded | |||
* | |||
*/ | |||
if(is_array($text)) | |||
{ | |||
foreach($text as $k => $v) | |||
{ | |||
$text[$k] = self::toUTF8($v); | |||
} | |||
return $text; | |||
} | |||
if(!is_string($text)) { | |||
return $text; | |||
} | |||
$max = self::strlen($text); | |||
$buf = ""; | |||
for($i = 0; $i < $max; $i++){ | |||
$c1 = $text{$i}; | |||
if($c1>="\xc0"){ //Should be converted to UTF8, if it's not UTF8 already | |||
$c2 = $i+1 >= $max? "\x00" : $text{$i+1}; | |||
$c3 = $i+2 >= $max? "\x00" : $text{$i+2}; | |||
$c4 = $i+3 >= $max? "\x00" : $text{$i+3}; | |||
if($c1 >= "\xc0" & $c1 <= "\xdf"){ //looks like 2 bytes UTF8 | |||
if($c2 >= "\x80" && $c2 <= "\xbf"){ //yeah, almost sure it's UTF8 already | |||
$buf .= $c1 . $c2; | |||
$i++; | |||
} else { //not valid UTF8. Convert it. | |||
$cc1 = (chr(ord($c1) / 64) | "\xc0"); | |||
$cc2 = ($c1 & "\x3f") | "\x80"; | |||
$buf .= $cc1 . $cc2; | |||
} | |||
} elseif($c1 >= "\xe0" & $c1 <= "\xef"){ //looks like 3 bytes UTF8 | |||
if($c2 >= "\x80" && $c2 <= "\xbf" && $c3 >= "\x80" && $c3 <= "\xbf"){ //yeah, almost sure it's UTF8 already | |||
$buf .= $c1 . $c2 . $c3; | |||
$i = $i + 2; | |||
} else { //not valid UTF8. Convert it. | |||
$cc1 = (chr(ord($c1) / 64) | "\xc0"); | |||
$cc2 = ($c1 & "\x3f") | "\x80"; | |||
$buf .= $cc1 . $cc2; | |||
} | |||
} elseif($c1 >= "\xf0" & $c1 <= "\xf7"){ //looks like 4 bytes UTF8 | |||
if($c2 >= "\x80" && $c2 <= "\xbf" && $c3 >= "\x80" && $c3 <= "\xbf" && $c4 >= "\x80" && $c4 <= "\xbf"){ //yeah, almost sure it's UTF8 already | |||
$buf .= $c1 . $c2 . $c3 . $c4; | |||
$i = $i + 3; | |||
} else { //not valid UTF8. Convert it. | |||
$cc1 = (chr(ord($c1) / 64) | "\xc0"); | |||
$cc2 = ($c1 & "\x3f") | "\x80"; | |||
$buf .= $cc1 . $cc2; | |||
} | |||
} else { //doesn't look like UTF8, but should be converted | |||
$cc1 = (chr(ord($c1) / 64) | "\xc0"); | |||
$cc2 = (($c1 & "\x3f") | "\x80"); | |||
$buf .= $cc1 . $cc2; | |||
} | |||
} elseif(($c1 & "\xc0") == "\x80"){ // needs conversion | |||
if(isset(self::$win1252ToUtf8[ord($c1)])) { //found in Windows-1252 special cases | |||
$buf .= self::$win1252ToUtf8[ord($c1)]; | |||
} else { | |||
$cc1 = (chr(ord($c1) / 64) | "\xc0"); | |||
$cc2 = (($c1 & "\x3f") | "\x80"); | |||
$buf .= $cc1 . $cc2; | |||
} | |||
} else { // it doesn't need conversion | |||
$buf .= $c1; | |||
} | |||
} | |||
return $buf; | |||
} | |||
static function toWin1252($text, $option = self::WITHOUT_ICONV) { | |||
if(is_array($text)) { | |||
foreach($text as $k => $v) { | |||
$text[$k] = self::toWin1252($v, $option); | |||
} | |||
return $text; | |||
} elseif(is_string($text)) { | |||
return static::utf8_decode($text, $option); | |||
} else { | |||
return $text; | |||
} | |||
} | |||
static function toISO8859($text) { | |||
return self::toWin1252($text); | |||
} | |||
static function toLatin1($text) { | |||
return self::toWin1252($text); | |||
} | |||
static function fixUTF8($text, $option = self::WITHOUT_ICONV){ | |||
if(is_array($text)) { | |||
foreach($text as $k => $v) { | |||
$text[$k] = self::fixUTF8($v, $option); | |||
} | |||
return $text; | |||
} | |||
$last = ""; | |||
while($last <> $text){ | |||
$last = $text; | |||
$text = self::toUTF8(static::utf8_decode($text, $option)); | |||
} | |||
$text = self::toUTF8(static::utf8_decode($text, $option)); | |||
return $text; | |||
} | |||
static function UTF8FixWin1252Chars($text){ | |||
// If you received an UTF-8 string that was converted from Windows-1252 as it was ISO8859-1 | |||
// (ignoring Windows-1252 chars from 80 to 9F) use this function to fix it. | |||
// See: http://en.wikipedia.org/wiki/Windows-1252 | |||
return str_replace(array_keys(self::$brokenUtf8ToUtf8), array_values(self::$brokenUtf8ToUtf8), $text); | |||
} | |||
static function removeBOM($str=""){ | |||
if(substr($str, 0,3) == pack("CCC",0xef,0xbb,0xbf)) { | |||
$str=substr($str, 3); | |||
} | |||
return $str; | |||
} | |||
protected static function strlen($text){ | |||
return (function_exists('mb_strlen') && ((int) ini_get('mbstring.func_overload')) & 2) ? | |||
mb_strlen($text,'8bit') : strlen($text); | |||
} | |||
public static function normalizeEncoding($encodingLabel) | |||
{ | |||
$encoding = strtoupper($encodingLabel); | |||
$encoding = preg_replace('/[^a-zA-Z0-9\s]/', '', $encoding); | |||
$equivalences = array( | |||
'ISO88591' => 'ISO-8859-1', | |||
'ISO8859' => 'ISO-8859-1', | |||
'ISO' => 'ISO-8859-1', | |||
'LATIN1' => 'ISO-8859-1', | |||
'LATIN' => 'ISO-8859-1', | |||
'UTF8' => 'UTF-8', | |||
'UTF' => 'UTF-8', | |||
'WIN1252' => 'ISO-8859-1', | |||
'WINDOWS1252' => 'ISO-8859-1' | |||
); | |||
if(empty($equivalences[$encoding])){ | |||
return 'UTF-8'; | |||
} | |||
return $equivalences[$encoding]; | |||
} | |||
public static function encode($encodingLabel, $text) | |||
{ | |||
$encodingLabel = self::normalizeEncoding($encodingLabel); | |||
if($encodingLabel == 'ISO-8859-1') return self::toLatin1($text); | |||
return self::toUTF8($text); | |||
} | |||
protected static function utf8_decode($text, $option) | |||
{ | |||
if ($option == self::WITHOUT_ICONV || !function_exists('iconv')) { | |||
$o = utf8_decode( | |||
str_replace(array_keys(self::$utf8ToWin1252), array_values(self::$utf8ToWin1252), self::toUTF8($text)) | |||
); | |||
} else { | |||
$o = iconv("UTF-8", "Windows-1252" . ($option == self::ICONV_TRANSLIT ? '//TRANSLIT' : ($option == self::ICONV_IGNORE ? '//IGNORE' : '')), $text); | |||
} | |||
return $o; | |||
} | |||
} |
@@ -0,0 +1,2 @@ | |||
.idea | |||
.php_cs.cache |
@@ -0,0 +1,36 @@ | |||
<?php | |||
$config = PhpCsFixer\Config::create() | |||
->setUsingCache(false) | |||
->setRules([ | |||
'@PSR2' => true, | |||
'@Symfony' => true, | |||
'no_whitespace_in_blank_line' => true, | |||
'phpdoc_align' => true, | |||
'phpdoc_indent' => true, | |||
'phpdoc_scalar' => true, | |||
'phpdoc_separation' => true, | |||
'short_scalar_cast' => true, | |||
'single_blank_line_before_namespace' => true, | |||
'standardize_not_equals' => true, | |||
'ternary_operator_spaces' => true, | |||
'whitespace_after_comma_in_array' => true, | |||
'concat_space' => ["spacing" => "one"], | |||
'align_multiline_comment' => ['comment_type' => 'phpdocs_like'], | |||
'array_syntax' => ['syntax' => 'short'], | |||
'binary_operator_spaces' => ['default' => 'align'], | |||
'cast_spaces' => ['space' => 'single'], | |||
'combine_consecutive_issets' => true, | |||
'combine_consecutive_unsets' => true, | |||
]) | |||
->setFinder( | |||
PhpCsFixer\Finder::create() | |||
->in(__DIR__) | |||
->exclude('vendor') | |||
->exclude('node_modules') | |||
->exclude('plugins') | |||
->notPath('adminer.php') | |||
) | |||
; | |||
return $config; |
@@ -0,0 +1,674 @@ | |||
GNU GENERAL PUBLIC LICENSE | |||
Version 3, 29 June 2007 | |||
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/> | |||
Everyone is permitted to copy and distribute verbatim copies | |||
of this license document, but changing it is not allowed. | |||
Preamble | |||
The GNU General Public License is a free, copyleft license for | |||
software and other kinds of works. | |||
The licenses for most software and other practical works are designed | |||
to take away your freedom to share and change the works. By contrast, | |||
the GNU General Public License is intended to guarantee your freedom to | |||
share and change all versions of a program--to make sure it remains free | |||
software for all its users. We, the Free Software Foundation, use the | |||
GNU General Public License for most of our software; it applies also to | |||
any other work released this way by its authors. You can apply it to | |||
your programs, too. | |||
When we speak of free software, we are referring to freedom, not | |||
price. Our General Public Licenses are designed to make sure that you | |||
have the freedom to distribute copies of free software (and charge for | |||
them if you wish), that you receive source code or can get it if you | |||
want it, that you can change the software or use pieces of it in new | |||
free programs, and that you know you can do these things. | |||
To protect your rights, we need to prevent others from denying you | |||
these rights or asking you to surrender the rights. Therefore, you have | |||
certain responsibilities if you distribute copies of the software, or if | |||
you modify it: responsibilities to respect the freedom of others. | |||
For example, if you distribute copies of such a program, whether | |||
gratis or for a fee, you must pass on to the recipients the same | |||
freedoms that you received. You must make sure that they, too, receive | |||
or can get the source code. And you must show them these terms so they | |||
know their rights. | |||
Developers that use the GNU GPL protect your rights with two steps: | |||
(1) assert copyright on the software, and (2) offer you this License | |||
giving you legal permission to copy, distribute and/or modify it. | |||
For the developers' and authors' protection, the GPL clearly explains | |||
that there is no warranty for this free software. For both users' and | |||
authors' sake, the GPL requires that modified versions be marked as | |||
changed, so that their problems will not be attributed erroneously to | |||
authors of previous versions. | |||
Some devices are designed to deny users access to install or run | |||
modified versions of the software inside them, although the manufacturer | |||
can do so. This is fundamentally incompatible with the aim of | |||
protecting users' freedom to change the software. The systematic | |||
pattern of such abuse occurs in the area of products for individuals to | |||
use, which is precisely where it is most unacceptable. Therefore, we | |||
have designed this version of the GPL to prohibit the practice for those | |||
products. If such problems arise substantially in other domains, we | |||
stand ready to extend this provision to those domains in future versions | |||
of the GPL, as needed to protect the freedom of users. | |||
Finally, every program is threatened constantly by software patents. | |||
States should not allow patents to restrict development and use of | |||
software on general-purpose computers, but in those that do, we wish to | |||
avoid the special danger that patents applied to a free program could | |||
make it effectively proprietary. To prevent this, the GPL assures that | |||
patents cannot be used to render the program non-free. | |||
The precise terms and conditions for copying, distribution and | |||
modification follow. | |||
TERMS AND CONDITIONS | |||
0. Definitions. | |||
"This License" refers to version 3 of the GNU General Public License. | |||
"Copyright" also means copyright-like laws that apply to other kinds of | |||
works, such as semiconductor masks. | |||
"The Program" refers to any copyrightable work licensed under this | |||
License. Each licensee is addressed as "you". "Licensees" and | |||
"recipients" may be individuals or organizations. | |||
To "modify" a work means to copy from or adapt all or part of the work | |||
in a fashion requiring copyright permission, other than the making of an | |||
exact copy. The resulting work is called a "modified version" of the | |||
earlier work or a work "based on" the earlier work. | |||
A "covered work" means either the unmodified Program or a work based | |||
on the Program. | |||
To "propagate" a work means to do anything with it that, without | |||
permission, would make you directly or secondarily liable for | |||
infringement under applicable copyright law, except executing it on a | |||
computer or modifying a private copy. Propagation includes copying, | |||
distribution (with or without modification), making available to the | |||
public, and in some countries other activities as well. | |||
To "convey" a work means any kind of propagation that enables other | |||
parties to make or receive copies. Mere interaction with a user through | |||
a computer network, with no transfer of a copy, is not conveying. | |||
An interactive user interface displays "Appropriate Legal Notices" | |||
to the extent that it includes a convenient and prominently visible | |||
feature that (1) displays an appropriate copyright notice, and (2) | |||
tells the user that there is no warranty for the work (except to the | |||
extent that warranties are provided), that licensees may convey the | |||
work under this License, and how to view a copy of this License. If | |||
the interface presents a list of user commands or options, such as a | |||
menu, a prominent item in the list meets this criterion. | |||
1. Source Code. | |||
The "source code" for a work means the preferred form of the work | |||
for making modifications to it. "Object code" means any non-source | |||
form of a work. | |||
A "Standard Interface" means an interface that either is an official | |||
standard defined by a recognized standards body, or, in the case of | |||
interfaces specified for a particular programming language, one that | |||
is widely used among developers working in that language. | |||
The "System Libraries" of an executable work include anything, other | |||
than the work as a whole, that (a) is included in the normal form of | |||
packaging a Major Component, but which is not part of that Major | |||
Component, and (b) serves only to enable use of the work with that | |||
Major Component, or to implement a Standard Interface for which an | |||
implementation is available to the public in source code form. A | |||
"Major Component", in this context, means a major essential component | |||
(kernel, window system, and so on) of the specific operating system | |||
(if any) on which the executable work runs, or a compiler used to | |||
produce the work, or an object code interpreter used to run it. | |||
The "Corresponding Source" for a work in object code form means all | |||
the source code needed to generate, install, and (for an executable | |||
work) run the object code and to modify the work, including scripts to | |||
control those activities. However, it does not include the work's | |||
System Libraries, or general-purpose tools or generally available free | |||
programs which are used unmodified in performing those activities but | |||
which are not part of the work. For example, Corresponding Source | |||
includes interface definition files associated with source files for | |||
the work, and the source code for shared libraries and dynamically | |||
linked subprograms that the work is specifically designed to require, | |||
such as by intimate data communication or control flow between those | |||
subprograms and other parts of the work. | |||
The Corresponding Source need not include anything that users | |||
can regenerate automatically from other parts of the Corresponding | |||
Source. | |||
The Corresponding Source for a work in source code form is that | |||
same work. | |||
2. Basic Permissions. | |||
All rights granted under this License are granted for the term of | |||
copyright on the Program, and are irrevocable provided the stated | |||
conditions are met. This License explicitly affirms your unlimited | |||
permission to run the unmodified Program. The output from running a | |||
covered work is covered by this License only if the output, given its | |||
content, constitutes a covered work. This License acknowledges your | |||
rights of fair use or other equivalent, as provided by copyright law. | |||
You may make, run and propagate covered works that you do not | |||
convey, without conditions so long as your license otherwise remains | |||
in force. You may convey covered works to others for the sole purpose | |||
of having them make modifications exclusively for you, or provide you | |||
with facilities for running those works, provided that you comply with | |||
the terms of this License in conveying all material for which you do | |||
not control copyright. Those thus making or running the covered works | |||
for you must do so exclusively on your behalf, under your direction | |||
and control, on terms that prohibit them from making any copies of | |||
your copyrighted material outside their relationship with you. | |||
Conveying under any other circumstances is permitted solely under | |||
the conditions stated below. Sublicensing is not allowed; section 10 | |||
makes it unnecessary. | |||
3. Protecting Users' Legal Rights From Anti-Circumvention Law. | |||
No covered work shall be deemed part of an effective technological | |||
measure under any applicable law fulfilling obligations under article | |||
11 of the WIPO copyright treaty adopted on 20 December 1996, or | |||
similar laws prohibiting or restricting circumvention of such | |||
measures. | |||
When you convey a covered work, you waive any legal power to forbid | |||
circumvention of technological measures to the extent such circumvention | |||
is effected by exercising rights under this License with respect to | |||
the covered work, and you disclaim any intention to limit operation or | |||
modification of the work as a means of enforcing, against the work's | |||
users, your or third parties' legal rights to forbid circumvention of | |||
technological measures. | |||
4. Conveying Verbatim Copies. | |||
You may convey verbatim copies of the Program's source code as you | |||
receive it, in any medium, provided that you conspicuously and | |||
appropriately publish on each copy an appropriate copyright notice; | |||
keep intact all notices stating that this License and any | |||
non-permissive terms added in accord with section 7 apply to the code; | |||
keep intact all notices of the absence of any warranty; and give all | |||
recipients a copy of this License along with the Program. | |||
You may charge any price or no price for each copy that you convey, | |||
and you may offer support or warranty protection for a fee. | |||
5. Conveying Modified Source Versions. | |||
You may convey a work based on the Program, or the modifications to | |||
produce it from the Program, in the form of source code under the | |||
terms of section 4, provided that you also meet all of these conditions: | |||
a) The work must carry prominent notices stating that you modified | |||
it, and giving a relevant date. | |||
b) The work must carry prominent notices stating that it is | |||
released under this License and any conditions added under section | |||
7. This requirement modifies the requirement in section 4 to | |||
"keep intact all notices". | |||
c) You must license the entire work, as a whole, under this | |||
License to anyone who comes into possession of a copy. This | |||
License will therefore apply, along with any applicable section 7 | |||
additional terms, to the whole of the work, and all its parts, | |||
regardless of how they are packaged. This License gives no | |||
permission to license the work in any other way, but it does not | |||
invalidate such permission if you have separately received it. | |||
d) If the work has interactive user interfaces, each must display | |||
Appropriate Legal Notices; however, if the Program has interactive | |||
interfaces that do not display Appropriate Legal Notices, your | |||
work need not make them do so. | |||
A compilation of a covered work with other separate and independent | |||
works, which are not by their nature extensions of the covered work, | |||
and which are not combined with it such as to form a larger program, | |||
in or on a volume of a storage or distribution medium, is called an | |||
"aggregate" if the compilation and its resulting copyright are not | |||
used to limit the access or legal rights of the compilation's users | |||
beyond what the individual works permit. Inclusion of a covered work | |||
in an aggregate does not cause this License to apply to the other | |||
parts of the aggregate. | |||
6. Conveying Non-Source Forms. | |||
You may convey a covered work in object code form under the terms | |||
of sections 4 and 5, provided that you also convey the | |||
machine-readable Corresponding Source under the terms of this License, | |||
in one of these ways: | |||
a) Convey the object code in, or embodied in, a physical product | |||
(including a physical distribution medium), accompanied by the | |||
Corresponding Source fixed on a durable physical medium | |||
customarily used for software interchange. | |||
b) Convey the object code in, or embodied in, a physical product | |||
(including a physical distribution medium), accompanied by a | |||
written offer, valid for at least three years and valid for as | |||
long as you offer spare parts or customer support for that product | |||
model, to give anyone who possesses the object code either (1) a | |||
copy of the Corresponding Source for all the software in the | |||
product that is covered by this License, on a durable physical | |||
medium customarily used for software interchange, for a price no | |||
more than your reasonable cost of physically performing this | |||
conveying of source, or (2) access to copy the | |||
Corresponding Source from a network server at no charge. | |||
c) Convey individual copies of the object code with a copy of the | |||
written offer to provide the Corresponding Source. This | |||
alternative is allowed only occasionally and noncommercially, and | |||
only if you received the object code with such an offer, in accord | |||
with subsection 6b. | |||
d) Convey the object code by offering access from a designated | |||
place (gratis or for a charge), and offer equivalent access to the | |||
Corresponding Source in the same way through the same place at no | |||
further charge. You need not require recipients to copy the | |||
Corresponding Source along with the object code. If the place to | |||
copy the object code is a network server, the Corresponding Source | |||
may be on a different server (operated by you or a third party) | |||
that supports equivalent copying facilities, provided you maintain | |||
clear directions next to the object code saying where to find the | |||
Corresponding Source. Regardless of what server hosts the | |||
Corresponding Source, you remain obligated to ensure that it is | |||
available for as long as needed to satisfy these requirements. | |||
e) Convey the object code using peer-to-peer transmission, provided | |||
you inform other peers where the object code and Corresponding | |||
Source of the work are being offered to the general public at no | |||
charge under subsection 6d. | |||
A separable portion of the object code, whose source code is excluded | |||
from the Corresponding Source as a System Library, need not be | |||
included in conveying the object code work. | |||
A "User Product" is either (1) a "consumer product", which means any | |||
tangible personal property which is normally used for personal, family, | |||
or household purposes, or (2) anything designed or sold for incorporation | |||
into a dwelling. In determining whether a product is a consumer product, | |||
doubtful cases shall be resolved in favor of coverage. For a particular | |||
product received by a particular user, "normally used" refers to a | |||
typical or common use of that class of product, regardless of the status | |||
of the particular user or of the way in which the particular user | |||
actually uses, or expects or is expected to use, the product. A product | |||
is a consumer product regardless of whether the product has substantial | |||
commercial, industrial or non-consumer uses, unless such uses represent | |||
the only significant mode of use of the product. | |||
"Installation Information" for a User Product means any methods, | |||
procedures, authorization keys, or other information required to install | |||
and execute modified versions of a covered work in that User Product from | |||
a modified version of its Corresponding Source. The information must | |||
suffice to ensure that the continued functioning of the modified object | |||
code is in no case prevented or interfered with solely because | |||
modification has been made. | |||
If you convey an object code work under this section in, or with, or | |||
specifically for use in, a User Product, and the conveying occurs as | |||
part of a transaction in which the right of possession and use of the | |||
User Product is transferred to the recipient in perpetuity or for a | |||
fixed term (regardless of how the transaction is characterized), the | |||
Corresponding Source conveyed under this section must be accompanied | |||
by the Installation Information. But this requirement does not apply | |||
if neither you nor any third party retains the ability to install | |||
modified object code on the User Product (for example, the work has | |||
been installed in ROM). | |||
The requirement to provide Installation Information does not include a | |||
requirement to continue to provide support service, warranty, or updates | |||
for a work that has been modified or installed by the recipient, or for | |||
the User Product in which it has been modified or installed. Access to a | |||
network may be denied when the modification itself materially and | |||
adversely affects the operation of the network or violates the rules and | |||
protocols for communication across the network. | |||
Corresponding Source conveyed, and Installation Information provided, | |||
in accord with this section must be in a format that is publicly | |||
documented (and with an implementation available to the public in | |||
source code form), and must require no special password or key for | |||
unpacking, reading or copying. | |||
7. Additional Terms. | |||
"Additional permissions" are terms that supplement the terms of this | |||
License by making exceptions from one or more of its conditions. | |||
Additional permissions that are applicable to the entire Program shall | |||
be treated as though they were included in this License, to the extent | |||
that they are valid under applicable law. If additional permissions | |||
apply only to part of the Program, that part may be used separately | |||
under those permissions, but the entire Program remains governed by | |||
this License without regard to the additional permissions. | |||
When you convey a copy of a covered work, you may at your option | |||
remove any additional permissions from that copy, or from any part of | |||
it. (Additional permissions may be written to require their own | |||
removal in certain cases when you modify the work.) You may place | |||
additional permissions on material, added by you to a covered work, | |||
for which you have or can give appropriate copyright permission. | |||
Notwithstanding any other provision of this License, for material you | |||
add to a covered work, you may (if authorized by the copyright holders of | |||
that material) supplement the terms of this License with terms: | |||
a) Disclaiming warranty or limiting liability differently from the | |||
terms of sections 15 and 16 of this License; or | |||
b) Requiring preservation of specified reasonable legal notices or | |||
author attributions in that material or in the Appropriate Legal | |||
Notices displayed by works containing it; or | |||
c) Prohibiting misrepresentation of the origin of that material, or | |||
requiring that modified versions of such material be marked in | |||
reasonable ways as different from the original version; or | |||
d) Limiting the use for publicity purposes of names of licensors or | |||
authors of the material; or | |||
e) Declining to grant rights under trademark law for use of some | |||
trade names, trademarks, or service marks; or | |||
f) Requiring indemnification of licensors and authors of that | |||
material by anyone who conveys the material (or modified versions of | |||
it) with contractual assumptions of liability to the recipient, for | |||
any liability that these contractual assumptions directly impose on | |||
those licensors and authors. | |||
All other non-permissive additional terms are considered "further | |||
restrictions" within the meaning of section 10. If the Program as you | |||
received it, or any part of it, contains a notice stating that it is | |||
governed by this License along with a term that is a further | |||
restriction, you may remove that term. If a license document contains | |||
a further restriction but permits relicensing or conveying under this | |||
License, you may add to a covered work material governed by the terms | |||
of that license document, provided that the further restriction does | |||
not survive such relicensing or conveying. | |||
If you add terms to a covered work in accord with this section, you | |||
must place, in the relevant source files, a statement of the | |||
additional terms that apply to those files, or a notice indicating | |||
where to find the applicable terms. | |||
Additional terms, permissive or non-permissive, may be stated in the | |||
form of a separately written license, or stated as exceptions; | |||
the above requirements apply either way. | |||
8. Termination. | |||
You may not propagate or modify a covered work except as expressly | |||
provided under this License. Any attempt otherwise to propagate or | |||
modify it is void, and will automatically terminate your rights under | |||
this License (including any patent licenses granted under the third | |||
paragraph of section 11). | |||
However, if you cease all violation of this License, then your | |||
license from a particular copyright holder is reinstated (a) | |||
provisionally, unless and until the copyright holder explicitly and | |||
finally terminates your license, and (b) permanently, if the copyright | |||
holder fails to notify you of the violation by some reasonable means | |||
prior to 60 days after the cessation. | |||
Moreover, your license from a particular copyright holder is | |||
reinstated permanently if the copyright holder notifies you of the | |||
violation by some reasonable means, this is the first time you have | |||
received notice of violation of this License (for any work) from that | |||
copyright holder, and you cure the violation prior to 30 days after | |||
your receipt of the notice. | |||
Termination of your rights under this section does not terminate the | |||
licenses of parties who have received copies or rights from you under | |||
this License. If your rights have been terminated and not permanently | |||
reinstated, you do not qualify to receive new licenses for the same | |||
material under section 10. | |||
9. Acceptance Not Required for Having Copies. | |||
You are not required to accept this License in order to receive or | |||
run a copy of the Program. Ancillary propagation of a covered work | |||
occurring solely as a consequence of using peer-to-peer transmission | |||
to receive a copy likewise does not require acceptance. However, | |||
nothing other than this License grants you permission to propagate or | |||
modify any covered work. These actions infringe copyright if you do | |||
not accept this License. Therefore, by modifying or propagating a | |||
covered work, you indicate your acceptance of this License to do so. | |||
10. Automatic Licensing of Downstream Recipients. | |||
Each time you convey a covered work, the recipient automatically | |||
receives a license from the original licensors, to run, modify and | |||
propagate that work, subject to this License. You are not responsible | |||
for enforcing compliance by third parties with this License. | |||
An "entity transaction" is a transaction transferring control of an | |||
organization, or substantially all assets of one, or subdividing an | |||
organization, or merging organizations. If propagation of a covered | |||
work results from an entity transaction, each party to that | |||
transaction who receives a copy of the work also receives whatever | |||
licenses to the work the party's predecessor in interest had or could | |||
give under the previous paragraph, plus a right to possession of the | |||
Corresponding Source of the work from the predecessor in interest, if | |||
the predecessor has it or can get it with reasonable efforts. | |||
You may not impose any further restrictions on the exercise of the | |||
rights granted or affirmed under this License. For example, you may | |||
not impose a license fee, royalty, or other charge for exercise of | |||
rights granted under this License, and you may not initiate litigation | |||
(including a cross-claim or counterclaim in a lawsuit) alleging that | |||
any patent claim is infringed by making, using, selling, offering for | |||
sale, or importing the Program or any portion of it. | |||
11. Patents. | |||
A "contributor" is a copyright holder who authorizes use under this | |||
License of the Program or a work on which the Program is based. The | |||
work thus licensed is called the contributor's "contributor version". | |||
A contributor's "essential patent claims" are all patent claims | |||
owned or controlled by the contributor, whether already acquired or | |||
hereafter acquired, that would be infringed by some manner, permitted | |||
by this License, of making, using, or selling its contributor version, | |||
but do not include claims that would be infringed only as a | |||
consequence of further modification of the contributor version. For | |||
purposes of this definition, "control" includes the right to grant | |||
patent sublicenses in a manner consistent with the requirements of | |||
this License. | |||
Each contributor grants you a non-exclusive, worldwide, royalty-free | |||
patent license under the contributor's essential patent claims, to | |||
make, use, sell, offer for sale, import and otherwise run, modify and | |||
propagate the contents of its contributor version. | |||
In the following three paragraphs, a "patent license" is any express | |||
agreement or commitment, however denominated, not to enforce a patent | |||
(such as an express permission to practice a patent or covenant not to | |||
sue for patent infringement). To "grant" such a patent license to a | |||
party means to make such an agreement or commitment not to enforce a | |||
patent against the party. | |||
If you convey a covered work, knowingly relying on a patent license, | |||
and the Corresponding Source of the work is not available for anyone | |||
to copy, free of charge and under the terms of this License, through a | |||
publicly available network server or other readily accessible means, | |||
then you must either (1) cause the Corresponding Source to be so | |||
available, or (2) arrange to deprive yourself of the benefit of the | |||
patent license for this particular work, or (3) arrange, in a manner | |||
consistent with the requirements of this License, to extend the patent | |||
license to downstream recipients. "Knowingly relying" means you have | |||
actual knowledge that, but for the patent license, your conveying the | |||
covered work in a country, or your recipient's use of the covered work | |||
in a country, would infringe one or more identifiable patents in that | |||
country that you have reason to believe are valid. | |||
If, pursuant to or in connection with a single transaction or | |||
arrangement, you convey, or propagate by procuring conveyance of, a | |||
covered work, and grant a patent license to some of the parties | |||
receiving the covered work authorizing them to use, propagate, modify | |||
or convey a specific copy of the covered work, then the patent license | |||
you grant is automatically extended to all recipients of the covered | |||
work and works based on it. | |||
A patent license is "discriminatory" if it does not include within | |||
the scope of its coverage, prohibits the exercise of, or is | |||
conditioned on the non-exercise of one or more of the rights that are | |||
specifically granted under this License. You may not convey a covered | |||
work if you are a party to an arrangement with a third party that is | |||
in the business of distributing software, under which you make payment | |||
to the third party based on the extent of your activity of conveying | |||
the work, and under which the third party grants, to any of the | |||
parties who would receive the covered work from you, a discriminatory | |||
patent license (a) in connection with copies of the covered work | |||
conveyed by you (or copies made from those copies), or (b) primarily | |||
for and in connection with specific products or compilations that | |||
contain the covered work, unless you entered into that arrangement, | |||
or that patent license was granted, prior to 28 March 2007. | |||
Nothing in this License shall be construed as excluding or limiting | |||
any implied license or other defenses to infringement that may | |||
otherwise be available to you under applicable patent law. | |||
12. No Surrender of Others' Freedom. | |||
If conditions are imposed on you (whether by court order, agreement or | |||
otherwise) that contradict the conditions of this License, they do not | |||
excuse you from the conditions of this License. If you cannot convey a | |||
covered work so as to satisfy simultaneously your obligations under this | |||
License and any other pertinent obligations, then as a consequence you may | |||
not convey it at all. For example, if you agree to terms that obligate you | |||
to collect a royalty for further conveying from those to whom you convey | |||
the Program, the only way you could satisfy both those terms and this | |||
License would be to refrain entirely from conveying the Program. | |||
13. Use with the GNU Affero General Public License. | |||
Notwithstanding any other provision of this License, you have | |||
permission to link or combine any covered work with a work licensed | |||
under version 3 of the GNU Affero General Public License into a single | |||
combined work, and to convey the resulting work. The terms of this | |||
License will continue to apply to the part which is the covered work, | |||
but the special requirements of the GNU Affero General Public License, | |||
section 13, concerning interaction through a network will apply to the | |||
combination as such. | |||
14. Revised Versions of this License. | |||
The Free Software Foundation may publish revised and/or new versions of | |||
the GNU General Public License from time to time. Such new versions will | |||
be similar in spirit to the present version, but may differ in detail to | |||
address new problems or concerns. | |||
Each version is given a distinguishing version number. If the | |||
Program specifies that a certain numbered version of the GNU General | |||
Public License "or any later version" applies to it, you have the | |||
option of following the terms and conditions either of that numbered | |||
version or of any later version published by the Free Software | |||
Foundation. If the Program does not specify a version number of the | |||
GNU General Public License, you may choose any version ever published | |||
by the Free Software Foundation. | |||
If the Program specifies that a proxy can decide which future | |||
versions of the GNU General Public License can be used, that proxy's | |||
public statement of acceptance of a version permanently authorizes you | |||
to choose that version for the Program. | |||
Later license versions may give you additional or different | |||
permissions. However, no additional obligations are imposed on any | |||
author or copyright holder as a result of your choosing to follow a | |||
later version. | |||
15. Disclaimer of Warranty. | |||
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY | |||
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT | |||
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY | |||
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, | |||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM | |||
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF | |||
ALL NECESSARY SERVICING, REPAIR OR CORRECTION. | |||
16. Limitation of Liability. | |||
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING | |||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS | |||
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY | |||
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE | |||
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF | |||
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD | |||
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), | |||
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF | |||
SUCH DAMAGES. | |||
17. Interpretation of Sections 15 and 16. | |||
If the disclaimer of warranty and limitation of liability provided | |||
above cannot be given local legal effect according to their terms, | |||
reviewing courts shall apply local law that most closely approximates | |||
an absolute waiver of all civil liability in connection with the | |||
Program, unless a warranty or assumption of liability accompanies a | |||
copy of the Program in return for a fee. | |||
END OF TERMS AND CONDITIONS | |||
How to Apply These Terms to Your New Programs | |||
If you develop a new program, and you want it to be of the greatest | |||
possible use to the public, the best way to achieve this is to make it | |||
free software which everyone can redistribute and change under these terms. | |||
To do so, attach the following notices to the program. It is safest | |||
to attach them to the start of each source file to most effectively | |||
state the exclusion of warranty; and each file should have at least | |||
the "copyright" line and a pointer to where the full notice is found. | |||
<one line to give the program's name and a brief idea of what it does.> | |||
Copyright (C) <year> <name of author> | |||
This program is free software: you can redistribute it and/or modify | |||
it under the terms of the GNU General Public License as published by | |||
the Free Software Foundation, either version 3 of the License, or | |||
(at your option) any later version. | |||
This program is distributed in the hope that it will be useful, | |||
but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
GNU General Public License for more details. | |||
You should have received a copy of the GNU General Public License | |||
along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
Also add information on how to contact you by electronic and paper mail. | |||
If the program does terminal interaction, make it output a short | |||
notice like this when it starts in an interactive mode: | |||
<program> Copyright (C) <year> <name of author> | |||
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. | |||
This is free software, and you are welcome to redistribute it | |||
under certain conditions; type `show c' for details. | |||
The hypothetical commands `show w' and `show c' should show the appropriate | |||
parts of the General Public License. Of course, your program's commands | |||
might be different; for a GUI interface, you would use an "about box". | |||
You should also get your employer (if you work as a programmer) or school, | |||
if any, to sign a "copyright disclaimer" for the program, if necessary. | |||
For more information on this, and how to apply and follow the GNU GPL, see | |||
<http://www.gnu.org/licenses/>. | |||
The GNU General Public License does not permit incorporating your program | |||
into proprietary programs. If your program is a subroutine library, you | |||
may consider it more useful to permit linking proprietary applications with | |||
the library. If this is what you want to do, use the GNU Lesser General | |||
Public License instead of this License. But first, please read | |||
<http://www.gnu.org/philosophy/why-not-lgpl.html>. |
@@ -0,0 +1,54 @@ | |||
Torrent RW | |||
PHP version 5.2+ | |||
1) Features: | |||
- Decode torrent file or data | |||
- Build torrent from source folder/file(s) | |||
- Silent Exception error system | |||
2) Usage example | |||
```php | |||
require_once 'Torrent.php'; | |||
// get torrent infos | |||
$torrent = new Torrent( './test.torrent' ); | |||
echo '<br>private: ', $torrent->is_private() ? 'yes' : 'no', | |||
'<br>annonce: ', $torrent->announce(), | |||
'<br>name: ', $torrent->name(), | |||
'<br>comment: ', $torrent->comment(), | |||
'<br>piece_length: ', $torrent->piece_length(), | |||
'<br>size: ', $torrent->size( 2 ), | |||
'<br>hash info: ', $torrent->hash_info(), | |||
'<br>stats: '; | |||
var_dump( $torrent->scrape() ); | |||
echo '<br>content: '; | |||
var_dump( $torrent->content() ); | |||
echo '<br>source: ', | |||
$torrent; | |||
// get magnet link | |||
$torrent->magnet(); // use $torrent->magnet( false ); to get non html encoded ampersand | |||
// create torrent | |||
$torrent = new Torrent( array( 'test.mp3', 'test.jpg' ), 'http://torrent.tracker/annonce' ); | |||
$torrent->save('test.torrent'); // save to disk | |||
// modify torrent | |||
$torrent->announce('http://alternate-torrent.tracker/annonce'); // add a tracker | |||
$torrent->announce(false); // reset announce trackers | |||
$torrent->announce(array('http://torrent.tracker/annonce', 'http://alternate-torrent.tracker/annonce')); // set tracker(s), it also works with a 'one tracker' array... | |||
$torrent->announce(array(array('http://torrent.tracker/annonce', 'http://alternate-torrent.tracker/annonce'), 'http://another-torrent.tracker/annonce')); // set tiered trackers | |||
$torrent->comment('hello world'); | |||
$torrent->name('test torrent'); | |||
$torrent->is_private(true); | |||
$torrent->httpseeds('http://file-hosting.domain/path/'); // Bittornado implementation | |||
$torrent->url_list(array('http://file-hosting.domain/path/','http://another-file-hosting.domain/path/')); // GetRight implementation | |||
// print errors | |||
if ( $errors = $torrent->errors() ) | |||
var_dump( $errors ); | |||
// send to user | |||
$torrent->send(); | |||
``` |
@@ -0,0 +1 @@ | |||
theme: jekyll-theme-slate |
@@ -0,0 +1,334 @@ | |||
<?php | |||
/* | |||
__ ___ ______ __ ____ | |||
/ |/ /___ _____ / ____/___ ____ / /__________ / / /__ _____ | |||
/ /|_/ / __ `/ __ \ / / / __ \/ __ \/ __/ ___/ __ \/ / / _ \/ ___/ | |||
/ / / / /_/ / /_/ / / /___/ /_/ / / / / /_/ / / /_/ / / / __/ / | |||
/_/ /_/\__,_/ .___/ \____/\____/_/ /_/\__/_/ \____/_/_/\___/_/ | |||
/_/ | |||
-create a new map | |||
-change an old map | |||
-get map data | |||
----------------- | |||
-get tile values | |||
*/ | |||
ini_set('display_errors', 1); | |||
require_once "Utils/Constants.php"; | |||
require_once "Imports/LazerImports.php"; | |||
require_once 'Utils/Helpers.php'; | |||
require_once 'Models/Game/Coord.php'; | |||
require_once 'Models/Game/Level.php'; | |||
require_once 'Models/Game/Tile.php'; | |||
use \ForceUTF8\Encoding; | |||
//Autoload usage https://stackoverflow.com/questions/16175023/php-include-class-in-other-class | |||
use Lazer\Classes\Database as Lazer; | |||
defined('LAZER_DATA_PATH') or define('LAZER_DATA_PATH', realpath(dirname(__FILE__)).'/'.Constants::CONST_DB_FOLDER.'/'); | |||
Class MapController { | |||
/*************************** | |||
* SAVING AND GETTIGNS DATA | |||
***************************/ | |||
function createLevel($level) { | |||
$row = Lazer::table(Constants::CONST_TABLE_MAP); | |||
$row = $level ->fillRow($row); | |||
$row->save(); | |||
} | |||
function placePlayerFromTo($to_,$from_){ | |||
$row = Lazer::table(Constants::CONST_TABLE_MAP)->where('key', '=', $to_)->find(); | |||
$level = Level::parseRow($row); | |||
//get the future player coordonates | |||
$coord = $level -> placePlayerForKey($from_); | |||
//return Coord | |||
return $coord; | |||
} | |||
function getAllTiles(){ | |||
return Tile::getAllTiles(); | |||
} | |||
/************************** | |||
* MAP PROCEDURAL GENERATION | |||
*************************/ | |||
function generateWorld(){ | |||
//importnat VARS | |||
$gridData; | |||
$gridWidth = 2; | |||
$gridHeight = 2; | |||
$levelToPlace; | |||
$levelNumMax; | |||
$levelWidthMax; | |||
$levelHeightMax; | |||
//1. generate the dungeon grid | |||
$gridData = $this->fillgrid(null, $gridWidth, $gridHeight); | |||
$levelToPlace = array(); | |||
array_push($levelToPlace, new Level(Constants::CONST_MAP_ALPHA_NAME, 15, 13, true, true)); | |||
array_push($levelToPlace, new Level("request", 15, 13, true, false) ); | |||
array_push($levelToPlace, new Level("conspi", 15, 13, true, false) ); | |||
array_push($levelToPlace, new Level("art", 15, 13, true, false) ); | |||
array_push($levelToPlace, new Level("lulz", 15, 13, true, true) ); | |||
/* | |||
$size = Level::getDim(26); | |||
array_push($levelToPlace, new Level("tripletrap", $size->x, $size->y, true)); | |||
$size = Level::getDim(26); | |||
array_push($levelToPlace, new Level("pol", $size->x, $size->y, true) ); | |||
$size = Level::getDim(26); | |||
array_push($levelToPlace, new Level("senpai", $size->x, $size->y, true)); | |||
$size = Level::getDim(26); | |||
array_push($levelToPlace, new Level("varg", $size->x, $size->y, true) ); | |||
$size = Level::getDim(26); | |||
array_push($levelToPlace, new Level("crypto", $size->x, $size->y, true) );*/ | |||
//2. place the main level on this grid | |||
/* | |||
foreach ($levelToPlace as $lvl){ | |||
$coord = $this->pickPointFromGrid($gridData , $gridWidth, $gridHeight ); | |||
if(isset($coord)){ | |||
$gridData = $this->placeToGrid($gridData, $lvl, $gridWidth, $gridHeight, $coord ); | |||
$lvl -> x = $coord-> x; | |||
$lvl -> y = $coord-> y; | |||
} | |||
}*/ | |||
//Genrate room for missing points | |||
/* | |||
$emptyCoord = $this->getCoordsFor($gridData, NULL, $gridWidth, $gridHeight); | |||
for($l = 0; $l < count($levelToPlace); $l++){ | |||
$index = rand(0, count($emptyCoord)-1 ); | |||
$coord = $emptyCoord[$index]; | |||
$level = new Level("???", rand(2,7), rand(2,7), false ); | |||
$gridData = $this->placeToGrid($gridData, $level , $gridWidth, $gridHeight, $coord); | |||
array_splice($emptyCoord, $index, 1); | |||
$level-> x = $coord-> x; | |||
$level-> y = $coord-> y; | |||
if(count($emptyCoord) < 1) break; | |||
}*/ | |||
$this->displayGrid($gridData, $gridWidth, $gridHeight, true); | |||
//3. each level need to have at least 1 door | |||
/* | |||
$allLevels = $this->getAllLevels($gridData); | |||
foreach ($allLevels as $lvl){ | |||
$dir = 0; | |||
$numDoors = rand(1,2); | |||
for( $dir; $dir < 3; $dir ++ ){ | |||
//CAUTION level found are the door on the other direction!!! | |||
$levelFound = null; | |||
$oppDir; | |||
$coord = new Coord($lvl-> x, $lvl-> y); | |||
//South | |||
if($dir == 2 ){ | |||
$levelFound = $this->getLevelForDir($gridData, $gridWidth, $gridHeight, $coord,$dir); | |||
if(isset( $levelFound->door_key_N )) $levelFound = null; | |||
$oppDir = 0; | |||
} | |||
//West | |||
if($dir == 3 ){ | |||
$levelFound = $this->getLevelForDir($gridData, $gridWidth, $gridHeight, $coord,$dir); | |||
if(isset( $levelFound->door_key_E )) $levelFound = null; | |||
$oppDir = 1; | |||
} | |||
//North | |||
if($dir == 0){ | |||
$levelFound = $this->getLevelForDir($gridData, $gridWidth, $gridHeight, $coord,$dir); | |||
if(isset( $levelFound->door_key_S )) $levelFound = null; | |||
$oppDir = 2; | |||
} | |||
//East | |||
if($dir == 1 ){ | |||
$levelFound = $this->getLevelForDir($gridData, $gridWidth, $gridHeight, $coord,$dir); | |||
if(isset( $levelFound->door_key_W )) $levelFound = null; | |||
$oppDir = 3; | |||
} | |||
if( isset($levelFound) && $numDoors > 0){ | |||
$levelFound -> setKeyForDir($lvl->key, $oppDir); | |||
$lvl-> setKeyForDir($levelFound->key, $dir); | |||
$numDoors --; | |||
} | |||
} | |||
//echo $lvl->name." has ".$lvl->getNumDoors()." doors<br/>"; | |||
}*/ | |||
//Get the level | |||
foreach ($levelToPlace as $lvl){ | |||
$lvl -> initLevelData(); | |||
$this->createLevel($lvl); | |||
} | |||
} | |||
/**************************** | |||
* UTILS for PROCEDURAL | |||
* Generation | |||
****************************/ | |||
function fillgrid($defaultTile_, $width_, $height_){ | |||
$newGrid = array(); | |||
for ($i = 0; $i < ($height_*$width_); $i++) { | |||
array_push($newGrid,$defaultTile_); | |||
} | |||
return $newGrid; | |||
} | |||
function pickPointFromGrid($gridData, $width_, $height_ ){ | |||
for ($i = 0; $i < 10; $i++) { | |||
$x = rand ( 0 , $width_-1); | |||
$y = rand ( 0 , $height_-1); | |||
//is grid coordonate occupped? | |||
$val = $gridData[ ($y*$height_) + $x]; | |||
if( !isset($val)) return new Coord($x, $y); | |||
} | |||
return NULL; | |||
} | |||
function placeToGrid($gridData, $data, $width_, $height_, $coord){ | |||
$gridData[ ( $coord->y *$width_) + $coord->x] = $data; | |||
return $gridData; | |||
} | |||
function getLevelForCoord($gridData_, $coord_, $width_, $height_){ | |||
return $gridData_[ ( $coord_->y *$width_) + $coord_->x]; | |||
} | |||
function getCoordsFor($gridData, $data, $width_, $height_){ | |||
$listData = array(); | |||
for ($y = 0; $y < $height_; $y++) { | |||
for ($x = 0; $x < $width_; $x++) { | |||
if( $gridData[ ($y*$width_) + $x] == $data) array_push($listData, new Coord($x, $y)); | |||
} | |||
} | |||
return $listData; | |||
} | |||
/** | |||
* Get all the levels from the griddata | |||
* Return Level[] array; | |||
*/ | |||
function getAllLevels($gridData){ | |||
$levels = array(); | |||
foreach ($gridData as $lvl){ | |||
if(isset($lvl)) array_push($levels,$lvl); | |||
} | |||
return $levels; | |||
} | |||
function displayGrid($gridData_, $width_, $height_, $is_null){ | |||
for ($y = 0; $y < $height_; $y++) { | |||
for ($x = 0; $x < $width_; $x++) { | |||
if( !isset($gridData_[($y*$width_) + $x]) || !isset($gridData_[ ($y*$width_) + $x] -> name)){ | |||
echo "."; | |||
} else { | |||
$name = $gridData_[ ($y*$width_) + $x] -> name; | |||
echo substr($name,0,1); | |||
} | |||
} | |||
echo "<br/>"; | |||
} | |||
} | |||
function getLevelForDir($gridData_, $width_, $height_, $coord_,$dir_){ | |||
switch($dir_){ | |||
case 0: | |||
for ($y = $coord_->y -1; $y >= 0; $y--) { | |||
$coord = new Coord( $coord_->x,$y); | |||
$level = $this->getLevelForCoord($gridData_, $coord, $width_, $height_); | |||
if(isset($level)) return $level; | |||
} | |||
break; | |||
case 1: | |||
for ($x = $coord_->x +1; $x < $width_; $x++) { | |||
$coord = new Coord( $x,$coord_->y); | |||
$level = $this->getLevelForCoord($gridData_, $coord, $width_, $height_); | |||
if(isset($level)){ | |||
return $level; | |||
} | |||
} | |||
break; | |||
case 2: | |||
for ($y = $coord_->y +1; $y < $height_; $y++) { | |||
$coord = new Coord( $coord_->x,$y); | |||
$level = $this->getLevelForCoord($gridData_, $coord, $width_, $height_); | |||
if(isset($level)) return $level; | |||
} | |||
break; | |||
case 3: | |||
for ($x = $coord_->x -1; $x >= 0; $x--) { | |||
$coord = new Coord( $x,$coord_->y); | |||
$level = $this->getLevelForCoord($gridData_, $coord, $width_, $height_); | |||
if(isset($level)) return $level; | |||
} | |||
break; | |||
} | |||
return null; | |||
} | |||
} |
@@ -0,0 +1,24 @@ | |||
<? | |||
require_once 'Utils/Helpers.php'; | |||
class FakeFile { | |||
/* | |||
'id' => 'integer', | |||
'id_post' => 'integer', | |||
'thread_key' => 'string', | |||
'fake_path' => 'string', | |||
'fake_name' => 'string', | |||
'file_name' => 'string'*/ | |||
function __construct($file_path_, $file_ext_, $map_key ) { | |||
$name = uniqid(); | |||
$this ->fake_name = $name.'.'.$file_ext_; | |||
$this ->file_name = Helpers::getRealFileName($this ->fake_name).'.'.$file_ext_; | |||
//$this ->fake_path = $file_path_."img/".$map_key."_". $this ->file_name; | |||
$this ->fake_path = $file_path_."php/uploads/".$map_key."/".Helpers::getRealFileName($this ->fake_name).'.'.$file_ext_; | |||
$this ->map_key = $map_key; | |||
} | |||
} |
@@ -0,0 +1,13 @@ | |||
<?php | |||
class Coord{ | |||
public $x; | |||
public $y; | |||
function __construct($x, $y ) { | |||
$this-> x = $x; | |||
$this-> y = $y; | |||
} | |||
} |
@@ -0,0 +1,15 @@ | |||
<? | |||
class GameData { | |||
public $player; | |||
public $players; | |||
public $posts; | |||
public $itemsPlayer; | |||
public $itemsMap; | |||
function __construct() { | |||
} | |||
} |
@@ -0,0 +1,106 @@ | |||
<? | |||
class Item { | |||
public $name; | |||
public $description; | |||
public $player_id; // owner ID | |||
public $map_key; | |||
public $key; | |||
public $action; | |||
public $type; | |||
public $itemsPerPlayer; | |||
//weapon | |||
//potion | |||
//paint | |||
//sponge | |||
//ring | |||
//armor | |||
//Influence it has | |||
public $is_expendable = true; | |||
public $numOfUse; | |||
public $value; | |||
//---------------- | |||
public $valueMin; | |||
public $valueMax; | |||
function __construct() { | |||
} | |||
public static function getAllPotentialItems() | |||
{ | |||
$items = array(); | |||
$item = new Item(); | |||
$item-> name = "sponge"; | |||
$item-> action = "post delete"; | |||
$item-> type = "posting"; | |||
$item-> description = "The sponge give you the ability to make disappear a post that isn't canon"; | |||
$item-> is_expendable = true; | |||
$item-> valueMin = 1; | |||
$item-> valueMax = 3; | |||
$item-> itemsPerPlayer = 1; | |||
array_push( $items ,$item); | |||
/* | |||
$item = new Item(); | |||
$item-> name = "ring of upload"; | |||
$item-> action = "upload"; | |||
$item-> type = "posting"; | |||
$item-> description = "Give you the ability to upload picture when you post"; | |||
$item-> is_expendable = false; | |||
$item-> valueMin = 10; | |||
$item-> valueMax = 18; | |||
$item-> itemsPerPlayer = 1; | |||
array_push( $items ,$item); | |||
$item = new Item(); | |||
$item-> name = "pen"; | |||
$item-> action = "drawing"; | |||
$item-> type = "posting"; | |||
$item-> description = "Give you the ability to draw"; | |||
$item-> is_expendable = true; | |||
$item-> valueMin = 1; | |||
$item-> valueMax = 10; | |||
$item-> itemsPerPlayer = 10; | |||
array_push( $items ,$item); | |||
$item = new Item(); | |||
$item-> name = "black powder"; | |||
$item-> action = "canon"; | |||
$item-> type = "posting"; | |||
$item-> description = "Set a post as canon"; | |||
$item-> is_expendable = true; | |||
$item-> valueMin = 1; | |||
$item-> valueMax = 5; | |||
$item-> itemsPerPlayer = 3; | |||
array_push( $items ,$item); | |||
$item = new Item(); | |||
$item-> name = "knife"; | |||
$item-> action = "harm"; | |||
$item-> type = "fight"; | |||
$item-> description = "You can kill enemies from the dungeon or even other anons"; | |||
$item-> is_expendable = true; | |||
$item-> valueMin = 99; | |||
$item-> valueMax = 100; | |||
$item-> itemsPerPlayer = 1; | |||
array_push( $items ,$item); | |||
$item = new Item(); | |||
$item-> name = "rope"; | |||
$item-> action = "bound"; | |||
$item-> type = "fight"; | |||
$item-> description = "You bound certain enemies and anons"; | |||
$item-> is_expendable = true; | |||
$item-> valueMin = 2; | |||
$item-> valueMax = 4; | |||
$item-> itemsPerPlayer = 1; | |||
array_push( $items ,$item);*/ | |||
return $items; | |||
} | |||
} |
@@ -0,0 +1,362 @@ | |||
<?php | |||
class Level { | |||
public $name; | |||
public $key; | |||
public $theme = "medieval"; | |||
public $x; | |||
public $y; | |||
public $width; | |||
public $height; | |||
public $data; | |||
public $door_key_n; | |||
public $door_key_e; | |||
public $door_key_s; | |||
public $door_key_w; | |||
public $is_safe = false; | |||
public $is_chan = false; | |||
public $is_secret = false; | |||
public $level_data; | |||
/* | |||
public $TILE_GROUND = 0; | |||
public $TILE_WALL = 1; | |||
public $TILE_WALL_DRAWABLE = 2; | |||
public $TILE_DOOR = 3;*/ | |||
function __construct( $name, $width, $height, $is_chan, $is_secret) { | |||
$this-> name = $name; | |||
$this-> width = $width; | |||
$this-> height = $height; | |||
$this-> is_chan = $is_chan; | |||
$this-> is_secret = $is_secret; | |||
$this-> key = $name; | |||
} | |||
public function setKeyForDir($key_,$dir_){ | |||
switch($dir_){ | |||
case 0: | |||
$this -> door_key_n = $key_; | |||
break; | |||
case 1: | |||
$this -> door_key_e = $key_; | |||
break; | |||
case 2: | |||
$this -> door_key_s = $key_; | |||
break; | |||
case 3: | |||
$this -> door_key_w = $key_; | |||
break; | |||
} | |||
} | |||
public function getNumDoors(){ | |||
$num = 0; | |||
if(isset($this -> door_key_n)) $num ++; | |||
if(isset($this -> door_key_e)) $num ++; | |||
if(isset($this -> door_key_s)) $num ++; | |||
if(isset($this -> door_key_w)) $num ++; | |||
return $num; | |||
} | |||
public function getDoorCoordKey($key_){ | |||
$x = 0; | |||
$y = 0; | |||
//test N | |||
if($key_ == $this -> door_key_n){ | |||
for($x = 0 ; $x < $this->width ; $x++ ){ | |||
$tile = $this -> pickTile($this->width, $this->height,new Coord($x , $y)); | |||
if($tile == Tile::getValueForName("gate")) return new Coord($x,$y); | |||
} | |||
} else if($key_ == $this -> door_key_e){ | |||
$x = $this->width - 1; | |||
for($y = 0 ; $y < $this->height ; $y++ ){ | |||
$tile = $this -> pickTile( $this->width, $this->height, new Coord($x , $y)); | |||
if($tile == Tile::getValueForName("gate")) return new Coord($x,$y); | |||
} | |||
} else if($key_ == $this -> door_key_s){ | |||
$y = $this->height - 1; | |||
for($x = 0 ; $x < $this->width ; $x++ ){ | |||
$tile = $this -> pickTile($this->width, $this->height,new Coord($x , $y)); | |||
if($tile == Tile::getValueForName("gate")) return new Coord($x,$y); | |||
} | |||
}else if($key_ == $this -> door_key_w){ | |||
for($y = 0 ; $y < $this->height ; $y++ ){ | |||
$tile = $this -> pickTile($this->width, $this->height,new Coord($x , $y)); | |||
if($tile == Tile::getValueForName("gate")) return new Coord($x,$y); | |||
} | |||
} | |||
return null; | |||
} | |||
public function placePlayerForKey($key_){ | |||
$coord = $this -> getDoorCoordKey($key_); | |||
if($coord->y == 0) { | |||
return new Coord($coord->x , $coord->y+1); | |||
} else if($coord->x == $this->width-1) { | |||
return new Coord($coord->x-1 , $coord->y); | |||
}else if($coord->y == $this->height-1) { | |||
return new Coord($coord->x , $coord->y-1); | |||
}else if($coord->x == 0) { | |||
return new Coord($coord->x+1 , $coord->y); | |||
} | |||
return new Coord(1 , 1); | |||
} | |||
public function initLevelData(){ | |||
//New version: all the level are the same | |||
$this->level_data = | |||
[ | |||
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, | |||
1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1, | |||
1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1, | |||
1,0,0,1,1,1,1,1,1,1,1,1,1,1,1,0,0,1, | |||
1,0,0,1,0,0,0,0,0,1,0,4,0,0,1,0,0,1, | |||
1,0,0,1,0,0,13,0,0,1,0,1,0,0,1,0,0,1, | |||
1,0,0,1,0,0,0,0,0,1,0,1,0,0,1,0,0,1, | |||
1,0,0,1,0,0,0,0,0,1,3,1,0,0,1,0,0,1, | |||
1,0,0,1,1,1,4,1,1,1,1,1,0,0,1,0,0,1, | |||
1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,1, | |||
1,1,1,1,1,1,1,1,1,1,1,1,0,0,1,0,0,1, | |||
1,0,0,0,0,0,0,0,0,0,0,1,0,0,1,0,0,1, | |||
14,0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,1, | |||
1,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,1, | |||
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 | |||
]; | |||
$this-> width = 18; | |||
$this-> height = 15; | |||
/* | |||
//Create a middle room | |||
//Middle room looks cool everywhere | |||
$this->fillgrid(Tile::getValueForName("ground"), $this->width, $this->height); | |||
//Place wall | |||
$this->makeWallForLevel(); | |||
//place gates | |||
$coord = new Coord(0,0); | |||
if(isset( $this -> door_key_n)){ | |||
$coord ->y = 0; | |||
$coord ->x = rand(1, $this->width-2); | |||
$this->placeToLevel(Tile::getValueForName("gate"), $this->width, $this->height, $coord); | |||
} | |||
if(isset( $this -> door_key_e)){ | |||
$coord ->y = rand(1, $this->height-2); | |||
$coord ->x = $this->width-1; | |||
$this->placeToLevel(Tile::getValueForName("gate"), $this->width, $this->height, $coord); | |||
} | |||
if(isset( $this -> door_key_s)){ | |||
$coord ->y = $this->height-1; | |||
$coord ->x = rand(1, $this->width-2); | |||
$this->placeToLevel(Tile::getValueForName("gate"), $this->width, $this->height, $coord); | |||
} | |||
if(isset( $this -> door_key_w)){ | |||
$coord ->y = rand(1, $this->height-2); | |||
$coord ->x = 0; | |||
$this->placeToLevel(Tile::getValueForName("gate"), $this->width, $this->height, $coord); | |||
}*/ | |||
//Display the level | |||
$this -> displayLevelData(); | |||
} | |||
function makeWallForLevel(){ | |||
//North wall | |||
$y = 0; | |||
for ($x = 0 ; $x <= $this-> width ; $x++){ | |||
$coord = new Coord($x,$y); | |||
$this->placeToLevel(Tile::getValueForName("wall"), $this->width, $this->height, $coord); | |||
} | |||
//South wall | |||
$y = $this->height-1; | |||
for ($x = 0 ; $x < $this-> width ; $x++){ | |||
$coord = new Coord($x,$y); | |||
$this->placeToLevel(Tile::getValueForName("wall"), $this->width, $this->height, $coord); | |||
} | |||
//West | |||
$x = 0; | |||
for ($y = 0 ; $y < $this-> height ; $y++){ | |||
$coord = new Coord($x,$y); | |||
$this->placeToLevel(Tile::getValueForName("wall"), $this->width, $this->height, $coord); | |||
} | |||
//Est | |||
$x = $this->width-1; | |||
for ($y = 0 ; $y < $this-> height ; $y++){ | |||
$coord = new Coord($x,$y); | |||
$this->placeToLevel(Tile::getValueForName("wall"), $this->width, $this->height, $coord); | |||
} | |||
} | |||
public function displayLevelData(){ | |||
echo "# MAP ".$this->name." num tiles:".count($this->level_data)."<br/>"; | |||
$x = 0; | |||
$y = 0; | |||
foreach($this->level_data as $data){ | |||
//echo "x:".$x."y:".$y."<br/>"; | |||
/* | |||
if(!isset( $data ) || $data == Tile::getValueForName("wall") ){ | |||
echo "#"; | |||
} else if($data == Tile::getValueForName("ground")) { | |||
echo "."; | |||
} else if($data == Tile::getValueForName("door")) { | |||
//echo "x:".$x."y:".$y."<br/>"; | |||
echo "D"; | |||
}*/ | |||
echo Tile::getDisplayForVal($data); | |||
$x ++; | |||
if($x >= $this -> width){ | |||
$x = 0; | |||
$y ++; | |||
echo "<br/>"; | |||
} | |||
} | |||
} | |||
//Level Data management | |||
function fillgrid($defaultTile_, $width_, $height_){ | |||
$this->level_data = array(); | |||
for ($i = 0; $i < $height_*$width_; $i++) { | |||
array_push( $this->level_data ,$defaultTile_); | |||
} | |||
} | |||
function placeToLevel($data, $width_, $height_, $coord){ | |||
$this->level_data [ ( $coord->y *$width_) + $coord->x] = $data; | |||
} | |||
function pickTile($width_, $height_, $coord){ | |||
return $this->level_data [ ( $coord->y *$width_)+ $coord->x]; | |||
} | |||
//Fill a data base row | |||
public function fillRow($row_){ | |||
echo "Write level: ".$this-> name."; for key".$this-> key." with ".count($this-> level_data)." data"; | |||
$row_ -> key = $this-> key; | |||
$row_ -> name = $this-> name; | |||
$row_ -> theme = $this-> theme; | |||
/* | |||
$row_ -> x = $this-> x; | |||
$row_ -> y = $this-> y; | |||
*/ | |||
$row_ -> width = $this-> width; | |||
$row_ -> height = $this-> height; | |||
if(isset( $this-> door_key_n))$row_ -> door_key_n = $this-> door_key_n; | |||
if(isset( $this-> door_key_e)) $row_ -> door_key_e = $this-> door_key_e; | |||
if(isset( $this-> door_key_s)) $row_ -> door_key_s = $this-> door_key_s; | |||
if(isset( $this-> door_key_w)) $row_ -> door_key_w = $this-> door_key_w; | |||
$dataString = ""; | |||
foreach( $this-> level_data as $data ){ | |||
$dataString = $dataString.$data.","; | |||
} | |||
$dataString = $dataString .substr(0, strlen($dataString) - 1); | |||
$row_ -> level_data = $dataString; | |||
$row_ -> is_safe = $this-> is_safe; | |||
$row_ -> is_chan = $this-> is_chan; | |||
$row_ -> is_secret = $this-> is_secret; | |||
//var_dump( $row_); | |||
return $row_; | |||
} | |||
//Get Ground tiles | |||
public function getEmptyCoord(){ | |||
$coords = array(); | |||
$x = 0; | |||
$y = 0; | |||
foreach( $this-> level_data as $data ){ | |||
if((int) $data == Tile::getValueForName("ground")){ | |||
$coord = new Coord($x,$y); | |||
array_push($coords,$coord); | |||
} | |||
$x ++; | |||
if($x >= $this-> width){ | |||
$y ++; | |||
$x = 0; | |||
} | |||
} | |||
return $coords[rand( 0, count( $coords )-1)]; | |||
} | |||
//Fill a data base row | |||
public static function parseRow($row_){ | |||
$level = new Level("",0,0,false, false); | |||
$level -> key = $row_ -> key; | |||
$level -> name = $row_ -> name; | |||
$level -> theme = $row_ -> theme; | |||
$level -> is_secret = $row_ -> is_secret; | |||
$level -> x = $row_ -> x; | |||
$level -> y = $row_ -> y; | |||
$level -> width = $row_ -> width; | |||
$level -> height = $row_ -> height; | |||
if(isset( $row_-> door_key_n)) $level -> door_key_n = $row_-> door_key_n; | |||
if(isset( $row_-> door_key_e)) $level -> door_key_e = $row_-> door_key_e; | |||
if(isset( $row_-> door_key_s)) $level -> door_key_s = $row_-> door_key_s; | |||
if(isset( $row_-> door_key_w)) $level -> door_key_w = $row_-> door_key_w; | |||
//parse the data | |||
$level -> level_data = explode(",",$row_ -> level_data); | |||
$level -> is_safe = $row_-> is_safe; | |||
$level -> is_chan = $row_-> is_chan; | |||
return $level ; | |||
} | |||
//Fill a data base row | |||
public static function getDim($num){ | |||
$minTile = 4; | |||
if($num < $minTile ) $num = $minTile; | |||
$width = rand ( $minTile , $num - $minTile ); | |||
$height = $num - $width; | |||
return new Coord( $width, $height); | |||
} | |||
} |
@@ -0,0 +1,56 @@ | |||
<? | |||
class Tile { | |||
public $value; | |||
public $display; | |||
public $name; | |||
public $descitption; | |||
function __construct( $value, $display, $name, $descitption) { | |||
$this -> value = $value; | |||
$this -> display = $display; | |||
$this -> name = $name; | |||
$this -> descitption = $descitption; | |||
} | |||
public static function getAllTiles() | |||
{ | |||
$tiles = array(); | |||
array_push( $tiles, new Tile(0,".","ground","You can walk on it.")); | |||
array_push( $tiles, new Tile(1,"█","wall","You cannot go thought it.")); | |||
array_push( $tiles, new Tile(2,"#","drawable wall","Like a wall, but you can post on it.")); | |||
array_push( $tiles, new Tile(3,"/","gate","An entrance to another level.")); | |||
array_push( $tiles, new Tile(4,"D","door","You can open it.")); | |||
array_push( $tiles, new Tile(5,"▓","fake wall","You can open it.")); | |||
/* array_push( $tiles, new Tile(6,"*","trap","It can kill you.")); | |||
array_push( $tiles, new Tile(7,";","grass","just green ground")); | |||
array_push( $tiles, new Tile(8,"±","shrine","Special items goes there.")); | |||
array_push( $tiles, new Tile(9,"f","fire","You cannot cross.")); | |||
array_push( $tiles, new Tile(10,"R","fast food","You can fullfil your health here"));*/ | |||
array_push( $tiles, new Tile(11,"t","seed","You will found torrent of the board here")); | |||
//array_push( $tiles, new Tile(12,"A","Advertisement wall","It's used to display advertisement.")); | |||
array_push( $tiles, new Tile(13,"s","Player start","It's the point of arrival of a player. All map need one")); | |||
array_push( $tiles, new Tile(14,"|","gate secret","An entrance to secret level.")); | |||
return $tiles; | |||
} | |||
public static function getValueForName($name) | |||
{ | |||
$tiles = Tile::getAllTiles(); | |||
foreach ($tiles as $tile){ | |||
if($tile->name == $name) return $tile->value; | |||
} | |||
return -1; | |||
} | |||
public static function getDisplayForVal($val) | |||
{ | |||
$tiles = Tile::getAllTiles(); | |||
foreach ($tiles as $tile){ | |||
if($tile->value == $val) return $tile->display; | |||
} | |||
return -1; | |||
} | |||
} |
@@ -0,0 +1,69 @@ | |||
<? | |||
class Post { | |||
/* | |||
'id' => 'integer', | |||
'key' => 'string', | |||
'scale' => 'integer', | |||
'date' => 'integer', | |||
'player_ip' => 'string', | |||
'player_id' => 'integer', | |||
'is_canon' => 'boolean', | |||
'nsfw' => 'boolean', | |||
'player_name' => 'string', | |||
'thread_key' => 'string', | |||
'canvas_key' => 'string', | |||
'message' => 'string', | |||
'url' => 'string', | |||
'magnet' => 'string', | |||
'torrent' => 'string', | |||
'hash' => 'string' | |||
*/ | |||
public $id; | |||
public $key; | |||
public $scale; | |||
public $date; | |||
public $reply; | |||
public $player_ip; | |||
public $player_id; | |||
public $is_canon; | |||
public $nsfw; | |||
public $player_name; | |||
public $map_key; | |||
public $canvas_key; | |||
public $message; | |||
public $url; | |||
public $magnet; | |||
public $hash; | |||
public $graffiti; | |||
function __construct( ) { | |||
$this ->url = ""; | |||
$this ->map_key = ""; | |||
$this ->message = ""; | |||
$this ->magnet = ""; | |||
$this ->hash = ""; | |||
$this ->player_name = "anonymous"; | |||
$this ->graffiti = 'false'; | |||
$this ->reply = ""; | |||
} | |||
function fillWithPostData(){ | |||
if( isset($_POST['tmap_key']) ) $this -> map_key = $_POST['map_key']; | |||
if( isset($_POST['canvas_key']) ) $this -> canvas_key = $_POST['canvas_key']; | |||
if( isset($_POST['message']) ) $this -> message = $_POST['message']; | |||
if( isset($_POST['magnet']) ) $this -> magnet = $_POST['magnet']; | |||
if( isset($_POST['url']) ) $this -> url = $_POST['url']; | |||
if( isset($_POST['hash']) ) $this -> hash = $_POST['hash']; | |||
if( isset($_POST['graffiti']) ) $this -> graffiti = $_POST['graffiti']; | |||
if( isset($_POST['reply']) ) $this -> reply = $_POST['reply']; | |||
} | |||
} |
@@ -0,0 +1,51 @@ | |||
<?php | |||
/* | |||
______ __ __ | |||
/ ____/___ ____ _____/ /_____ _____ / /______ | |||
/ / / __ \/ __ \/ ___/ __/ __ `/ __ \/ __/ ___/ | |||
/ /___/ /_/ / / / (__ ) /_/ /_/ / / / / /_(__ ) | |||
\____/\____/_/ /_/____/\__/\__,_/_/ /_/\__/____/ | |||
List of constant of the server, helping to make the database files hard to find | |||
*/ | |||
//FOLDERS & DB | |||
class Constants { | |||
const CONST_DB_FOLDER = "data"; | |||
const CONST_CONFIG_FOLDER = "config"; | |||
const CONST_MAP_FOLDER = "maps"; | |||
const CONST_TABLE_CHANS = "chans"; | |||
const CONST_TABLE_POSTS = "posts"; | |||
const CONST_TABLE_LOGS = "logs"; | |||
const CONST_TABLE_MAP = "maps"; | |||
const CONST_TABLE_ITEMS = "items"; | |||
const CONST_TABLE_LOOT = "loot"; | |||
const CONST_TABLE_THREADS = "threads"; | |||
const CONST_TABLE_BANS = "bans"; | |||
const CONST_TABLE_FILES = "files"; | |||
const CONST_TABLE_PLAYERS = "players"; | |||
const CONST_TABLE_THREADS_TOP = "threads_top"; | |||
const CONST_NUM_THREAD_MAX = 100; | |||
const CONST_FILES_EXT_ERROR = "Only image extension and mp3 are allowed."; | |||
const CONST_FILES_MAX_SIZE = 25097152; | |||
const CONST_FILES_MAX_SIZE_ERROR = 'File size cannot exceed 25 MB'; | |||
const CONST_FILES_MAX_NUM = 5; | |||
const CONST_PASSWORD_FOLDER = "password"; | |||
const CONST_PASSWORD_FILE = "password.txt"; | |||
const SITE_TORRENT_DESC = "AnonIB💀3D, by AElx Krunch https://twitter.com/alexkrunch"; | |||
const CONST_IMAGE_UPLOAD_FOLDER = "uploads"; | |||
const CONST_IMAGE_PREVIEW_FOLDER = "previews"; | |||
const CONST_IMAGE_SALT = "SnUffCh4N"; | |||
const CONST_MAP_ALPHA_NAME = "alpha"; | |||
} |
@@ -0,0 +1,199 @@ | |||
<?php | |||
/* | |||
__ __ __ | |||
/ / / /__ / /___ ___ __________ | |||
/ /_/ / _ \/ / __ \/ _ \/ ___/ ___/ | |||
/ __ / __/ / /_/ / __/ / (__ ) | |||
/_/ /_/\___/_/ .___/\___/_/ /____/ | |||
/_/ | |||
Static function to help | |||
*/ | |||
require_once "./Utils/Constants.php"; | |||
class Helpers | |||
{ | |||
/** | |||
* Construct won't be called inside this class and is uncallable from | |||
* the outside. This prevents instantiating this class. | |||
* This is by purpose, because we want a static class. | |||
*/ | |||
private function __construct() {} | |||
private static $initialized = false; | |||
private static function initialize() | |||
{ | |||
if (self::$initialized) | |||
return; | |||
self::$initialized = true; | |||
} | |||
/** | |||
* Serialize the LarZer data in Array. | |||
*/ | |||
public static function getDataFromLazer($lazerObj) | |||
{ | |||
self::initialize(); | |||
$lazerObj = (array) $lazerObj; | |||
if(array_key_exists ( '' . "\0" . '*' . "\0" . 'data' , $lazerObj ) && $lazerObj[ '' . "\0" . '*' . "\0" . 'data'] != null){ | |||
$lazerObj = (array) $lazerObj[ '' . "\0" . '*' . "\0" . 'data']; | |||
} else if(array_key_exists ( '' . "\0" . '*' . "\0" . 'set' , $lazerObj ) && $lazerObj[ '' . "\0" . '*' . "\0" . 'set'] != null){ | |||
$lazerObj = (array) $lazerObj[ '' . "\0" . '*' . "\0" . 'set']; | |||
} | |||
return $lazerObj; | |||
} | |||
/** | |||
* Get the dead line to consider a player as inactive. | |||
* (surival of a video game version of the forum) | |||
*/ | |||
public static function getDeadline() | |||
{ | |||
self::initialize(); | |||
$currentTimeStamp = time(); | |||
$deadLine = $currentTimeStamp - 3600; | |||
return $deadLine; | |||
} | |||
/** | |||
* Get the dead line to consider a player should be deleted. | |||
* (surival of a video game version of the forum) | |||
*/ | |||
public static function getDeletionline() | |||
{ | |||
self::initialize(); | |||
$currentTimeStamp = time(); | |||
$deadLine = $currentTimeStamp - 3600*24; | |||
return $deadLine; | |||
} | |||
/** | |||
* make a generic response for Web services | |||
*/ | |||
public static function makeGenericResponse($isOk, $result, $error) | |||
{ | |||
self::initialize(); | |||
//prepare the result | |||
$response = array( | |||
'ok' => $isOk, | |||
'result' => $result, | |||
'error' => $error | |||
); | |||
header("Content-type: application/json"); | |||
echo json_encode($response); | |||
exit(); | |||
} | |||
/** | |||
* Get the user IP | |||
*/ | |||
public static function getClientIp() { | |||
// IP si internet partagé | |||
if (isset($_SERVER['HTTP_CLIENT_IP'])) { | |||
return $_SERVER['HTTP_CLIENT_IP']; | |||
} | |||
// IP derrière un proxy | |||
elseif (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) { | |||
return $_SERVER['HTTP_X_FORWARDED_FOR']; | |||
} | |||
// Sinon : IP normale | |||
else { | |||
return (isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : ''); | |||
} | |||
} | |||
/** | |||
* CHECK IF BASE64 code is an image | |||
*/ | |||
public static function check_base64_image($base64) { | |||
$img = imagecreatefromstring(base64_decode($base64)); | |||
if (!$img) { | |||
return false; | |||
} | |||
imagepng($img, 'tmp.png'); | |||
$info = getimagesize('tmp.png'); | |||
unlink('tmp.png'); | |||
if ($info[0] > 0 && $info[1] > 0 && $info['mime']) { | |||
return true; | |||
} | |||
return false; | |||
} | |||
/* | |||
* Check Base64 size | |||
*/ | |||
public static function getBase64ImageSize($base64Image){ //return memory size in B, KB, MB | |||
try{ | |||
$size_in_bytes = (int) (strlen(rtrim($base64Image, '=')) * 3 / 4); | |||
$size_in_kb = $size_in_bytes / 1024; | |||
return $size_in_kb; | |||
} | |||
catch(Exception $e){ | |||
return $e; | |||
} | |||
} | |||
/** | |||
* Generate random Token | |||
*/ | |||
public static function generateToken(){ | |||
//Generate a random string. | |||
$token = openssl_random_pseudo_bytes(16); | |||
//Convert the binary data into hexadecimal representation. | |||
return bin2hex($token); | |||
} | |||
/** | |||
* Hash password | |||
*/ | |||
public static function hash_pw($plain_pw) | |||
{ | |||
// (optional) change logic here for different hash algorithm | |||
//return password_hash($plain_pw, PASSWORD_DEFAULT); | |||
return md5($plain_pw); | |||
} | |||
/** | |||
* Verify hashed password | |||
*/ | |||
public static function verify_pw($plain_pw, $hashed_pw) | |||
{ | |||
// (optional) change logic here for different hash algorithm | |||
//return password_verify($plain_pw, $hashed_pw); | |||
return (md5($plain_pw)==$hashed_pw); | |||
} | |||
/** | |||
* Get Real File Name | |||
*/ | |||
public static function getRealFileName($fileName_) | |||
{ | |||
return md5($fileName_.'_'.Constants::CONST_IMAGE_SALT); | |||
} | |||
} |
@@ -0,0 +1,241 @@ | |||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> | |||
<html> | |||
<head> | |||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> | |||
<link href="CSS/bootstrap-hacker-theme/css/bootstrap4-neon-glow.min.css" rel="stylesheet"> | |||
<link href="CSS/style.css" rel="stylesheet"> | |||
<title>ADMIN OF THE BOARD</title> | |||
</head> | |||
<body> | |||
<div>===================</div> | |||
<div>ADMIN OF THE BOARD</div> | |||
<div>===================</div> | |||
<div> | |||
<div>Manage the database player+arts here.</div> | |||
<div style="font-size:xx-small">Map powered by LAZER®</div> | |||
<br/> | |||
<div>Admin pswd: | |||
<br><input id="admin-password" type="password"/> | |||
</div> | |||
<button onClick="setPassword()">Set password</button> | |||
<button onClick="validPassword()">Test password</button> | |||
<br/> | |||
<div id="manage-interface"> | |||
<div>------------------------</div> | |||
<div><b>List of the different WS</b></div> | |||
<div> | |||
<button onClick="initDb()">Init the Database</button> | |||
<button onClick="eraseDb()">Erase the Database</button><br/> | |||
<button onClick="initBans()">Init the Bans table</button> | |||
<button onClick="eraseBans()">Erase the Bans table</button><br/> | |||
<button onClick="initMapsAndPosts()">Init Maps snd Posts</button> | |||
<button onClick="eraseMapsAndPosts()">Erase Maps and Posts</button> | |||
</div> | |||
</div> | |||
<div>------------------------</div> | |||
<div><b>Web service response</b></div> | |||
<textarea id="admin-ws_response" type="" name="" rows="4" cols="60" placeholder="The WS response"></textarea> | |||
</div> | |||
<br/> | |||
</body> | |||
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js" type="text/javascript"></script> | |||
<script> | |||
//Manage the DB | |||
function initDb(){ | |||
$.ajax({ | |||
type: "POST", | |||
url: "DatabaseWebService.php", | |||
data: { | |||
'action':'initDB', | |||
'password': $( '#admin-password' ).val() | |||
}, | |||
success:function(data){ | |||
$("#admin-ws_response").val(data); | |||
}, | |||
error: function(xhr, textStatus, errorThrown){ | |||
console("Some error happened"); | |||
$("#admin-ws_response").val("xhr ="+xhr+"; textStatus= "+textStatus+"; errorThrown="+errorThrown); | |||
} | |||
}); | |||
} | |||
function initMapsAndPosts(){ | |||
$.ajax({ | |||
type: "POST", | |||
url: "DatabaseWebService.php", | |||
data: { | |||
'action':'initMapsAndPosts', | |||
'password': $( '#admin-password' ).val() | |||
}, | |||
success:function(data){ | |||
$("#admin-ws_response").val(data); | |||
}, | |||
error: function(xhr, textStatus, errorThrown){ | |||
console("Some error happened"); | |||
$("#admin-ws_response").val("xhr ="+xhr+"; textStatus= "+textStatus+"; errorThrown="+errorThrown); | |||
} | |||
}); | |||
} | |||
function eraseDb(){ | |||
$.ajax({ | |||
type: "POST", | |||
url: "DatabaseWebService.php", | |||
data: { | |||
'action':'destroyDB', | |||
'password': $( '#admin-password' ).val() | |||
}, | |||
success:function(data){ | |||
$("#admin-ws_response").val(data); | |||
}, | |||
error: function(xhr, textStatus, errorThrown){ | |||
console("Some error happened"); | |||
$("#admin-ws_response").val("xhr ="+xhr+"; textStatus= "+textStatus+"; errorThrown="+errorThrown); | |||
} | |||
}); | |||
} | |||
function eraseMapsAndPosts(){ | |||
$.ajax({ | |||
type: "POST", | |||
url: "DatabaseWebService.php", | |||
data: { | |||
'action':'destroyMapsAndPosts', | |||
'password': $( '#admin-password' ).val() | |||
}, | |||
success:function(data){ | |||
$("#admin-ws_response").val(data); | |||
}, | |||
error: function(xhr, textStatus, errorThrown){ | |||
console("Some error happened"); | |||
$("#admin-ws_response").val("xhr ="+xhr+"; textStatus= "+textStatus+"; errorThrown="+errorThrown); | |||
} | |||
}); | |||
} | |||
//erase bans | |||
function eraseBans(){ | |||
$.ajax({ | |||
type: "POST", | |||
url: "DatabaseWebService.php", | |||
data: { | |||
'action':'destroyBans', | |||
'password': $( '#admin-password' ).val() | |||
}, | |||
success:function(data){ | |||
$("#admin-ws_response").val(data); | |||
}, | |||
error: function(xhr, textStatus, errorThrown){ | |||
console("Some error happened"); | |||
$("#admin-ws_response").val("xhr ="+xhr+"; textStatus= "+textStatus+"; errorThrown="+errorThrown); | |||
} | |||
}); | |||
} | |||
//erase bans | |||
function initBans(){ | |||
$.ajax({ | |||
type: "POST", | |||
url: "DatabaseWebService.php", | |||
data: { | |||
'action':'initBans', | |||
'password': $( '#admin-password' ).val() | |||
}, | |||
success:function(data){ | |||
$("#admin-ws_response").val(data); | |||
}, | |||
error: function(xhr, textStatus, errorThrown){ | |||
console("Some error happened"); | |||
$("#admin-ws_response").val("xhr ="+xhr+"; textStatus= "+textStatus+"; errorThrown="+errorThrown); | |||
} | |||
}); | |||
} | |||
//Password SET | |||
function setPassword(){ | |||
$.ajax({ | |||
type: "POST", | |||
url: "ChanWebService.php", | |||
data: { | |||
'action':'setAdminPassword', | |||
'password': $( '#admin-password' ).val() | |||
}, | |||
success:function(data){ | |||
$("#admin-ws_response").val("password settings is "+data.result+"; if false it's mean there's probabably already a password"); | |||
}, | |||
error: function(xhr, textStatus, errorThrown){ | |||
console("Some error happened"); | |||
$("#admin-ws_response").val("xhr ="+xhr+"; textStatus= "+textStatus+"; errorThrown="+errorThrown); | |||
} | |||
}); | |||
} | |||
function validPassword(){ | |||
$.ajax({ | |||
type: "POST", | |||
url: "ChanWebService.php", | |||
data: { | |||
'action':'validAdmin', | |||
'password': $( '#admin-password' ).val() | |||
}, | |||
success:function(data){ | |||
$("#admin-ws_response").val("password test is "+data.result); | |||
}, | |||
error: function(xhr, textStatus, errorThrown){ | |||
console("Some error happened"); | |||
$("#admin-ws_response").val("xhr ="+xhr+"; textStatus= "+textStatus+"; errorThrown="+errorThrown); | |||
} | |||
}); | |||
} | |||
</script> | |||
</html> |
@@ -0,0 +1,9 @@ | |||
{ | |||
"name":"Noodle Demo", | |||
"description":"Test server with Noodle-IB. ✌⊂(✰‿✰)つ✌", | |||
"rules":"Your rules here.", | |||
"bannerImg":"https://pbs.twimg.com/media/DmBnJhaW4AAiZtn.jpg", | |||
"contact":"alexkrunch@gmail.com", | |||
"isMap":false, | |||
"flavours":["alpha","techno","oktaku"] | |||
} |
@@ -0,0 +1,2 @@ | |||
# Block External Access | |||
deny from all |
@@ -0,0 +1,2 @@ | |||
# Block External Access | |||
deny from all |