webservercontroller.js 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. var url = require('url'),
  2. http = require('http'),
  3. mime = require('mime-types'),
  4. fs = require('fs');
  5. module.exports = class WebserverController {
  6. handleRequest(config, request, response) {
  7. switch(request.method.toLowerCase()) {
  8. case "post":
  9. this.handlePostRequest(config, request, response);
  10. break;
  11. case "get":
  12. default:
  13. this.handleGetRequest(config, request, response);
  14. break;
  15. }
  16. }
  17. handlePostRequest(config, request, response) {
  18. var body = '';
  19. var self = this;
  20. request.on('data', function(chunk) {
  21. body += chunk.toString();
  22. });
  23. request.on('end', function() {
  24. var keyValuePairs = body.split("&");
  25. var postData = {};
  26. for(var i in keyValuePairs) {
  27. var block = keyValuePairs[i].split("=");
  28. postData[block[0]] = block[1];
  29. }
  30. self.handleRoutes(config, request, response, postData);
  31. });
  32. }
  33. handleRoutes(config, request, response, body) {
  34. var parsedUrl = url.parse(request.url, true);
  35. var pathname = parsedUrl.pathname;
  36. var pathParts = pathname.replace(/^\/+/gm, '').split("/");
  37. if(pathParts[0] == "api") {
  38. pathParts.shift(); //drop api
  39. var responseData = null;
  40. switch(pathParts.shift()) {
  41. case "current":
  42. this.current(config, request, response);
  43. break;
  44. case "register":
  45. this.register(config, request, response, body);
  46. break;
  47. default:
  48. this.help(request, response);
  49. break;
  50. }
  51. return;
  52. }
  53. var filename = config.websitePath;
  54. if(config.routes.hasOwnProperty(pathname)) {
  55. filename += config.routes[pathname];
  56. } else {
  57. filename += pathname;
  58. }
  59. fs.stat(filename, function(err, stat) {
  60. if(err != null) {
  61. if(err.code == 'ENOENT') {
  62. response.writeHead(404, {'Content-Type': 'text/html'});
  63. response.write("404 Page Not Found");
  64. } else {
  65. response.writeHead(500, {'Content-Type': 'text/html'});
  66. response.write("500 Server Error");
  67. }
  68. response.end();
  69. return;
  70. }
  71. fs.readFile(filename, function(err, data) {
  72. var mimeType = mime.lookup(filename);
  73. response.writeHead(200, {'Content-Type': mimeType});
  74. response.write(data);
  75. response.end();
  76. });
  77. });
  78. }
  79. handleGetRequest(config, request, response) {
  80. this.handleRoutes(config, request, response, {});
  81. }
  82. current(config, request, response) {
  83. var responseData = {};
  84. var activePlayers = [];
  85. for(var i in session.players) {
  86. var player = session.players[i];
  87. activePlayers.push(player.name);
  88. }
  89. responseData.players = activePlayers;
  90. response.writeHead(200, {'Content-Type': 'application/json'});
  91. response.write(JSON.stringify(responseData, null, '\t'));
  92. response.end();
  93. }
  94. register(config, request, response, body) {
  95. if(!config.allowRegistration) {
  96. response.writeHead(200, {'Content-Type': 'application/json'});
  97. response.write(JSON.stringify({"status": "error", "error": "Registration is not enabled at this time."}, null, '\t'));
  98. response.end();
  99. return;
  100. }
  101. //TODO: make sure username is valid and not already claimed
  102. if(!this.isValidUsername(config, body.username)) {
  103. response.writeHead(200, {'Content-Type': 'application/json'});
  104. response.write(JSON.stringify({"status": "error", "error": "That username is not available."}, null, '\t'));
  105. response.end();
  106. return;
  107. }
  108. var newPlayer = builder.mud_spawnMobile("PlayerMobile");
  109. newPlayer.password = world.mud_generateHash(body.username.toLowerCase() + body.password);
  110. var playerName = JSON.stringify(body.username).replace( /[_\W]/g , '');
  111. playerName = playerName.substring(0,1).toUpperCase() + playerName.substring(1);
  112. newPlayer.name = playerName;
  113. world.mud_playerSave(newPlayer);
  114. world.mud_destroyMobile(newPlayer.id);
  115. response.writeHead(200, {'Content-Type': 'application/json'});
  116. response.write(JSON.stringify({"status": "ok"}, null, '\t'));
  117. response.end();
  118. }
  119. isValidUsername(config, username) {
  120. var cleanName = JSON.stringify(username).replace( /[_\W]/g , '');
  121. if(config.usernameBlacklist.indexOf(cleanName) != -1) {
  122. return false;
  123. }
  124. var playerFilename = config.playerDataPath+ "/"+cleanName+".json";
  125. if (fs.existsSync(playerFilename)) {
  126. return false;
  127. }
  128. return cleanName == username;
  129. }
  130. help(request, response) {
  131. var helpData = {"description": "This is the API for accessing or writing data to the Starmire MUD.",
  132. "commands" : [
  133. {"path": "/api/current", "method": "get", "description": "Returns the current players"},
  134. {"path": "/api/register", "method": "post", "fields": "username, password", "description": "Will create a new character with the username and password specified if valid."},
  135. ]};
  136. response.writeHead(200, {'Content-Type': 'application/json'});
  137. response.write(JSON.stringify(helpData, null, '\t'));
  138. response.end();
  139. }
  140. };