You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

134 lines
4.1KB

  1. import binascii
  2. import os
  3. import exec_helpers
  4. import re
  5. import uuid
  6. import json
  7. from flask import request, url_for
  8. from flask_api import FlaskAPI, status, exceptions
  9. from flask_cors import CORS
  10. app = FlaskAPI(__name__)
  11. CORS(app)
  12. @app.route("/compile", methods=['POST'])
  13. def compile():
  14. if request.method == 'POST':
  15. note = str(request.data.get('source', ''))
  16. flags = str(request.data.get('flags', ''))
  17. uuid_ = str(request.data.get('uuid', ''))
  18. if not uuid_:
  19. uuid_ = str(uuid.uuid1())
  20. counter = 0
  21. if os.path.exists("/data/{}/counter".format(uuid_)):
  22. with open("/data/{}/counter".format(uuid_), "r") as f:
  23. counter = int(f.read().strip()) + 1
  24. f.close()
  25. else:
  26. os.mkdir("/data/{}".format(uuid_))
  27. os.mkdir("/data/{}/{}".format(uuid_, counter))
  28. with open("/data/{}/{}/environ".format(uuid_, counter), "w") as f:
  29. for env in os.environ:
  30. f.write("{}={}\n".format(env, os.environ[env]))
  31. f.close()
  32. with open("/data/{}/{}/source".format(uuid_, counter), "w") as f:
  33. f.write(note)
  34. f.close()
  35. with open("/data/{}/{}/flags".format(uuid_, counter), "w") as f:
  36. f.write(flags)
  37. f.close()
  38. with open("/data/{}/counter".format(uuid_), "w") as f:
  39. f.write(str(counter))
  40. f.close()
  41. with open("/tmp/test.cpp", "w") as f:
  42. f.write(note)
  43. f.close()
  44. stdout = ''
  45. stderr = ''
  46. retcode = 0
  47. output = ''
  48. output_wasm = ''
  49. flags = flags.replace("\n", " ")
  50. wasm = 'cheerp-mode=wasm' in flags
  51. # Simple way to disable malicious flags (hopefully)
  52. if not re.match('^[\s\ta-zA-Z0-9=\-_\.]*$', flags):
  53. flags = ""
  54. cmd = "/opt/cheerp/bin/clang {} /tmp/test.cpp -o /tmp/test.js".format(flags)
  55. if wasm:
  56. cmd = "/opt/cheerp/bin/clang {} /tmp/test.cpp -cheerp-wasm-loader=/tmp/test.js -o /tmp/test.wasm".format(flags)
  57. with exec_helpers.Subprocess() as executor:
  58. try:
  59. ret = executor.check_call(cmd, shell=True, timeout=10)
  60. if ret:
  61. retcode = ret.exit_code
  62. output = ret.stdout_str
  63. except exec_helpers.ExecHelperTimeoutError as e:
  64. #stdout = e.stdout
  65. #stderr = e.stderr
  66. stderr = str(e)
  67. except exec_helpers.CalledProcessError as e:
  68. stdout = e.stdout
  69. stderr = e.stderr
  70. if os.path.exists("/tmp/test.js"):
  71. with open("/tmp/test.js", "r") as f:
  72. output = f.read()
  73. f.close()
  74. if wasm and os.path.exists("/tmp/test.wasm"):
  75. with open("/tmp/test.wasm", "rb") as f:
  76. output_wasm = f.read()
  77. f.close()
  78. return {
  79. 'stdout': stdout,
  80. 'stderr': stderr,
  81. 'command': cmd,
  82. 'retcode': retcode,
  83. 'javascript': output,
  84. 'wasm': binascii.b2a_base64(output_wasm).decode("utf-8") if wasm else "",
  85. 'uuid': uuid_,
  86. 'version': counter,
  87. }, status.HTTP_201_CREATED
  88. @app.route("/retrieve", methods=['POST'])
  89. def retrieve():
  90. if request.method == 'POST':
  91. uuid_ = str(request.data.get('uuid', ''))
  92. version = str(request.data.get('version', ''))
  93. source = ''
  94. flags = ''
  95. if not os.path.exists("/data/{}/{}".format(uuid_, version)):
  96. return False
  97. with open("/data/{}/{}/source".format(uuid_, version), "r") as f:
  98. source = f.read()
  99. f.close()
  100. with open("/data/{}/{}/flags".format(uuid_, version), "r") as f:
  101. flags = f.read()
  102. f.close()
  103. return {
  104. 'source': source,
  105. 'flags': flags,
  106. }, status.HTTP_201_CREATED
  107. if __name__ == "__main__":
  108. app.run(host="0.0.0.0", debug=True)