@@ -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 |