mirror of
https://github.com/ONLYOFFICE/document-server-integration.git
synced 2026-02-10 18:05:10 +08:00
486 lines
17 KiB
JavaScript
486 lines
17 KiB
JavaScript
/*
|
|
*
|
|
* (c) Copyright Ascensio System Limited 2010-2016
|
|
*
|
|
* This program is freeware. You can redistribute it and/or modify it under the terms of the GNU
|
|
* General Public License (GPL) version 3 as published by the Free Software Foundation (https://www.gnu.org/copyleft/gpl.html).
|
|
* In accordance with Section 7(a) of the GNU GPL its Section 15 shall be amended to the effect that
|
|
* Ascensio System SIA expressly excludes the warranty of non-infringement of any third-party rights.
|
|
*
|
|
* THIS PROGRAM IS DISTRIBUTED WITHOUT ANY WARRANTY; WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR
|
|
* FITNESS FOR A PARTICULAR PURPOSE. For more details, see GNU GPL at https://www.gnu.org/copyleft/gpl.html
|
|
*
|
|
* You can contact Ascensio System SIA by email at sales@onlyoffice.com
|
|
*
|
|
* The interactive user interfaces in modified source and object code versions of ONLYOFFICE must display
|
|
* Appropriate Legal Notices, as required under Section 5 of the GNU GPL version 3.
|
|
*
|
|
* Pursuant to Section 7 § 3(b) of the GNU GPL you must retain the original ONLYOFFICE logo which contains
|
|
* relevant author attributions when distributing the software. If the display of the logo in its graphic
|
|
* form is not reasonably feasible for technical reasons, you must include the words "Powered by ONLYOFFICE"
|
|
* in every copy of the program you distribute.
|
|
* Pursuant to Section 7 § 3(e) we decline to grant you any rights under trademark law for use of our trademarks.
|
|
*
|
|
*/
|
|
|
|
var express = require("express");
|
|
var path = require("path");
|
|
var favicon = require("serve-favicon");
|
|
var bodyParser = require("body-parser");
|
|
var fileSystem = require("fs");
|
|
var formidable = require("formidable");
|
|
var syncRequest = require("sync-request");
|
|
var configServer = require('config').get('server');
|
|
var docManager = require("./helpers/docManager");
|
|
var documentService = require("./helpers/documentService");
|
|
var fileUtility = require("./helpers/fileUtility");
|
|
var siteUrl = configServer.get('siteUrl');
|
|
|
|
|
|
process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";
|
|
|
|
|
|
String.prototype.hashCode = function () {
|
|
for (var ret = 0, i = 0, len = this.length; i < len; i++) {
|
|
ret = (31 * ret + this.charCodeAt(i)) << 0;
|
|
}
|
|
return ret;
|
|
};
|
|
String.prototype.format = function () {
|
|
var text = this.toString();
|
|
|
|
if (!arguments.length) return text;
|
|
|
|
for (var i = 0; i < arguments.length; i++) {
|
|
text = text.replace(new RegExp("\\{" + i + "\\}", "gi"), arguments[i]);
|
|
}
|
|
|
|
return text;
|
|
};
|
|
|
|
|
|
var app = express();
|
|
|
|
|
|
app.set("views", path.join(__dirname, "views"));
|
|
app.set("view engine", "ejs")
|
|
|
|
|
|
app.use(function (req, res, next) {
|
|
res.setHeader('Access-Control-Allow-Origin', '*');
|
|
next();
|
|
});
|
|
|
|
app.use(express.static(path.join(__dirname, "public")));
|
|
app.use(favicon(__dirname + "/public/images/favicon.ico"));
|
|
|
|
|
|
app.use(bodyParser.json());
|
|
app.use(bodyParser.urlencoded({ extended: false }));
|
|
|
|
|
|
app.get("/", function (req, res) {
|
|
try {
|
|
|
|
docManager.init(__dirname, req, res);
|
|
|
|
res.render("index", {
|
|
preloaderUrl: siteUrl + configServer.get('preloaderUrl'),
|
|
convertExts: configServer.get('convertedDocs').join(","),
|
|
editedExts: configServer.get('editedDocs').join(","),
|
|
storedFiles: docManager.getStoredFiles(),
|
|
params: docManager.getCustomParams()
|
|
});
|
|
|
|
}
|
|
catch (ex) {
|
|
res.status(500);
|
|
res.render("error", { message: ex.message, error: ex });
|
|
return;
|
|
}
|
|
});
|
|
|
|
app.post("/upload", function (req, res) {
|
|
|
|
docManager.init(__dirname, req, res);
|
|
docManager.storagePath(""); //mkdir if not exist
|
|
|
|
var userIp = docManager.curUserHostAddress();
|
|
var uploadDir = "./public/" + configServer.get('storageFolder') + "/" + userIp;
|
|
|
|
var form = new formidable.IncomingForm();
|
|
form.uploadDir = uploadDir;
|
|
form.keepExtensions = true;
|
|
|
|
form.parse(req, function (err, fields, files) {
|
|
|
|
var file = files.uploadedFile;
|
|
|
|
file.name = docManager.getCorrectName(file.name);
|
|
|
|
if (configServer.get('maxFileSize') < file.size || file.size <= 0) {
|
|
fileSystem.unlinkSync(file.path);
|
|
res.writeHead(200, { "Content-Type": "text/plain" });
|
|
res.write("{ \"error\": \"File size is incorrect\"}");
|
|
res.end();
|
|
return;
|
|
}
|
|
|
|
var exts = [].concat(configServer.get('viewedDocs'), configServer.get('editedDocs'), configServer.get('convertedDocs'));
|
|
var curExt = fileUtility.getFileExtension(file.name);
|
|
|
|
if (exts.indexOf(curExt) == -1) {
|
|
fileSystem.unlinkSync(file.path);
|
|
res.writeHead(200, { "Content-Type": "text/plain" });
|
|
res.write("{ \"error\": \"File type is not supported\"}");
|
|
res.end();
|
|
return;
|
|
}
|
|
|
|
fileSystem.rename(file.path, uploadDir + "/" + file.name, function (err) {
|
|
res.writeHead(200, { "Content-Type": "text/plain" });
|
|
if (err) {
|
|
res.write("{ \"error\": \"" + err + "\"}");
|
|
} else {
|
|
res.write("{ \"filename\": \"" + file.name + "\"}");
|
|
|
|
var userid = req.query.userid ? req.query.userid : "uid-1";
|
|
var firstname = req.query.firstname ? req.query.firstname : "Jonn";
|
|
var lastname = req.query.lastname ? req.query.lastname : "Smith";
|
|
|
|
docManager.saveFileData(file.name, userid, firstname + " " + lastname);
|
|
docManager.getFileData(file.name, docManager.curUserHostAddress());
|
|
}
|
|
res.end();
|
|
});
|
|
});
|
|
});
|
|
|
|
app.get("/convert", function (req, res) {
|
|
|
|
var fileName = req.query.filename;
|
|
var fileUri = docManager.getFileUri(fileName);
|
|
var fileExt = fileUtility.getFileExtension(fileName);
|
|
var fileType = fileUtility.getFileType(fileName);
|
|
var internalFileExt = docManager.getInternalExtension(fileType);
|
|
var response = res;
|
|
|
|
var writeResult = function (filename, step, error) {
|
|
var result = {};
|
|
|
|
if (filename != null)
|
|
result["filename"] = filename;
|
|
|
|
if (step != null)
|
|
result["step"] = step;
|
|
|
|
if (error != null)
|
|
result["error"] = error;
|
|
|
|
response.write(JSON.stringify(result));
|
|
response.end();
|
|
}
|
|
|
|
var callback = function (err, data) {
|
|
if (err) {
|
|
if (err.name === "ConnectionTimeoutError") {
|
|
writeResult(fileName, 0, null);
|
|
return;
|
|
} else {
|
|
throw { message: err };
|
|
}
|
|
}
|
|
|
|
try {
|
|
var responseUri = documentService.getResponseUri(data.toString())
|
|
var result = responseUri.key;
|
|
var newFileUri = responseUri.value;
|
|
|
|
if (result != 100) {
|
|
writeResult(fileName, result, null)
|
|
return;
|
|
}
|
|
|
|
var correctName = docManager.getCorrectName(fileUtility.getFileName(fileName, true) + internalFileExt);
|
|
|
|
var file = syncRequest("GET", newFileUri);
|
|
fileSystem.writeFileSync(docManager.storagePath(correctName), file.getBody());
|
|
|
|
fileSystem.unlinkSync(docManager.storagePath(fileName));
|
|
|
|
writeResult(correctName, null, null)
|
|
} catch (ex) {
|
|
writeResult(null, null, ex.message)
|
|
}
|
|
}
|
|
|
|
try {
|
|
if (configServer.get('convertedDocs').indexOf(fileExt) != -1) {
|
|
var key = documentService.generateRevisionId(fileUri);
|
|
var res = documentService.getConvertedUriAsync(fileUri, fileExt, internalFileExt, key, callback);
|
|
} else {
|
|
writeResult(fileName, null, null)
|
|
}
|
|
} catch (ex) {
|
|
writeResult(null, null, ex.message)
|
|
}
|
|
|
|
});
|
|
|
|
app.delete("/file", function (req, res) {
|
|
try {
|
|
docManager.init(__dirname, req, res);
|
|
|
|
var fileName = req.query.filename;
|
|
|
|
var filePath = docManager.storagePath(fileName)
|
|
fileSystem.unlinkSync(filePath);
|
|
|
|
var userAddress = docManager.curUserHostAddress();
|
|
var historyPath = docManager.historyPath(fileName, userAddress, true);
|
|
|
|
var deleteFolderRecursive = function (path) {
|
|
if (fileSystem.existsSync(path)) {
|
|
var files = fileSystem.readdirSync(path);
|
|
files.forEach(function (file, index) {
|
|
var curPath = path + "/" + file;
|
|
if (fileSystem.lstatSync(curPath).isDirectory()) {
|
|
deleteFolderRecursive(curPath);
|
|
} else {
|
|
fileSystem.unlinkSync(curPath);
|
|
}
|
|
});
|
|
fileSystem.rmdirSync(path);
|
|
}
|
|
};
|
|
deleteFolderRecursive(historyPath);
|
|
|
|
res.write("{\"success\":true}");
|
|
} catch (ex) {
|
|
res.write(JSON.stringify(ex));
|
|
}
|
|
res.end();
|
|
});
|
|
|
|
app.post("/track", function (req, res) {
|
|
|
|
docManager.init(__dirname, req, res);
|
|
|
|
var userAddress = req.query.useraddress;
|
|
var fileName = req.query.filename;
|
|
var version = 0;
|
|
|
|
var processTrack = function (response, body, fileName, userAddress) {
|
|
|
|
var processSave = function (body, fileName, userAddress, newVersion) {
|
|
|
|
var downloadUri = body.url;
|
|
var curExt = fileUtility.getFileExtension(fileName);
|
|
var downloadExt = fileUtility.getFileExtension(downloadUri);
|
|
|
|
if (downloadExt != curExt) {
|
|
var key = documentService.generateRevisionId(downloadUri);
|
|
|
|
try {
|
|
downloadUri = documentService.getConvertedUri(downloadUri, downloadExt, curExt, key);
|
|
} catch (ex) {
|
|
fileName = docManager.getCorrectName(fileUtility.getFileName(fileName, true) + downloadExt, userAddress)
|
|
}
|
|
}
|
|
|
|
try {
|
|
|
|
var path = docManager.storagePath(fileName, userAddress);
|
|
|
|
if (newVersion) {
|
|
var historyPath = docManager.historyPath(fileName, userAddress);
|
|
if (historyPath == "") {
|
|
historyPath = docManager.historyPath(fileName, userAddress, true);
|
|
docManager.createDirectory(historyPath);
|
|
}
|
|
|
|
var count_version = docManager.countVersion(historyPath);
|
|
version = count_version + 1;
|
|
versionPath = docManager.versionPath(fileName, userAddress, version);
|
|
docManager.createDirectory(versionPath);
|
|
|
|
var downloadZip = body.changesurl;
|
|
if (downloadZip) {
|
|
var path_changes = docManager.diffPath(fileName, userAddress, version);
|
|
var diffZip = syncRequest("GET", downloadZip);
|
|
fileSystem.writeFileSync(path_changes, diffZip.getBody());
|
|
}
|
|
|
|
var changeshistory = body.changeshistory;
|
|
if (changeshistory) {
|
|
var path_changes_json = docManager.changesPath(fileName, userAddress, version);
|
|
fileSystem.writeFileSync(path_changes_json, body.changeshistory);
|
|
}
|
|
|
|
var path_key = docManager.keyPath(fileName, userAddress, version);
|
|
fileSystem.writeFileSync(path_key, body.key);
|
|
|
|
var path_prev = docManager.prevFilePath(fileName, userAddress, version);
|
|
fileSystem.writeFileSync(path_prev, fileSystem.readFileSync(path));
|
|
}
|
|
|
|
var file = syncRequest("GET", downloadUri);
|
|
fileSystem.writeFileSync(path, file.getBody());
|
|
} catch (ex) {
|
|
}
|
|
}
|
|
|
|
if (body.status == 1) { //Editing
|
|
if (body.actions && body.actions[0].type == 0) { //finished edit
|
|
var user = body.actions[0].userid;
|
|
if (body.users.indexOf(user) == -1) {
|
|
var key = body.key;
|
|
try {
|
|
documentService.commandRequest("forcesave", key);
|
|
} catch (ex) {
|
|
}
|
|
}
|
|
}
|
|
} else if (body.status == 2 || body.status == 3) { //MustSave, Corrupted
|
|
processSave(body, fileName, userAddress, true);
|
|
} else if (body.status == 6 || body.status == 7) { //MustForceSave, CorruptedForceSave
|
|
processSave(body, fileName, userAddress);
|
|
}
|
|
|
|
response.write("{\"error\":0}");
|
|
response.end();
|
|
}
|
|
|
|
var readbody = function (request, response, fileName, userAddress) {
|
|
var content = "";
|
|
request.on('data', function (data) {
|
|
content += data;
|
|
});
|
|
request.on('end', function () {
|
|
var body = JSON.parse(content);
|
|
processTrack(response, body, fileName, userAddress);
|
|
});
|
|
}
|
|
|
|
if (req.body.hasOwnProperty("status")) {
|
|
processTrack(res, req.body, fileName, userAddress);
|
|
} else {
|
|
readbody(req, res, fileName, userAddress);
|
|
}
|
|
});
|
|
|
|
app.get("/editor", function (req, res) {
|
|
try {
|
|
|
|
docManager.init(__dirname, req, res);
|
|
|
|
var fileExt = req.query.fileExt;
|
|
var history = [];
|
|
var prevUrl = [];
|
|
var diff = [];
|
|
var lang = docManager.getLang();
|
|
var userid = req.query.userid ? req.query.userid : "uid-1";
|
|
var firstname = req.query.firstname ? req.query.firstname : "Jonn";
|
|
var lastname = req.query.lastname ? req.query.lastname : "Smith";
|
|
|
|
if (fileExt != null) {
|
|
var fileName = docManager.createDemo((req.query.create ? "new." : "sample.") + fileExt, userid, firstname + " " + lastname);
|
|
|
|
var redirectPath = docManager.getProtocol() + "://" + docManager.req.get("host") + "/editor?fileName=" + encodeURIComponent(fileName) + docManager.getCustomParams();
|
|
res.redirect(redirectPath);
|
|
return;
|
|
}
|
|
|
|
var userAddress = docManager.curUserHostAddress();
|
|
var fileName = req.query.fileName;
|
|
var key = docManager.getKey(fileName);
|
|
var url = docManager.getFileUri(fileName);
|
|
var mode = req.query.mode || "edit"; //mode: view/edit
|
|
var type = req.query.type || "desktop"; //type: embedded/mobile/desktop
|
|
var canEdit = configServer.get('editedDocs').indexOf(fileUtility.getFileExtension(fileName)) != -1;
|
|
|
|
var historyPath = docManager.historyPath(fileName, userAddress);
|
|
var countVersion = 1;
|
|
changes = null;
|
|
|
|
if (historyPath != '') {
|
|
|
|
countVersion = docManager.countVersion(historyPath) + 1;
|
|
var prev_path = docManager.getlocalFileUri(fileName, 1) + "/prev" + fileUtility.getFileExtension(fileName);
|
|
var diff_path = null;
|
|
for (var i = 1; i < countVersion; i++) {
|
|
var keyPath = docManager.keyPath(fileName, userAddress, i);
|
|
var keyVersion = "" + fileSystem.readFileSync(keyPath);
|
|
history.push(docManager.getHistory(fileName, changes, keyVersion, i));
|
|
|
|
prevUrl.push(prev_path);
|
|
prev_path = docManager.getlocalFileUri(fileName, i) + "/prev" + fileUtility.getFileExtension(fileName);
|
|
|
|
diff.push(diff_path);
|
|
diff_path = docManager.getlocalFileUri(fileName, i) + "/diff.zip";
|
|
|
|
var changesFile = docManager.changesPath(fileName, userAddress, i);
|
|
var changes = docManager.getChanges(changesFile);
|
|
}
|
|
prevUrl.push(prev_path);
|
|
diff.push(diff_path);
|
|
} else {
|
|
prevUrl.push(url)
|
|
}
|
|
history.push(docManager.getHistory(fileName, changes, key, countVersion));
|
|
|
|
var argss = {
|
|
apiUrl: siteUrl + configServer.get('apiUrl'),
|
|
file: {
|
|
name: fileName,
|
|
ext: fileUtility.getFileExtension(fileName, true),
|
|
uri: url,
|
|
version: countVersion
|
|
},
|
|
editor: {
|
|
type: type,
|
|
documentType: fileUtility.getFileType(fileName),
|
|
key: key,
|
|
callbackUrl: docManager.getCallback(fileName),
|
|
isEdit: canEdit,
|
|
mode: canEdit && mode != "view" ? "edit" : "view",
|
|
canBackToFolder: type != "embedded",
|
|
getServerUrl: docManager.getServerUrl(),
|
|
curUserHostAddress: docManager.curUserHostAddress(),
|
|
lang: lang,
|
|
userid: userid,
|
|
firstname: firstname,
|
|
lastname: lastname
|
|
},
|
|
history: history,
|
|
setHistoryData: {
|
|
url: prevUrl || "", //из файла прочитать ссылки
|
|
urlDiff: diff || ""
|
|
}
|
|
};
|
|
|
|
res.render("editor", argss);
|
|
|
|
}
|
|
catch (ex) {
|
|
res.status(500);
|
|
res.render("error", { message: ex.message, error: ex });
|
|
return;
|
|
}
|
|
});
|
|
|
|
app.use(function (req, res, next) {
|
|
var err = new Error("Not Found");
|
|
err.status = 404;
|
|
next(err);
|
|
});
|
|
|
|
app.use(function (err, req, res, next) {
|
|
res.status(err.status || 500);
|
|
res.render("error", {
|
|
message: err.message
|
|
});
|
|
});
|
|
|
|
module.exports = app;
|