Advertisement
Guest User

Untitled

a guest
May 19th, 2019
76
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.02 KB | None | 0 0
  1. const fs = require('fs');
  2. const EventEmitter = require('events');
  3. const util = require('util');
  4. const os = require('os');
  5. const path = require('path');
  6. const child_process = require('child_process');
  7.  
  8. const readFile = util.promisify(fs.readFile);
  9. const appendFile = util.promisify(fs.appendFile);
  10. const writeFile = util.promisify(fs.writeFile);
  11. const mkdir = util.promisify(fs.mkdir);
  12.  
  13. function base64Encode(str) {
  14. // first we use encodeURIComponent to get percent-encoded UTF-8,
  15. // then we convert the percent encodings into raw bytes which
  16. // can be fed into btoa.
  17. const encodedURI = encodeURIComponent(str)
  18. let result = Buffer.from(encodedURI.replace(/%([0-9A-F]{2})/g,
  19. (match, p1) => {
  20. let s = String.fromCharCode('0x' + p1);
  21. return s;
  22. }
  23. ));
  24. return result.toString('base64');
  25. }
  26.  
  27. function base64Decode(str) {
  28. // Going backwards: from bytestream, to percent-encoding, to original string.
  29. return decodeURIComponent(Buffer.from(str, 'base64').toString().split('').map(function (c) {
  30. let s = '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2);
  31. return s;
  32. }).join(''));
  33. }
  34.  
  35. async function createTempDir() {
  36. const r1 = Math.round(Math.random() * 10000);
  37. const r2 = Math.round(Math.random() * 10000);
  38. const directory = path.join(os.tmpdir(), `judge-${r1}-${r2}`);
  39.  
  40. await mkdir(directory);
  41. return directory;
  42. }
  43.  
  44. async function execProcess(command, input) {
  45. const options = { timeout: 5000, maxBuffer: 50 * 1024 * 1024 };
  46.  
  47. return new Promise((resolve, reject) => {
  48. const proc = child_process.exec(command, options, (error, stdout, stderr) => {
  49. resolve({ stdout, stderr });
  50. });
  51.  
  52. if (input) {
  53. proc.stdin.write(input, () => {
  54. proc.stdin.end();
  55. });
  56. }
  57. });
  58. }
  59.  
  60. function deleteDir(path) {
  61. setImmediate(async () => {
  62. try {
  63. await execProcess(`rmdir /Q /S ${path}`);
  64. } catch (error) {
  65. console.log(error);
  66. }
  67. })
  68. };
  69.  
  70. const runner = {
  71. cpp: async (code, input) => {
  72. const directory = await createTempDir();
  73.  
  74. const mainFile = path.join(directory, 'main.cpp');
  75. await writeFile(mainFile, code);
  76.  
  77. const exeFile = path.join(directory, 'main.exe');
  78.  
  79. let result = await execProcess(`clang "${mainFile}" --output "${exeFile}"`);
  80. if (!result.stderr || !result.stderr.length) {
  81. result = await execProcess(`"${exeFile}"`, input);
  82. }
  83.  
  84. deleteDir(directory);
  85.  
  86. return result;
  87. },
  88. javascript: async (code, input) => {
  89. const directory = await createTempDir();
  90.  
  91. const mainFile = path.join(directory, 'main.js');
  92. await writeFile(mainFile, code);
  93.  
  94. const result = await execProcess(`node "${mainFile}"`, input);
  95.  
  96. deleteDir(directory);
  97.  
  98. return result;
  99. }
  100. };
  101.  
  102. const propertyGetterSetter = {
  103. getHostProps: async () => {
  104. let data = await execProcess('VBoxControl guestproperty enumerate --patterns /Host/*');
  105.  
  106. data = data ? data.stdout : data;
  107.  
  108. let props = [];
  109.  
  110. if (data && data.length) {
  111. lines = data.split('\r\n').splice(3).filter(line => line.trim().length);
  112.  
  113. props = lines.map(line => {
  114. const pairs = line.split(', ');
  115.  
  116. const rawName = pairs[0].split(': ')[1];
  117. const name = rawName.substr(rawName.lastIndexOf('/') + 1);
  118. const value = base64Decode(pairs[1].split(': ')[1]);
  119.  
  120. return { name, value };
  121. });
  122. }
  123.  
  124. return props;
  125. },
  126. deleteHostProp: async (name) => {
  127. await execProcess(`VBoxControl guestproperty delete "/Host/${name}"`);
  128. },
  129. setGuestProp: async (name, value) => {
  130. await execProcess(`VBoxControl guestproperty set "/Guest/${name}" "${base64Encode(JSON.stringify(value))}"`);
  131. }
  132. };
  133.  
  134. const eventEmitter = new EventEmitter();
  135. eventEmitter.on('solution', async (name, value) => {
  136. try {
  137. const { language, input, code } = value;
  138. if (!language || !input || !code) {
  139. throw new Error(`malformed [language=${language}] [input=${input}] [code=${code}]`);
  140. }
  141.  
  142. if (!runner[language]) {
  143. throw new Error('language not found');
  144. }
  145.  
  146. const result = await runner[language](code, input);
  147. await propertyGetterSetter.setGuestProp(name, result);
  148.  
  149. } catch (error) {
  150. await propertyGetterSetter.setGuestProp(name, 'error');
  151. console.log(error);
  152. } finally {
  153. await propertyGetterSetter.deleteHostProp(name, '');
  154. }
  155.  
  156. });
  157.  
  158. setInterval(async () => {
  159. try {
  160. let props = await propertyGetterSetter.getHostProps();
  161. props.forEach((prop) => eventEmitter.emit('solution', prop.name, JSON.parse(prop.value)));
  162. } catch (error) {
  163. console.log(error);
  164. }
  165. }, 1000);
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement