http-up
Version:
Simple share folder via http with upload
344 lines (260 loc) • 12.5 kB
JavaScript
import os from 'os';
import fs from 'fs';
import path from 'node:path';
import chalk from 'chalk';
import * as urlencode from 'urlencode';
import * as dateTime from 'node-datetime';
import mime from 'mime';
import shell from 'shelljs';
import { exec } from 'child_process';
import multer from 'multer';
import config from '../lib/config.js';
import * as util from '../lib/util.js';
import * as model from '../model/index.js';
export const api_edit = (app, argv) => {
app.get('/__doc/*splat', async (req, res) => {
let req_path = req.path;
req_path = urlencode.decode(req_path);
req_path = req_path.replace(/^\/__doc/, '');
req_path = util.http_path_clear(req_path);
let readFolder = argv.fold;
let full_filename_orig = path.join(readFolder, req_path);
let name = util.get_name(req_path);
let ext = util.get_ext_norm(req_path);
let is_doc_editable = ext.match(/^(html|rtf|doc|docx|odt)$/i);
if (!is_doc_editable) {
res.status(500).send(util.error_page_content('500', 'Editor support only for text format and office files'));
return;
}
if (ext == 'pdf') {
res.status(500).send(util.error_page_content('500', 'PDF Edit temporary disabled'));
return;
}
if (ext == 'txt') {
res.status(500).send(util.error_page_content('500', 'TXT Edit temporary disabled'));
return;
}
if (!fs.existsSync(full_filename_orig)) {
model.event_log.write(res, req, 404, 'edit', full_filename_orig);
res.status(404).send(util.error_page_content('404', '404 Not found'));
return;
}
let is_txt_editable = ext.match(/^(html)$/i);
if (is_txt_editable) {
try {
fs.copyFileSync(full_filename_orig, path.join(config.httpup_temp, name + '.' + 'html'));
let file_data = fs.readFileSync(path.join(config.httpup_temp, name + '.' + 'html'));
res.render('edit_doc', {
file_name: name + '.' + ext,
full_path: req_path,
file_data: file_data,
});
model.event_log.write(res, req, 200, 'api/edit', 'Open file ' + full_filename_orig + ' for edit');
return;
} catch (e) {
model.event_log.write(res, req, 500, 'edit', 'copyFileSync error: ', e.toString());
res.status(500).json({ code: 500 });
return;
}
}
if (shell.exec('libreoffice --help', { silent: true }).code !== 0) {
model.event_log.write(res, req, 500, 'edit', 'Error: libreoffice not found');
res.status(500).send(util.error_page_content('500', 'libreoffice not found'));
return;
}
exec(
`libreoffice --headless --norestore --nologo --convert-to html:HTML --outdir "${config.httpup_temp}" "${full_filename_orig}"`,
function (error, stdout, stderr) {
if (fs.existsSync(path.join(config.httpup_temp, name + '.html'))) {
let file_data = fs.readFileSync(path.join(config.httpup_temp, name + '.html'));
res.render('edit_doc', {
file_name: name + '.' + ext,
full_path: req_path,
file_data: file_data,
});
model.event_log.write(res, req, 200, 'api/edit', 'Open file ' + full_filename_orig + ' for edit');
}
},
);
});
app.get('/__code/*splat', async (req, res) => {
let req_path = req.path;
req_path = urlencode.decode(req_path);
req_path = req_path.replace(/^\/__code/, '');
req_path = util.http_path_clear(req_path);
let readFolder = argv.fold;
let full_filename_orig = path.join(readFolder, req_path);
let name = util.get_name(req_path);
let ext = util.get_ext_norm(req_path);
let is_doc_editable = ext.match(/^(html|txt|js|css|md|sh|json)$/i);
if (!is_doc_editable) {
res.status(500).send(util.error_page_content('500', 'Editor support only for text format files'));
return;
}
if (!fs.existsSync(full_filename_orig)) {
model.event_log.write(res, req, 404, 'edit', full_filename_orig);
res.status(404).send(util.error_page_content('404', '404 Not found'));
return;
}
try {
fs.copyFileSync(full_filename_orig, path.join(config.httpup_temp, name + '.' + ext));
let file_data = fs.readFileSync(path.join(config.httpup_temp, name + '.' + ext));
res.render('edit_code', {
file_name: name + '.' + ext,
full_path: req_path,
file_data: file_data,
});
model.event_log.write(res, req, 200, 'api/edit', 'Open file ' + full_filename_orig + ' for edit');
return;
} catch (e) {
model.event_log.write(res, req, 500, 'edit', 'copyFileSync error: ', e.toString());
res.status(500).json({ code: 500 });
return;
}
});
app.get('/__md/*splat', async (req, res) => {
let req_path = req.path;
req_path = urlencode.decode(req_path);
req_path = req_path.replace(/^\/__md/, '');
req_path = util.http_path_clear(req_path);
let readFolder = argv.fold;
let full_filename_orig = path.join(readFolder, req_path);
let name = util.get_name(req_path);
let ext = util.get_ext_norm(req_path);
let is_md_editable = ext.match(/^(md)$/i);
if (!is_md_editable) {
res.status(500).send(util.error_page_content('500', 'Editor support only for markdown format files'));
return;
}
if (!fs.existsSync(full_filename_orig)) {
model.event_log.write(res, req, 404, 'edit', full_filename_orig);
res.status(404).send(util.error_page_content('404', '404 Not found'));
return;
}
try {
fs.copyFileSync(full_filename_orig, path.join(config.httpup_temp, name + '.' + ext));
let file_data = fs.readFileSync(path.join(config.httpup_temp, name + '.' + ext));
res.render('edit_md', {
file_name: name + '.' + ext,
full_path: req_path,
file_data: file_data,
});
model.event_log.write(res, req, 200, 'api/edit', 'Open file ' + full_filename_orig + ' for edit');
return;
} catch (e) {
model.event_log.write(res, req, 500, 'edit', 'copyFileSync error: ', e.toString());
res.status(500).json({ code: 500 });
return;
}
});
//const multer = require('multer');
const upload = multer({ dest: config.httpup_temp, limits: { fieldSize: config.fieldSize_max } });
const postProcessing = upload.fields([
{ name: 'full_path', maxCount: 1 },
{ name: 'body', maxCount: 1 },
]);
app.post('/api/file/edit', postProcessing, async (req, res) => {
console.log('—'.repeat(process.stdout.columns));
let full_path = req.body.full_path;
let body = req.body.body;
let save_as_source = req.body.save_as_source;
if (full_path) {
//model.file().del( path.join(argv.fold, full_path) );
let name = util.get_name(full_path);
let target_ext = util.get_ext_norm(full_path);
if (save_as_source) {
let full_filename_temp = path.join(config.httpup_temp, name + '.' + target_ext);
try {
fs.writeFileSync(full_filename_temp, body);
model.event_log.write(res, req, 200, 'api/edit', 'File ' + full_filename_temp + ' updated.');
} catch (e) {
model.event_log.write(res, req, 500, 'api/edit', 'writeFileSync error: ', e.toString());
res.status(500).json({ code: 500 });
return;
}
let to = path.join(argv.fold, full_path);
try {
fs.renameSync(full_filename_temp, to);
model.event_log.write(res, req, 200, 'api/edit', 'fs.renameSync3', full_filename_temp, '=>', to);
//model.file.del(to);
res.status(200).json({ code: 200 });
return;
} catch (e) {
model.event_log.write(res, req, 500, 'api/edit', 'fs.renameSync3', 'err=', e);
res.status(500).json({ code: 500 });
return;
}
}
let full_filename_temp = path.join(config.httpup_temp, name + '.html');
try {
fs.writeFileSync(full_filename_temp, body);
model.event_log.write(res, req, 200, 'api/edit', 'File ' + full_filename_temp + ' updated.');
} catch (e) {
model.event_log.write(res, req, 500, 'api/edit', 'writeFileSync error: ', e.toString());
res.status(500).json({ code: 500 });
return;
}
let is_txt_editable = target_ext.match(/^(html)$/i);
if (is_txt_editable) {
//let from = path.join(config.httpup_temp, name + '.' + 'html');
let to = path.join(argv.fold, full_path);
try {
fs.renameSync(full_filename_temp, to);
model.event_log.write(res, req, 200, 'api/edit', 'fs.renameSync2', full_filename_temp, '=>', to);
//model.file.del(to);
res.status(200).json({ code: 200 });
return;
} catch (e) {
model.event_log.write(res, req, 500, 'api/edit', 'fs.renameSync2', 'err=', e);
res.status(500).json({ code: 500 });
return;
}
}
let convert_format = '';
// https://help.libreoffice.org/latest/en-US/text/shared/guide/convertfilters.html
// (txt|pdf|rtf|doc|docx|odt)
//
// --convert-to "txt:Text (encoded):UTF8" *.doc
// "Rich Text Format"
switch (target_ext) {
case 'doc':
convert_format = 'doc:MS Word 97';
break;
case 'docx':
convert_format = 'docx:MS Word 2007 XML';
break;
case 'odt':
convert_format = 'odt:writer8';
break;
case 'rtf':
convert_format = 'rtf:Rich Text Format';
break;
case 'pdf':
convert_format = 'pdf:writer_pdf_Export';
break;
}
//console.log(`libreoffice --headless --norestore --nologo --convert-to "${convert_format}" --outdir "${config.httpup_temp}" "${full_filename_temp}"`);
exec(
`libreoffice --headless --norestore --nologo --convert-to "${convert_format}" --outdir "${config.httpup_temp}" "${full_filename_temp}"`,
function (error, stdout, stderr) {
if (fs.existsSync(path.join(config.httpup_temp, name + '.' + target_ext))) {
let from = path.join(config.httpup_temp, name + '.' + target_ext);
let to = path.join(argv.fold, full_path);
try {
fs.renameSync(from, to);
model.event_log.write(res, req, 200, 'api/edit', 'fs.renameSync', from, '=>', to);
model.file.del(res, to);
res.status(200).json({ code: 200 });
return;
} catch (e) {
model.event_log.write(res, req, 500, 'api/edit', 'fs.renameSync', 'err=', e);
res.status(500).json({ code: 500 });
return;
}
}
},
);
}
//res.status(500).json({ code: 500 });
});
};