C++
Let's make it find the entrypoint and endpoint automatically.
1) Create data.txt with these symbols at the beginning and at the end
<?? hello world ??>
2) Generate resources.res
3) Generate main.exe.
Server
1) Start
mkdir nodecpp
cd nodecpp
npm init -y
npm i express express-fileupload
npm i cors fs path buffer-indexof
2) path_join.js
const path = require('path')
const path_join = function( file, folder ){
if( folder ) return path.join(__dirname, `/${folder}/${ file }`)
return path.join(__dirname, `/${ file }`)
}
module.exports = path_join;
3) server.js
var cors = require('cors')
const path = require('path')
const express = require('express')
const fileUpload = require('express-fileupload')
const app = express()
const port = 8000
var corsOptions = {
origin: '*',
optionsSuccessStatus: 200
}
app.use(fileUpload())
app.use(express.static(__dirname + '/www'));
var router_home = require("./routes/home")
var router_uploads = require("./routes/uploads")
var router_downloads = require("./routes/downloads")
app.use("/", router_home)
app.use("/uploads", router_uploads)
app.use("/downloads", router_downloads)
app.listen(port, () => {
console.log(`Server listening on port ${port}`)
})
Routes
4) Generate routes folder
mkdir routes
5) routes/home.js
const express = require("express")
const router = express.Router()
const controller_home = require("../controllers/home")
router.get("/", controller_home.index);
module.exports = router;
6) routes/uploads.js
const express = require("express")
const router = express.Router()
const controller_uploads = require("../controllers/uploads")
router.post("/", controller_uploads.uploadFile, controller_uploads.upload_txt, controller_uploads.upload_exe)
module.exports = router
7) routes/downloads.js
const express = require("express")
const router = express.Router()
const controller_downloads = require("../controllers/downloads")
router.get("/", controller_downloads.getInfo);
router.get("/:filename", controller_downloads.getFile);
module.exports = router;
Controllers
Generate controllers folder
mkdir controllers
8) controllers/home.js
const path_join = require('../path_join')
exports.index = async function (req, res, next) {
res.sendFile( path_join( "www/index.html" ) )
}
9) controllers/uploads.js
var service_uploads = require('../services/uploads')
var service_compiler = require('../services/compiler')
exports.uploadFile = async function ( req, res, next ){
if( req.files && Object.keys(req.files).length !== 0 ){
const uploadedFile = req.files.uploadFile
const filename = uploadedFile.name
if( !uploadedFile.name.includes(".exe") && !uploadedFile.name.includes(".txt") ){
return res.status(500).json({ error: 'Only EXE or TXT file are accepted' })
}
next()
}else{
res.status(400).json({ error: 'No file name' })
}
}
exports.upload_txt = async function ( req, res, next ){
const uploadedFile = req.files.uploadFile
const filename = uploadedFile.name
if( uploadedFile.name.includes(".exe") ){
next()
}else{
try{
service_uploads.uploadFile(uploadedFile, uploadedFile.name, function( err ){
if( err ){
console.log(err);
res.status(404).json({ error: 'No such file or directory' })
}else{
res.status(200).json({ ok: 'TXT received!' })
}
})
}catch( err ){
console.log( err )
res.status(500).json({ error: 'Server upload file error' })
}
}
}
exports.upload_exe = async function ( req, res, next ){
const uploadedFile = req.files.uploadFile
const filename = uploadedFile.name
const new_filename = "new_"+filename
try{
service_uploads.uploadFile(uploadedFile, uploadedFile.name, function( err ){
if( err ){
console.log(err);
res.status(404).json({ error: 'No such file or directory' })
}else{
var result = service_compiler.compile( filename, new_filename )
if( result == "ok" ){
res.redirect(`downloads?filename=${new_filename}`)
//res.redirect(`downloads/${new_filename}`)
}else{
res.status(404).json({ error: result })
}
}
})
}catch( err ){
console.log( err )
res.status(500).json({ error: 'Server upload file error' })
}
}
10) controllers/downloads.js
var service_downloads = require('../services/downloads')
exports.getInfo = async function ( req, res, next ){
if( req.query.filename ){
try{
var download_info = service_downloads.getInfo( req )
res.json( download_info )
}catch( err ){
console.log( err )
res.status(500).json({ error: 'Server info file error' })
}
}else{
res.status(400).send("No file name")
}
}
exports.getFile = async function ( req, res, next ){
if( req.params.filename ){
try{
service_downloads.getFile( req.params.filename, res, function( err ){
if( err ){
console.log(err);
res.status(404).json({ error: 'No such file or directory' })
}
})
}catch( err ){
console.log( err )
res.status(500).json({ error: 'Server download file error' })
}
}else{
res.status(400).json({ error: 'No file name' })
}
}
Services
Generate services folder
mkdir services
11) services/uploads.js
const path_join = require('../path_join')
exports.uploadFile = function( uploadedFile, filename, callback ) {
var uploadPath = path_join(filename, "uploads")
uploadedFile.mv(uploadPath, async function (err) {
if( err ){
console.log(err);
callback("Error uploading file");
}else{
callback(null); // No error
}
})
}
12) services/downloads.js
const path_join = require('../path_join')
exports.getInfo = function( req ){
var folder = "downloads";
var host = req.get('host')
var protocol = req.protocol
var filename = req.query.filename
var download_link = `${protocol}://${host}/${folder}/${filename}`;
return {
filename: filename,
download_link: download_link
}
}
exports.getFile = function( filename, res, callback ) {
var file_path = path_join( filename, "uploads" )
res.download( file_path, function( err ) {
if( err ){
console.log(err);
callback("Error download file");
}else{
callback(null); // No error
}
})
}
13) services/compiler.js
var path_join = require('../path_join')
var slicer = require('./compiler/slicer')
const getIndex = require('./compiler/getIndex');
var merge3binary = require('./compiler/merge3binary')
var replaceBinaryText = require('./compiler/replaceBinaryText')
exports.compile = function( filename, new_filename ){
var folder = "uploads"
var input_path = path_join( filename, folder )
var output_path = path_join( new_filename, folder )
var header_path = path_join( "main_header.exe", folder )
var middle_path = path_join( "main_middle.exe", folder )
var footer_path = path_join( "main_footer.exe", folder )
var data_path = path_join( "data.txt", folder )
var new_path = path_join( "main_middle_updated.exe", folder )
var indexes = getIndex( input_path )
if( indexes.error ){
return indexes.error
}
var adress_start = indexes[0]
var adress_end = indexes[1]
// -------- Generate 3 slices
slicer( input_path, header_path, "0x00000", adress_start)
slicer( input_path, middle_path, adress_start, adress_end)
slicer( input_path, footer_path, adress_end, "end")
// -------- Update resources region
replaceBinaryText( data_path, middle_path, new_path )
// Merge 3 binary
merge3binary(header_path, new_path, footer_path, output_path)
return "ok"
}
Compiler
Generate compiler folder inside services
mkdir compiler
14) compiler/getIndex.js
const fs = require('fs');
const BufferIndexOf = require('buffer-indexof');
const getIndex = function( exe_path ){
const input_data = fs.readFileSync( exe_path )
const buffer = Buffer.from( input_data )
const startString = Buffer.from('<??', 'utf-8')
const endString = Buffer.from('??>', 'utf-8')
const start = BufferIndexOf(buffer, startString)
const endSize = BufferIndexOf(buffer, endString, start + startString.length)
const end = endSize + endString.length
const entryPoint = start.toString(16)
const endPoint = end.toString(16)
if (start === -1 || end === -1) {
return { error: "<?? and ??> not found" }
console.log("<?? and ??> not found")
} else {
console.log("Start:"+entryPoint)
console.log("End:"+endPoint)
return [entryPoint, endPoint]
}
}
module.exports = getIndex;
15) compiler/slicer.js
const fs = require('fs')
const slicer = function( exe_path, result_path, entry_start, entry_end ){
var file_data;
// Set positions
const file_start = parseInt( entry_start, 16 );
const file_end = parseInt( entry_end, 16 );
// Get exe
const input_data = fs.readFileSync( exe_path );
// Slice
if( entry_end == "end" ){
file_data = input_data.slice( file_start )
}else{
file_data = input_data.slice( file_start, file_end )
}
// Write
fs.writeFileSync( result_path, file_data );
console.log('Binary file sucessfull created!');
}
module.exports = slicer;
16) compiler/replaceBinaryText.js
const fs = require('fs')
const replaceBinaryText = function( data_path, input_path, output_path ){
// Get bin
const exe = fs.readFileSync( input_path );
const min_size = exe.length;
// Get text
const input_data = fs.readFileSync( data_path );
const data_size = input_data.length;
if( data_size > min_size ){
console.log(`File Error. Maximum size is ${min_size}`);
}else{
// Fill
const padding_buffer = Buffer.alloc(min_size - data_size, 0x00);
// Concat
const output_buffer = Buffer.concat([input_data, padding_buffer]);
// Write
fs.writeFileSync(output_path, output_buffer, 'binary');
console.log('Binary file sucessfull created!');
}
}
module.exports = replaceBinaryText;
17) compiler/merge3binary.js
const fs = require('fs')
const merge3binary = function( header, middle, footer, output_path ){
const header_data = fs.readFileSync( header );
const middle_data = fs.readFileSync( middle );
const footer_data = fs.readFileSync( footer );
const merged_buffer = Buffer.concat([header_data, middle_data, footer_data]);
fs.writeFileSync(output_path, merged_buffer, 'binary');
console.log('Binary file sucessfull created!');
}
module.exports = merge3binary;
Compiler
Generate folders: uploads and www
mkdir uploads
mkdir www
18) www/index.html
<!DOCTYPE html>
<html lang='en'>
<head>
<meta name='viewport' content='width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no'>
<meta charset='utf-8'>
<title>Fake Compiler C++</title>
<link rel='stylesheet' src='style.css'>
</head>
<body>
<div id='root'>
<h1>Fake Compiler C++</h1>
<form id="txt" method="post" enctype="multipart/form-data" action="/uploads">
<input type="hidden" name="msgtype" value="2"/>
<input type="file" name="uploadFile" accept=".txt"/>
<button type="submit" value="Upload" >Browse File</button>
</form>
</div>
<script type='javascript' src='main.js'></script>
</body>
</html>
19) Run
node server.js
# Download fileInfo
http://localhost:8000/downloads?filename=new_main.exe
# Download file
http://localhost:8000/downloads/new_main.exe
# Post file
var post_txt = async() => {
const formData = new FormData(txt);
try {
const response = await fetch('/uploads', {
method: 'POST',
body: formData
});
const data = await response.json();
console.log(data);
} catch (error) {
console.error(error);
}
}
20) Demo
Fake C++ Compiler with Node.js - Frontend - Part 3
https://dev.to/gurigraphics/fake-c-compiler-with-nodejs-frontend-part-3-1m18
Top comments (0)