Compare commits
18 Commits
v99.99.99.
...
feature/py
| Author | SHA1 | Date | |
|---|---|---|---|
| c9baa474be | |||
| 48185674d4 | |||
| dbca11e85c | |||
| d21a732859 | |||
| b96a6fac53 | |||
| b01af348a7 | |||
| c2443d3106 | |||
| 5fa3f4c57f | |||
| efd7e1b6e7 | |||
| 259ee63eea | |||
| 453b9835b7 | |||
| 89e6544b79 | |||
| c06f2a5a29 | |||
| 8aed04753c | |||
| 15ed02e556 | |||
| fb66dc8423 | |||
| 541ace8132 | |||
| 8b5cebeb3f |
2
.github/workflows/lint-php.yml
vendored
@ -26,4 +26,4 @@ jobs:
|
||||
tools: cs2pr, phpcs
|
||||
|
||||
- name: Lint
|
||||
run: phpcs src index.php
|
||||
run: phpcs .
|
||||
28
.gitmodules
vendored
@ -1,3 +1,7 @@
|
||||
[submodule "web/documentserver-example/java/src/main/resources/assets"]
|
||||
path = web/documentserver-example/java/src/main/resources/assets
|
||||
url = https://github.com/ONLYOFFICE/document-templates
|
||||
branch = main/en
|
||||
[submodule "web/documentserver-example/csharp-mvc/assets"]
|
||||
path = web/documentserver-example/csharp-mvc/assets
|
||||
url = https://github.com/ONLYOFFICE/document-templates
|
||||
@ -6,6 +10,14 @@
|
||||
path = web/documentserver-example/csharp/assets
|
||||
url = https://github.com/ONLYOFFICE/document-templates
|
||||
branch = main/en
|
||||
[submodule "web/documentserver-example/ruby/public/assets"]
|
||||
path = web/documentserver-example/ruby/public/assets
|
||||
url = https://github.com/ONLYOFFICE/document-templates
|
||||
branch = main/en
|
||||
[submodule "web/documentserver-example/java-spring/src/main/resources/assets"]
|
||||
path = web/documentserver-example/java-spring/src/main/resources/assets
|
||||
url = https://github.com/ONLYOFFICE/document-templates
|
||||
branch = main/en
|
||||
[submodule "web/documentserver-example/nodejs/public/assets/document-templates"]
|
||||
path = web/documentserver-example/nodejs/public/assets/document-templates
|
||||
url = https://github.com/ONLYOFFICE/document-templates
|
||||
@ -26,23 +38,7 @@
|
||||
path = web/documentserver-example/python/assets/document-templates
|
||||
url = https://github.com/ONLYOFFICE/document-templates
|
||||
branch = main/en
|
||||
[submodule "web/documentserver-example/java/src/main/resources/assets/document-templates"]
|
||||
path = web/documentserver-example/java/src/main/resources/assets/document-templates
|
||||
url = https://github.com/ONLYOFFICE/document-templates
|
||||
branch = main/en
|
||||
[submodule "web/documentserver-example/ruby/assets/document-templates"]
|
||||
path = web/documentserver-example/ruby/assets/document-templates
|
||||
url = https://github.com/ONLYOFFICE/document-templates
|
||||
branch = main/en
|
||||
[submodule "web/documentserver-example/java-spring/src/main/resources/assets/document-templates"]
|
||||
path = web/documentserver-example/java-spring/src/main/resources/assets/document-templates
|
||||
url = https://github.com/ONLYOFFICE/document-templates
|
||||
branch = main/en
|
||||
[submodule "web/documentserver-example/python/assets/document-formats"]
|
||||
path = web/documentserver-example/python/assets/document-formats
|
||||
url = https://github.com/ONLYOFFICE/document-formats
|
||||
branch = master
|
||||
[submodule "web/documentserver-example/ruby/assets/document-formats"]
|
||||
path = web/documentserver-example/ruby/assets/document-formats
|
||||
url = https://github.com/ONLYOFFICE/document-formats
|
||||
branch = master
|
||||
|
||||
@ -307,14 +307,6 @@ PHPUnit - The PHP Unit Testing framework. (https://github.com/sebastianb
|
||||
License: BSD 3-Clause
|
||||
License File: phpunit.license
|
||||
|
||||
property-access - Provides functions to read and write from/to an object or array using a simple string notation. (https://github.com/symfony/property-access/blob/6.3/LICENSE)
|
||||
License: MIT
|
||||
License File: property-access.license
|
||||
|
||||
serializer - Handles serializing and deserializing data structures, including object graphs, into array structures or other formats like XML and JSON. (https://github.com/symfony/serializer/blob/6.3/LICENSE)
|
||||
License: MIT
|
||||
License File: serializer.license
|
||||
|
||||
|
||||
web/documentserver-example/python
|
||||
|
||||
@ -354,10 +346,6 @@ jQuery.UI - jQuery UI is an open source library of interface components —
|
||||
License: MIT
|
||||
License File: jQuery.UI.license
|
||||
|
||||
msgspec - A fast serialization and validation library, with builtin support for JSON, MessagePack, YAML, and TOML. (https://github.com/jcrist/msgspec/blob/0.18.1/LICENSE)
|
||||
License: BSD 3-Clause
|
||||
License File: msgspec.license
|
||||
|
||||
mypy - Optional static typing for Python. (https://github.com/python/mypy/blob/master/LICENSE)
|
||||
License: MIT
|
||||
License File: mypy.license
|
||||
|
||||
15
CHANGELOG.md
@ -1,21 +1,14 @@
|
||||
# Change Log
|
||||
|
||||
- nodejs: link in referenceData
|
||||
- nodejs: onRequestSelectDocument method
|
||||
- nodejs: onRequestSelectSpreadsheet method
|
||||
- nodejs: onRequestOpen
|
||||
- nodejs: submitForm
|
||||
- nodejs: key in referenceData
|
||||
- nodejs: change reference source
|
||||
- php: using a repo with a list of formats
|
||||
- nodejs: using a repo with a list of formats
|
||||
- nodejs: delete file without reloading the page
|
||||
- nodejs: getting history by a separate request
|
||||
- csharp-mvc: getting history by a separate request
|
||||
- csharp: getting history by a separate request
|
||||
- java: getting history by a separate request
|
||||
- java-spring: getting history by a separate request
|
||||
- restore from history
|
||||
- nodejs: restore from history
|
||||
- python: restore from history
|
||||
- ruby: restore from history
|
||||
- php: restore from history
|
||||
|
||||
## 1.6.0
|
||||
- nodejs: setUsers for region protection
|
||||
|
||||
@ -17,6 +17,7 @@
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Web;
|
||||
@ -235,6 +236,123 @@ namespace OnlineEditorsExampleMVC.Models
|
||||
return jss.Serialize(config);
|
||||
}
|
||||
|
||||
// get the document history
|
||||
public void GetHistory(out string history, out string historyData)
|
||||
{
|
||||
var storagePath = WebConfigurationManager.AppSettings["storage-path"];
|
||||
var jss = new JavaScriptSerializer();
|
||||
var histDir = DocManagerHelper.HistoryDir(DocManagerHelper.StoragePath(FileName, null));
|
||||
|
||||
history = null;
|
||||
historyData = null;
|
||||
|
||||
if (DocManagerHelper.GetFileVersion(histDir) > 0) // if the file was modified (the file version is greater than 0)
|
||||
{
|
||||
var currentVersion = DocManagerHelper.GetFileVersion(histDir);
|
||||
var hist = new List<Dictionary<string, object>>();
|
||||
var histData = new Dictionary<string, object>();
|
||||
|
||||
for (var i = 1; i <= currentVersion; i++) // run through all the file versions
|
||||
{
|
||||
var obj = new Dictionary<string, object>();
|
||||
var dataObj = new Dictionary<string, object>();
|
||||
var verDir = DocManagerHelper.VersionDir(histDir, i); // get the path to the given file version
|
||||
|
||||
var key = i == currentVersion ? Key : File.ReadAllText(Path.Combine(verDir, "key.txt")); // get document key
|
||||
|
||||
obj.Add("key", key);
|
||||
obj.Add("version", i);
|
||||
|
||||
if (i == 1) // check if the version number is equal to 1
|
||||
{
|
||||
var infoPath = Path.Combine(histDir, "createdInfo.json"); // get meta data of this file
|
||||
|
||||
if (File.Exists(infoPath))
|
||||
{
|
||||
var info = jss.Deserialize<Dictionary<string, object>>(File.ReadAllText(infoPath));
|
||||
obj.Add("created", info["created"]); // write meta information to the object (user information and creation date)
|
||||
obj.Add("user", new Dictionary<string, object>() {
|
||||
{ "id", info["id"] },
|
||||
{ "name", info["name"] },
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
var ext = Path.GetExtension(FileName).ToLower();
|
||||
dataObj.Add("fileType", ext.Replace(".", ""));
|
||||
dataObj.Add("key", key);
|
||||
// write file url to the data object
|
||||
string prevFileUrl;
|
||||
string directPrevFileUrl;
|
||||
if (Path.IsPathRooted(storagePath) && !string.IsNullOrEmpty(storagePath))
|
||||
{
|
||||
prevFileUrl = i == currentVersion ? DocManagerHelper.GetHistoryDownloadUrl(FileName, i.ToString(), "prev" + ext)
|
||||
: DocManagerHelper.GetDownloadUrl(Directory.GetFiles(verDir, "prev.*")[0].Replace(storagePath + "\\", ""));
|
||||
directPrevFileUrl = i == currentVersion ? DocManagerHelper.GetHistoryDownloadUrl(FileName, i.ToString(), "prev" + ext, false)
|
||||
: DocManagerHelper.GetDownloadUrl(Directory.GetFiles(verDir, "prev.*")[0].Replace(storagePath + "\\", ""), false);
|
||||
}
|
||||
else {
|
||||
prevFileUrl = i == currentVersion ? FileUri
|
||||
: DocManagerHelper.GetHistoryDownloadUrl(FileName, i.ToString(), "prev" + ext);
|
||||
directPrevFileUrl = i == currentVersion ? DocManagerHelper.GetHistoryDownloadUrl(FileName, i.ToString(), "prev" + ext, false)
|
||||
: DocManagerHelper.GetDownloadUrl(Directory.GetFiles(verDir, "prev.*")[0].Replace(storagePath + "\\", ""), false);
|
||||
}
|
||||
|
||||
dataObj.Add("url", prevFileUrl);
|
||||
if (IsEnabledDirectUrl)
|
||||
{
|
||||
dataObj.Add("directUrl", directPrevFileUrl);
|
||||
}
|
||||
dataObj.Add("version", i);
|
||||
if (i > 1) // check if the version number is greater than 1 (the file was modified)
|
||||
{
|
||||
// get the path to the changes.json file
|
||||
var changes = jss.Deserialize<Dictionary<string, object>>(File.ReadAllText(Path.Combine(DocManagerHelper.VersionDir(histDir, i - 1), "changes.json")));
|
||||
var changesArray = (ArrayList)changes["changes"];
|
||||
var change = changesArray.Count > 0
|
||||
? (Dictionary<string, object>)changesArray[0]
|
||||
: new Dictionary<string, object>();
|
||||
|
||||
// write information about changes to the object
|
||||
obj.Add("changes", change.Count > 0 ? changes["changes"] : null);
|
||||
obj.Add("serverVersion", changes["serverVersion"]);
|
||||
obj.Add("created", change.Count > 0 ? change["created"] : null);
|
||||
obj.Add("user", change.Count > 0 ? change["user"] : null);
|
||||
|
||||
var prev = (Dictionary<string, object>)histData[(i - 2).ToString()]; // get the history data from the previous file version
|
||||
dataObj.Add("previous", IsEnabledDirectUrl ? new Dictionary<string, object>() { // write information about previous file version to the data object with direct url
|
||||
{ "fileType", prev["fileType"] },
|
||||
{ "key", prev["key"] }, // write key and url information about previous file version
|
||||
{ "url", prev["url"] },
|
||||
{ "directUrl", prev["directUrl"] },
|
||||
} : new Dictionary<string, object>() { // write information about previous file version to the data object without direct url
|
||||
{ "fileType", prev["fileType"] },
|
||||
{ "key", prev["key"] }, // write key and url information about previous file version
|
||||
{ "url", prev["url"] },
|
||||
});
|
||||
// write the path to the diff.zip archive with differences in this file version
|
||||
var changesUrl = DocManagerHelper.GetHistoryDownloadUrl(FileName, (i - 1).ToString(), "diff.zip");
|
||||
dataObj.Add("changesUrl", changesUrl);
|
||||
}
|
||||
if(JwtManager.Enabled)
|
||||
{
|
||||
var token = JwtManager.Encode(dataObj);
|
||||
dataObj.Add("token", token);
|
||||
}
|
||||
hist.Add(obj); // add object dictionary to the hist list
|
||||
histData.Add((i - 1).ToString(), dataObj); // write data object information to the history data
|
||||
}
|
||||
|
||||
// write history information about the current file version to the history object
|
||||
history = jss.Serialize(new Dictionary<string, object>()
|
||||
{
|
||||
{ "currentVersion", currentVersion },
|
||||
{ "history", hist }
|
||||
});
|
||||
historyData = jss.Serialize(histData);
|
||||
}
|
||||
}
|
||||
|
||||
// get a document which will be compared with the current document
|
||||
public void GetCompareFileData(out string compareConfig)
|
||||
{
|
||||
|
||||
@ -190,47 +190,6 @@
|
||||
}
|
||||
};
|
||||
|
||||
var onRequestHistory = function () {
|
||||
let xhr = new XMLHttpRequest();
|
||||
xhr.open("GET", "webeditor.ashx?type=gethistory&filename=<%= Model.FileName %>");
|
||||
xhr.setRequestHeader("Content-Type", "application/json");
|
||||
xhr.send();
|
||||
xhr.onload = function () {
|
||||
console.log(xhr.responseText);
|
||||
docEditor.refreshHistory(JSON.parse(xhr.responseText));
|
||||
}
|
||||
};
|
||||
|
||||
var onRequestHistoryData = function (event) {
|
||||
var ver = event.data;
|
||||
|
||||
let xhr = new XMLHttpRequest();
|
||||
xhr.open("GET", "webeditor.ashx?type=getversiondata&filename=<%= Model.FileName %>&version=" + ver + "&directUrl=" + !!config.document.directUrl);
|
||||
xhr.setRequestHeader("Content-Type", "application/json");
|
||||
xhr.send();
|
||||
xhr.onload = function () {
|
||||
console.log(xhr.responseText);
|
||||
docEditor.setHistoryData(JSON.parse(xhr.responseText)); // send the link to the document for viewing the version history
|
||||
}
|
||||
};
|
||||
|
||||
var onRequestRestore = function (event) {
|
||||
var fileName = "<%= Model.FileName %>";
|
||||
var version = event.data.version;
|
||||
var data = {
|
||||
fileName: fileName,
|
||||
version: version
|
||||
};
|
||||
|
||||
let xhr = new XMLHttpRequest();
|
||||
xhr.open("POST", "webeditor.ashx?type=restore&directUrl=" + !!config.document.directUrl);
|
||||
xhr.setRequestHeader('Content-Type', 'application/json');
|
||||
xhr.send(JSON.stringify(data));
|
||||
xhr.onload = function () {
|
||||
docEditor.refreshHistory(JSON.parse(xhr.responseText));
|
||||
}
|
||||
}
|
||||
|
||||
config = <%= Model.GetDocConfig(Request, Url) %>;
|
||||
|
||||
config.width = "100%";
|
||||
@ -248,19 +207,30 @@
|
||||
"onRequestMailMergeRecipients": onRequestMailMergeRecipients,
|
||||
};
|
||||
|
||||
<% string hist, histData; %>
|
||||
<% Model.GetHistory(out hist, out histData); %>
|
||||
|
||||
<% string usersForMentions; %>
|
||||
<% Model.GetUsersMentions(Request, out usersForMentions); %>
|
||||
|
||||
if (config.editorConfig.user.id) {
|
||||
// the user is trying to show the document version history
|
||||
config.events['onRequestHistory'] = onRequestHistory;
|
||||
// the user is trying to click the specific document version in the document version history
|
||||
config.events['onRequestHistoryData'] = onRequestHistoryData;
|
||||
// the user is trying to go back to the document from viewing the document version history
|
||||
config.events['onRequestHistoryClose'] = function () {
|
||||
document.location.reload();
|
||||
};
|
||||
config.events['onRequestRestore'] = onRequestRestore;
|
||||
<% if (!string.IsNullOrEmpty(hist) && !string.IsNullOrEmpty(histData))
|
||||
{ %>
|
||||
// the user is trying to show the document version history
|
||||
config.events['onRequestHistory'] = function () {
|
||||
docEditor.refreshHistory(<%= hist %>); // show the document version history
|
||||
};
|
||||
// the user is trying to click the specific document version in the document version history
|
||||
config.events['onRequestHistoryData'] = function (event) {
|
||||
var ver = event.data;
|
||||
var histData = <%= histData %>;
|
||||
docEditor.setHistoryData(histData[ver - 1]); // send the link to the document for viewing the version history
|
||||
};
|
||||
// the user is trying to go back to the document from viewing the document version history
|
||||
config.events['onRequestHistoryClose'] = function () {
|
||||
document.location.reload();
|
||||
};
|
||||
<% } %>
|
||||
|
||||
// add mentions for not anonymous users
|
||||
<% if (!string.IsNullOrEmpty(usersForMentions))
|
||||
|
||||
@ -17,7 +17,6 @@
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
@ -51,15 +50,6 @@ namespace OnlineEditorsExampleMVC
|
||||
case "downloadhistory":
|
||||
DownloadHistory(context);
|
||||
break;
|
||||
case "gethistory":
|
||||
GetHistory(context);
|
||||
break;
|
||||
case "getversiondata":
|
||||
GetVersionData(context);
|
||||
break;
|
||||
case "restore":
|
||||
Restore(context);
|
||||
break;
|
||||
case "convert":
|
||||
Convert(context);
|
||||
break;
|
||||
@ -523,173 +513,6 @@ namespace OnlineEditorsExampleMVC
|
||||
get { return false; }
|
||||
}
|
||||
|
||||
private static void GetHistory(HttpContext context)
|
||||
{
|
||||
var jss = new JavaScriptSerializer();
|
||||
var fileName = context.Request["filename"];
|
||||
|
||||
var history = GetHistory(fileName);
|
||||
|
||||
context.Response.Write(jss.Serialize(history));
|
||||
}
|
||||
|
||||
private static void GetVersionData(HttpContext context)
|
||||
{
|
||||
var storagePath = WebConfigurationManager.AppSettings["storage-path"];
|
||||
var jss = new JavaScriptSerializer();
|
||||
|
||||
var fileName = context.Request["filename"];
|
||||
int version;
|
||||
|
||||
if (!int.TryParse(context.Request["version"], out version))
|
||||
{
|
||||
context.Response.Write("{ \"error\": \"Version number invalid!\"}");
|
||||
return;
|
||||
}
|
||||
|
||||
var versionData = new Dictionary<string, object>();
|
||||
|
||||
var histDir = DocManagerHelper.HistoryDir(DocManagerHelper.StoragePath(fileName, null));
|
||||
var lastVersion = DocManagerHelper.GetFileVersion(histDir);
|
||||
|
||||
var verDir = DocManagerHelper.VersionDir(histDir, version);
|
||||
|
||||
var key = version == lastVersion
|
||||
? ServiceConverter.GenerateRevisionId(DocManagerHelper.CurUserHostAddress()
|
||||
+ "/" + fileName + "/"
|
||||
+ File.GetLastWriteTime(DocManagerHelper.StoragePath(fileName, null)).GetHashCode())
|
||||
: File.ReadAllText(Path.Combine(verDir, "key.txt"));
|
||||
|
||||
|
||||
var ext = Path.GetExtension(fileName).ToLower();
|
||||
versionData.Add("fileType", ext.Replace(".", ""));
|
||||
versionData.Add("key", key);
|
||||
|
||||
// write file url to the data object
|
||||
string prevFileUrl;
|
||||
string directPrevFileUrl;
|
||||
if (Path.IsPathRooted(storagePath) && !string.IsNullOrEmpty(storagePath))
|
||||
{
|
||||
prevFileUrl = version == lastVersion ? DocManagerHelper.GetDownloadUrl(fileName)
|
||||
: DocManagerHelper.GetDownloadUrl(Directory.GetFiles(verDir, "prev.*")[0].Replace(storagePath + "\\", ""));
|
||||
directPrevFileUrl = version == lastVersion ? DocManagerHelper.GetDownloadUrl(fileName, false)
|
||||
: DocManagerHelper.GetDownloadUrl(Directory.GetFiles(verDir, "prev.*")[0].Replace(storagePath + "\\", ""), false);
|
||||
}
|
||||
else
|
||||
{
|
||||
prevFileUrl = version == lastVersion ? DocManagerHelper.GetFileUri(fileName, true)
|
||||
: DocManagerHelper.GetHistoryDownloadUrl(fileName, version.ToString(), "prev" + ext);
|
||||
directPrevFileUrl = version == lastVersion ? DocManagerHelper.GetFileUri(fileName, false)
|
||||
: DocManagerHelper.GetHistoryDownloadUrl(fileName, version.ToString(), "prev" + ext, false);
|
||||
}
|
||||
|
||||
versionData.Add("url", prevFileUrl);
|
||||
|
||||
var isEnableDirectUrl = string.Equals(DocManagerHelper.GetDirectUrl(), "true");
|
||||
if (isEnableDirectUrl)
|
||||
{
|
||||
versionData.Add("directUrl", directPrevFileUrl); // write direct url to the data object
|
||||
}
|
||||
|
||||
versionData.Add("version", version);
|
||||
if (version > 1)
|
||||
{
|
||||
var prevVerDir = DocManagerHelper.VersionDir(histDir, version - 1);
|
||||
|
||||
var prevUrl = Path.IsPathRooted(storagePath) && !string.IsNullOrEmpty(storagePath)
|
||||
? DocManagerHelper.GetDownloadUrl(Directory.GetFiles(prevVerDir, "prev.*")[0].Replace(storagePath + "\\", ""))
|
||||
: DocManagerHelper.GetHistoryDownloadUrl(fileName, (version - 1).ToString(), "prev" + ext);
|
||||
|
||||
var prevKey = File.ReadAllText(Path.Combine(prevVerDir, "key.txt"));
|
||||
|
||||
Dictionary<string, object> dataPrev = new Dictionary<string, object>() { // write information about previous file version to the data object
|
||||
{ "fileType", ext.Replace(".", "") },
|
||||
{ "key", prevKey }, // write key and url information about previous file version
|
||||
{ "url", prevUrl }
|
||||
};
|
||||
|
||||
string directPrevUrl;
|
||||
if (isEnableDirectUrl)
|
||||
{
|
||||
directPrevUrl = Path.IsPathRooted(storagePath) && !string.IsNullOrEmpty(storagePath)
|
||||
? DocManagerHelper.GetDownloadUrl(Directory.GetFiles(prevVerDir, "prev.*")[0].Replace(storagePath + "\\", ""), false)
|
||||
: DocManagerHelper.GetHistoryDownloadUrl(fileName, version.ToString(), "prev" + ext, false);
|
||||
|
||||
dataPrev.Add("directUrl", directPrevUrl);
|
||||
}
|
||||
|
||||
versionData.Add("previous", dataPrev);
|
||||
|
||||
if (File.Exists(Path.Combine(prevVerDir, "diff.zip")))
|
||||
{
|
||||
var changesUrl = DocManagerHelper.GetHistoryDownloadUrl(fileName, (version - 1).ToString(), "diff.zip");
|
||||
versionData.Add("changesUrl", changesUrl);
|
||||
}
|
||||
}
|
||||
|
||||
if (JwtManager.Enabled)
|
||||
{
|
||||
var token = JwtManager.Encode(versionData);
|
||||
versionData.Add("token", token);
|
||||
}
|
||||
|
||||
context.Response.Write(jss.Serialize(versionData));
|
||||
}
|
||||
|
||||
private static void Restore(HttpContext context)
|
||||
{
|
||||
string fileData;
|
||||
try
|
||||
{
|
||||
using (var receiveStream = context.Request.InputStream)
|
||||
using (var readStream = new StreamReader(receiveStream))
|
||||
{
|
||||
fileData = readStream.ReadToEnd();
|
||||
if (string.IsNullOrEmpty(fileData)) return;
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
throw new HttpException((int)HttpStatusCode.BadRequest, e.Message);
|
||||
}
|
||||
|
||||
var jss = new JavaScriptSerializer();
|
||||
var body = jss.Deserialize<Dictionary<string, object>>(fileData);
|
||||
|
||||
var fileName = (string)body["fileName"];
|
||||
var version = (int)body["version"];
|
||||
|
||||
var key = ServiceConverter.GenerateRevisionId(DocManagerHelper.CurUserHostAddress()
|
||||
+ "/" + fileName + "/"
|
||||
+ File.GetLastWriteTime(DocManagerHelper.StoragePath(fileName, null)).GetHashCode());
|
||||
|
||||
var histDir = DocManagerHelper.HistoryDir(DocManagerHelper.StoragePath(fileName, null));
|
||||
var currentVersionDir = DocManagerHelper.VersionDir(histDir, DocManagerHelper.GetFileVersion(histDir));
|
||||
var verDir = DocManagerHelper.VersionDir(histDir, version);
|
||||
|
||||
if (!Directory.Exists(currentVersionDir)) Directory.CreateDirectory(currentVersionDir);
|
||||
|
||||
var ext = Path.GetExtension(fileName).ToLower();
|
||||
File.Copy(DocManagerHelper.StoragePath(fileName, null), Path.Combine(currentVersionDir, "prev" + ext));
|
||||
|
||||
File.WriteAllText(Path.Combine(currentVersionDir, "key.txt"), key);
|
||||
|
||||
var changesPath = Path.Combine(DocManagerHelper.VersionDir(histDir, version - 1), "changes.json");
|
||||
if (File.Exists(changesPath))
|
||||
{
|
||||
File.Copy(changesPath, Path.Combine(currentVersionDir, "changes.json"));
|
||||
}
|
||||
|
||||
File.Copy(Path.Combine(verDir, "prev" + ext), DocManagerHelper.StoragePath(fileName, null), true);
|
||||
|
||||
var fileInfo = new FileInfo(DocManagerHelper.StoragePath(fileName, null));
|
||||
fileInfo.LastWriteTimeUtc = DateTime.UtcNow;
|
||||
|
||||
var history = GetHistory(fileName);
|
||||
|
||||
context.Response.Write(jss.Serialize(history));
|
||||
}
|
||||
|
||||
// download a history file
|
||||
private static void DownloadHistory(HttpContext context)
|
||||
{
|
||||
@ -864,70 +687,6 @@ namespace OnlineEditorsExampleMVC
|
||||
context.Response.Write(jss.Serialize(data));
|
||||
}
|
||||
|
||||
// get the document history
|
||||
private static Dictionary<string, object> GetHistory(string fileName)
|
||||
{
|
||||
var jss = new JavaScriptSerializer();
|
||||
var histDir = DocManagerHelper.HistoryDir(DocManagerHelper.StoragePath(fileName, null));
|
||||
|
||||
var history = new Dictionary<string, object>();
|
||||
|
||||
var currentVersion = DocManagerHelper.GetFileVersion(histDir);
|
||||
var currentKey = ServiceConverter.GenerateRevisionId(DocManagerHelper.CurUserHostAddress()
|
||||
+ "/" + fileName + "/"
|
||||
+ File.GetLastWriteTime(DocManagerHelper.StoragePath(fileName, null)).GetHashCode());
|
||||
|
||||
var versionList = new List<Dictionary<string, object>>();
|
||||
for (var versionNum = 1; versionNum <= currentVersion; versionNum++)
|
||||
{
|
||||
var versionObj = new Dictionary<string, object>();
|
||||
var verDir = DocManagerHelper.VersionDir(histDir, versionNum); // get the path to the given file version
|
||||
|
||||
var key = versionNum == currentVersion ? currentKey : File.ReadAllText(Path.Combine(verDir, "key.txt")); // get document key
|
||||
|
||||
versionObj.Add("key", key);
|
||||
versionObj.Add("version", versionNum);
|
||||
|
||||
var changesPath = Path.Combine(DocManagerHelper.VersionDir(histDir, versionNum - 1), "changes.json");
|
||||
if (versionNum == 1 || !File.Exists(changesPath)) // check if the version number is equal to 1
|
||||
{
|
||||
var infoPath = Path.Combine(histDir, "createdInfo.json"); // get meta data of this file
|
||||
if (File.Exists(infoPath))
|
||||
{
|
||||
var info = jss.Deserialize<Dictionary<string, object>>(File.ReadAllText(infoPath));
|
||||
versionObj.Add("created", info["created"]); // write meta information to the object (user information and creation date)
|
||||
versionObj.Add("user", new Dictionary<string, object>()
|
||||
{
|
||||
{ "id", info["id"] },
|
||||
{ "name", info["name"] },
|
||||
});
|
||||
}
|
||||
}
|
||||
else if (versionNum > 1) // check if the version number is greater than 1 (the file was modified)
|
||||
{
|
||||
// get the path to the changes.json file
|
||||
var changes = jss.Deserialize<Dictionary<string, object>>(File.ReadAllText(changesPath));
|
||||
var changesArray = (ArrayList)changes["changes"];
|
||||
var change = changesArray.Count > 0
|
||||
? (Dictionary<string, object>)changesArray[0]
|
||||
: new Dictionary<string, object>();
|
||||
|
||||
// write information about changes to the object
|
||||
versionObj.Add("changes", change.Count > 0 ? changes["changes"] : null);
|
||||
versionObj.Add("serverVersion", changes["serverVersion"]);
|
||||
versionObj.Add("created", change.Count > 0 ? change["created"] : null);
|
||||
versionObj.Add("user", change.Count > 0 ? change["user"] : null);
|
||||
}
|
||||
|
||||
versionList.Add(versionObj);
|
||||
}
|
||||
|
||||
history.Add("currentVersion", currentVersion);
|
||||
history.Add("history", versionList);
|
||||
|
||||
return history;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@ -633,12 +633,5 @@ namespace OnlineEditorsExample
|
||||
string isEnabledDirectUrl = HttpUtility.ParseQueryString(HttpContext.Current.Request.Url.Query).Get("directUrl");
|
||||
return "&directUrl=" + (isEnabledDirectUrl != null ? isEnabledDirectUrl : "false");
|
||||
}
|
||||
|
||||
// get direct url flag
|
||||
public static bool IsEnabledDirectUrl()
|
||||
{
|
||||
string isEnabledDirectUrl = HttpUtility.ParseQueryString(HttpContext.Current.Request.Url.Query).Get("directUrl");
|
||||
return isEnabledDirectUrl != null ? Convert.ToBoolean(isEnabledDirectUrl) : false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -221,49 +221,20 @@
|
||||
};
|
||||
|
||||
if (config.editorConfig.user.id) {
|
||||
|
||||
config.events['onRequestHistory'] = function (event) { // the user is trying to show the document version history
|
||||
|
||||
let xhr = new XMLHttpRequest();
|
||||
xhr.open("GET", "webeditor.ashx?type=gethistory&filename=<%= FileName %>");
|
||||
xhr.setRequestHeader("Content-Type", "application/json");
|
||||
xhr.send();
|
||||
xhr.onload = function () {
|
||||
console.log(xhr.responseText);
|
||||
docEditor.refreshHistory(JSON.parse(xhr.responseText));
|
||||
}
|
||||
};
|
||||
config.events['onRequestHistoryData'] = function (event) { // the user is trying to click the specific document version in the document version history
|
||||
var ver = event.data;
|
||||
|
||||
let xhr = new XMLHttpRequest();
|
||||
xhr.open("GET", "webeditor.ashx?type=getversiondata&filename=<%= FileName %>&version=" + ver + "&directUrl=" + !!config.document.directUrl);
|
||||
xhr.setRequestHeader("Content-Type", "application/json");
|
||||
xhr.send();
|
||||
xhr.onload = function () {
|
||||
console.log(xhr.responseText);
|
||||
docEditor.setHistoryData(JSON.parse(xhr.responseText)); // send the link to the document for viewing the version history
|
||||
}
|
||||
};
|
||||
config.events['onRequestHistoryClose'] = function () { // the user is trying to go back to the document from viewing the document version history
|
||||
document.location.reload();
|
||||
};
|
||||
config.events['onRequestRestore'] = function (event) {
|
||||
var fileName = "<%= FileName %>";
|
||||
var version = event.data.version;
|
||||
var data = {
|
||||
fileName: fileName,
|
||||
version: version
|
||||
<% if (!string.IsNullOrEmpty(History) && !string.IsNullOrEmpty(HistoryData))
|
||||
{ %>
|
||||
config.events['onRequestHistory'] = function () { // the user is trying to show the document version history
|
||||
docEditor.refreshHistory(<%= History %>); // show the document version history
|
||||
};
|
||||
|
||||
let xhr = new XMLHttpRequest();
|
||||
xhr.open("POST", "webeditor.ashx?type=restore&directUrl=" + !!config.document.directUrl);
|
||||
xhr.setRequestHeader('Content-Type', 'application/json');
|
||||
xhr.send(JSON.stringify(data));
|
||||
xhr.onload = function () {
|
||||
docEditor.refreshHistory(JSON.parse(xhr.responseText));
|
||||
}
|
||||
};
|
||||
config.events['onRequestHistoryData'] = function (event) { // the user is trying to click the specific document version in the document version history
|
||||
var ver = event.data;
|
||||
var histData = <%= HistoryData %>;
|
||||
docEditor.setHistoryData(histData[ver - 1]); // send the link to the document for viewing the version history
|
||||
};
|
||||
config.events['onRequestHistoryClose'] = function () { // the user is trying to go back to the document from viewing the document version history
|
||||
document.location.reload();
|
||||
};
|
||||
<% } %>
|
||||
|
||||
// add mentions for not anonymous users
|
||||
<% if (!string.IsNullOrEmpty(UsersForMentions))
|
||||
|
||||
@ -17,6 +17,7 @@
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Web;
|
||||
@ -60,6 +61,8 @@ namespace OnlineEditorsExample
|
||||
}
|
||||
|
||||
protected string DocConfig { get; private set; }
|
||||
protected string History { get; private set; }
|
||||
protected string HistoryData { get; private set; }
|
||||
protected string InsertImageConfig { get; private set; }
|
||||
protected string CompareFileData { get; private set; }
|
||||
protected string DataMailMergeRecipients { get; private set; }
|
||||
@ -192,7 +195,7 @@ namespace OnlineEditorsExample
|
||||
{
|
||||
{ "title", FileName },
|
||||
{ "url", getDownloadUrl(FileName) },
|
||||
{ "directUrl", _Default.IsEnabledDirectUrl() ? directUrl : "" },
|
||||
{ "directUrl", IsEnabledDirectUrl() ? directUrl : "" },
|
||||
{ "fileType", ext.Trim('.') },
|
||||
{ "key", Key },
|
||||
{
|
||||
@ -317,10 +320,134 @@ namespace OnlineEditorsExample
|
||||
// get users for mentions
|
||||
List<Dictionary<string, object>> usersData = Users.getUsersForMentions(user.id);
|
||||
UsersForMentions = !user.id.Equals("uid-0") ? jss.Serialize(usersData) : null;
|
||||
|
||||
Dictionary<string, object> hist;
|
||||
Dictionary<string, object> histData;
|
||||
|
||||
// get the document history
|
||||
GetHistory(out hist, out histData);
|
||||
if (hist != null && histData != null)
|
||||
{
|
||||
History = jss.Serialize(hist);
|
||||
HistoryData = jss.Serialize(histData);
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
||||
// get the document history
|
||||
private void GetHistory(out Dictionary<string, object> history, out Dictionary<string, object> historyData)
|
||||
{
|
||||
var storagePath = WebConfigurationManager.AppSettings["storage-path"];
|
||||
var jss = new JavaScriptSerializer();
|
||||
var histDir = _Default.HistoryDir(_Default.StoragePath(FileName, null));
|
||||
|
||||
history = null;
|
||||
historyData = null;
|
||||
|
||||
if (_Default.GetFileVersion(histDir) > 0) // if the file was modified (the file version is greater than 0)
|
||||
{
|
||||
var currentVersion = _Default.GetFileVersion(histDir);
|
||||
var hist = new List<Dictionary<string, object>>();
|
||||
var histData = new Dictionary<string, object>();
|
||||
|
||||
for (var i = 1; i <= currentVersion; i++) // run through all the file versions
|
||||
{
|
||||
var obj = new Dictionary<string, object>();
|
||||
var dataObj = new Dictionary<string, object>();
|
||||
var verDir = _Default.VersionDir(histDir, i); // get the path to the given file version
|
||||
|
||||
var key = i == currentVersion ? Key : File.ReadAllText(Path.Combine(verDir, "key.txt")); // get document key
|
||||
|
||||
obj.Add("key", key);
|
||||
obj.Add("version", i);
|
||||
|
||||
if (i == 1) // check if the version number is equal to 1
|
||||
{
|
||||
var infoPath = Path.Combine(histDir, "createdInfo.json"); // get meta data of this file
|
||||
|
||||
if (File.Exists(infoPath)) {
|
||||
var info = jss.Deserialize<Dictionary<string, object>>(File.ReadAllText(infoPath));
|
||||
obj.Add("created", info["created"]); // write meta information to the object (user information and creation date)
|
||||
obj.Add("user", new Dictionary<string, object>() {
|
||||
{ "id", info["id"] },
|
||||
{ "name", info["name"] },
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
var ext = Path.GetExtension(FileName).ToLower();
|
||||
dataObj.Add("fileType", ext.Replace(".", ""));
|
||||
dataObj.Add("key", key);
|
||||
// write file url to the data object
|
||||
var directPrevFileUrl = i == currentVersion ? _Default.FileUri(FileName, false) : MakePublicHistoryUrl(FileName, i.ToString(), "prev" + ext, false);
|
||||
var prevFileUrl = i == currentVersion ? FileUri : MakePublicHistoryUrl(FileName, i.ToString(), "prev" + ext);
|
||||
if (Path.IsPathRooted(storagePath))
|
||||
{
|
||||
prevFileUrl = i == currentVersion ? getDownloadUrl(FileName) : getDownloadUrl(Directory.GetFiles(verDir, "prev.*")[0].Replace(storagePath + "\\", ""));
|
||||
directPrevFileUrl = i == currentVersion ? getDownloadUrl(FileName, false) : getDownloadUrl(Directory.GetFiles(verDir, "prev.*")[0].Replace(storagePath + "\\", ""), false);
|
||||
}
|
||||
|
||||
dataObj.Add("url", prevFileUrl); // write file url to the data object
|
||||
|
||||
if (IsEnabledDirectUrl())
|
||||
{
|
||||
dataObj.Add("directUrl", directPrevFileUrl); // write direct url to the data object
|
||||
}
|
||||
|
||||
dataObj.Add("version", i);
|
||||
if (i > 1) // check if the version number is greater than 1 (the file was modified)
|
||||
{
|
||||
// get the path to the changes.json file
|
||||
var changes = jss.Deserialize<Dictionary<string, object>>(File.ReadAllText(Path.Combine(_Default.VersionDir(histDir, i - 1), "changes.json")));
|
||||
var changesArray = (ArrayList)changes["changes"];
|
||||
var change = changesArray.Count > 0
|
||||
? (Dictionary<string, object>)changesArray[0]
|
||||
: new Dictionary<string, object>();
|
||||
|
||||
// write information about changes to the object
|
||||
obj.Add("changes", change.Count > 0 ? changes["changes"] : null);
|
||||
obj.Add("serverVersion", changes["serverVersion"]);
|
||||
obj.Add("created", change.Count > 0 ? change["created"] : null);
|
||||
obj.Add("user", change.Count > 0 ? change["user"] : null);
|
||||
|
||||
var prev = (Dictionary<string, object>)histData[(i - 2).ToString()]; // get the history data from the previous file version
|
||||
|
||||
Dictionary<string, object> dataPrev = new Dictionary<string, object>() { // write information about previous file version to the data object
|
||||
{ "fileType", prev["fileType"] },
|
||||
{ "key", prev["key"] }, // write key and url information about previous file version
|
||||
{ "url", prev["url"] }
|
||||
};
|
||||
|
||||
if (IsEnabledDirectUrl())
|
||||
{
|
||||
dataPrev.Add("directUrl", prev["directUrl"]);
|
||||
}
|
||||
|
||||
dataObj.Add("previous", dataPrev);
|
||||
// write the path to the diff.zip archive with differences in this file version
|
||||
var changesUrl = MakePublicHistoryUrl(FileName, (i - 1).ToString(), "diff.zip");
|
||||
dataObj.Add("changesUrl", changesUrl);
|
||||
}
|
||||
if (JwtManager.Enabled)
|
||||
{
|
||||
var token = JwtManager.Encode(dataObj);
|
||||
dataObj.Add("token", token);
|
||||
}
|
||||
hist.Add(obj); // add object dictionary to the hist list
|
||||
histData.Add((i - 1).ToString(), dataObj); // write data object information to the history data
|
||||
}
|
||||
|
||||
// write history information about the current file version to the history object
|
||||
history = new Dictionary<string, object>()
|
||||
{
|
||||
{ "currentVersion", currentVersion },
|
||||
{ "history", hist }
|
||||
};
|
||||
historyData = histData;
|
||||
}
|
||||
}
|
||||
|
||||
// get a logo config
|
||||
private Dictionary<string, object> GetLogoConfig()
|
||||
{
|
||||
@ -342,7 +469,7 @@ namespace OnlineEditorsExample
|
||||
{ "url", InsertImageUrl.ToString()}
|
||||
};
|
||||
|
||||
if (_Default.IsEnabledDirectUrl())
|
||||
if (IsEnabledDirectUrl())
|
||||
{
|
||||
logoConfig.Add("directUrl", DirectImageUrl.ToString());
|
||||
}
|
||||
@ -379,7 +506,7 @@ namespace OnlineEditorsExample
|
||||
{ "url", compareFileUrl.ToString() }
|
||||
};
|
||||
|
||||
if (_Default.IsEnabledDirectUrl())
|
||||
if (IsEnabledDirectUrl())
|
||||
{
|
||||
dataCompareFile.Add("directUrl", DirectFileUrl.ToString());
|
||||
}
|
||||
@ -418,7 +545,7 @@ namespace OnlineEditorsExample
|
||||
{ "url", mailmergeUrl.ToString() }
|
||||
};
|
||||
|
||||
if (_Default.IsEnabledDirectUrl())
|
||||
if (IsEnabledDirectUrl())
|
||||
{
|
||||
mailMergeConfig.Add("directUrl", DirectMailMergeUrl.ToString());
|
||||
}
|
||||
@ -462,6 +589,21 @@ namespace OnlineEditorsExample
|
||||
return _Default.GetServerUrl(true) + fullPath.Substring(root.Length).Replace(Path.DirectorySeparatorChar, '/');
|
||||
}
|
||||
|
||||
|
||||
// create the public history url
|
||||
private string MakePublicHistoryUrl(string filename, string version, string file, Boolean isServer = true)
|
||||
{
|
||||
var userAddress = isServer ? "&userAddress=" + HttpUtility.UrlEncode(_Default.CurUserHostAddress(HttpContext.Current.Request.UserHostAddress)) : "";
|
||||
var fileUrl = new UriBuilder(_Default.GetServerUrl(isServer));
|
||||
fileUrl.Path = HttpRuntime.AppDomainAppVirtualPath
|
||||
+ (HttpRuntime.AppDomainAppVirtualPath.EndsWith("/") ? "" : "/")
|
||||
+ "webeditor.ashx";
|
||||
fileUrl.Query = "type=downloadhistory&fileName=" + HttpUtility.UrlEncode(filename)
|
||||
+ "&ver=" + version + "&file=" + file
|
||||
+ userAddress;
|
||||
return fileUrl.ToString();
|
||||
}
|
||||
|
||||
// create demo document
|
||||
private static void Try(string type, string sample, HttpRequest request)
|
||||
{
|
||||
@ -510,5 +652,12 @@ namespace OnlineEditorsExample
|
||||
{ "name", uname }
|
||||
}));
|
||||
}
|
||||
|
||||
// get direct url flag
|
||||
private static bool IsEnabledDirectUrl()
|
||||
{
|
||||
string isEnabledDirectUrl = HttpUtility.ParseQueryString(HttpContext.Current.Request.Url.Query).Get("directUrl");
|
||||
return isEnabledDirectUrl != null ? Convert.ToBoolean(isEnabledDirectUrl) : false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -26,9 +26,7 @@ using System.Diagnostics;
|
||||
using System.Web.Configuration;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Collections;
|
||||
using System.Net.Sockets;
|
||||
using ASC.Api.DocumentConverter;
|
||||
|
||||
namespace OnlineEditorsExample
|
||||
{
|
||||
@ -50,15 +48,6 @@ namespace OnlineEditorsExample
|
||||
case "downloadhistory":
|
||||
DownloadHistory(context);
|
||||
break;
|
||||
case "gethistory":
|
||||
GetHistory(context);
|
||||
break;
|
||||
case "getversiondata":
|
||||
GetVersionData(context);
|
||||
break;
|
||||
case "restore":
|
||||
Restore(context);
|
||||
break;
|
||||
case "convert":
|
||||
Convert(context);
|
||||
break;
|
||||
@ -344,164 +333,6 @@ namespace OnlineEditorsExample
|
||||
get { return false; }
|
||||
}
|
||||
|
||||
private static void GetHistory(HttpContext context)
|
||||
{
|
||||
var jss = new JavaScriptSerializer();
|
||||
var fileName = context.Request["filename"];
|
||||
|
||||
var history = GetHistory(fileName);
|
||||
|
||||
context.Response.Write(jss.Serialize(history));
|
||||
}
|
||||
|
||||
private static void GetVersionData(HttpContext context)
|
||||
{
|
||||
var storagePath = WebConfigurationManager.AppSettings["storage-path"];
|
||||
var jss = new JavaScriptSerializer();
|
||||
|
||||
var fileName = context.Request["filename"];
|
||||
int version;
|
||||
|
||||
if (!int.TryParse(context.Request["version"], out version))
|
||||
{
|
||||
context.Response.Write("{ \"error\": \"Version number invalid!\"}");
|
||||
return;
|
||||
}
|
||||
|
||||
var versionData = new Dictionary<string, object>();
|
||||
|
||||
var histDir = _Default.HistoryDir(_Default.StoragePath(fileName, null));
|
||||
var lastVersion = _Default.GetFileVersion(histDir);
|
||||
|
||||
var verDir = _Default.VersionDir(histDir, version);
|
||||
|
||||
var lastVersionUri = _Default.FileUri(fileName, true);
|
||||
var key = version == lastVersion
|
||||
? ServiceConverter.GenerateRevisionId(_Default.CurUserHostAddress(null)
|
||||
+ "/" + Path.GetFileName(lastVersionUri)
|
||||
+ "/" + File.GetLastWriteTime(_Default.StoragePath(fileName, null)).GetHashCode())
|
||||
: File.ReadAllText(Path.Combine(verDir, "key.txt"));
|
||||
|
||||
|
||||
var ext = Path.GetExtension(fileName).ToLower();
|
||||
versionData.Add("fileType", ext.Replace(".", ""));
|
||||
versionData.Add("key", key);
|
||||
|
||||
var directPrevFileUrl = version == lastVersion ? _Default.FileUri(fileName, false) : MakePublicHistoryUrl(fileName, version.ToString(), "prev" + ext, false);
|
||||
var prevFileUrl = version == lastVersion ? lastVersionUri : MakePublicHistoryUrl(fileName, version.ToString(), "prev" + ext);
|
||||
if (Path.IsPathRooted(storagePath))
|
||||
{
|
||||
prevFileUrl = version == lastVersion ? DocEditor.getDownloadUrl(fileName) : DocEditor.getDownloadUrl(Directory.GetFiles(verDir, "prev.*")[0].Replace(storagePath + "\\", ""));
|
||||
directPrevFileUrl = version == lastVersion ? DocEditor.getDownloadUrl(fileName, false) : DocEditor.getDownloadUrl(Directory.GetFiles(verDir, "prev.*")[0].Replace(storagePath + "\\", ""), false);
|
||||
}
|
||||
|
||||
versionData.Add("url", prevFileUrl);
|
||||
|
||||
if (_Default.IsEnabledDirectUrl())
|
||||
{
|
||||
versionData.Add("directUrl", directPrevFileUrl); // write direct url to the data object
|
||||
}
|
||||
|
||||
versionData.Add("version", version);
|
||||
if (version > 1)
|
||||
{
|
||||
var prevVerDir = _Default.VersionDir(histDir, version - 1);
|
||||
|
||||
var prevUrl = MakePublicHistoryUrl(fileName, (version - 1).ToString(), "prev" + ext);
|
||||
if (Path.IsPathRooted(storagePath))
|
||||
prevUrl = DocEditor.getDownloadUrl(Directory.GetFiles(prevVerDir, "prev.*")[0].Replace(storagePath + "\\", ""));
|
||||
|
||||
var prevKey = File.ReadAllText(Path.Combine(prevVerDir, "key.txt"));
|
||||
|
||||
Dictionary<string, object> dataPrev = new Dictionary<string, object>() { // write information about previous file version to the data object
|
||||
{ "fileType", ext.Replace(".", "") },
|
||||
{ "key", prevKey }, // write key and url information about previous file version
|
||||
{ "url", prevUrl }
|
||||
};
|
||||
|
||||
string directPrevUrl;
|
||||
if (_Default.IsEnabledDirectUrl())
|
||||
{
|
||||
directPrevUrl = Path.IsPathRooted(storagePath)
|
||||
? DocEditor.getDownloadUrl(Directory.GetFiles(prevVerDir, "prev.*")[0].Replace(storagePath + "\\", ""), false)
|
||||
: MakePublicHistoryUrl(fileName, (version - 1).ToString(), "prev" + ext, false);
|
||||
|
||||
dataPrev.Add("directUrl", directPrevUrl); // write direct url to the data object
|
||||
}
|
||||
|
||||
versionData.Add("previous", dataPrev);
|
||||
|
||||
if (File.Exists(Path.Combine(prevVerDir, "diff.zip")))
|
||||
{
|
||||
var changesUrl = MakePublicHistoryUrl(fileName, (version - 1).ToString(), "diff.zip");
|
||||
versionData.Add("changesUrl", changesUrl);
|
||||
}
|
||||
}
|
||||
|
||||
if (JwtManager.Enabled)
|
||||
{
|
||||
var token = JwtManager.Encode(versionData);
|
||||
versionData.Add("token", token);
|
||||
}
|
||||
|
||||
context.Response.Write(jss.Serialize(versionData));
|
||||
}
|
||||
|
||||
private void Restore(HttpContext context)
|
||||
{
|
||||
string fileData;
|
||||
try
|
||||
{
|
||||
using (var receiveStream = context.Request.InputStream)
|
||||
using (var readStream = new StreamReader(receiveStream))
|
||||
{
|
||||
fileData = readStream.ReadToEnd();
|
||||
if (string.IsNullOrEmpty(fileData)) return;
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
throw new HttpException((int)HttpStatusCode.BadRequest, e.Message);
|
||||
}
|
||||
|
||||
var jss = new JavaScriptSerializer();
|
||||
var body = jss.Deserialize<Dictionary<string, object>>(fileData);
|
||||
|
||||
var fileName = (string)body["fileName"];
|
||||
var version = (int)body["version"];
|
||||
|
||||
var lastVersionUri = _Default.FileUri(fileName, true);
|
||||
var key = ServiceConverter.GenerateRevisionId(_Default.CurUserHostAddress(null)
|
||||
+ "/" + Path.GetFileName(lastVersionUri)
|
||||
+ "/" + File.GetLastWriteTime(_Default.StoragePath(fileName, null)).GetHashCode());
|
||||
|
||||
var histDir = _Default.HistoryDir(_Default.StoragePath(fileName, null));
|
||||
var currentVersionDir = _Default.VersionDir(histDir, _Default.GetFileVersion(histDir));
|
||||
var verDir = _Default.VersionDir(histDir, version);
|
||||
|
||||
if (!Directory.Exists(currentVersionDir)) Directory.CreateDirectory(currentVersionDir);
|
||||
|
||||
var ext = Path.GetExtension(fileName).ToLower();
|
||||
File.Copy(_Default.StoragePath(fileName, null), Path.Combine(currentVersionDir, "prev" + ext));
|
||||
|
||||
File.WriteAllText(Path.Combine(currentVersionDir, "key.txt"), key);
|
||||
|
||||
var changesPath = Path.Combine(_Default.VersionDir(histDir, version - 1), "changes.json");
|
||||
if (File.Exists(changesPath))
|
||||
{
|
||||
File.Copy(changesPath, Path.Combine(currentVersionDir, "changes.json"));
|
||||
}
|
||||
|
||||
File.Copy(Path.Combine(verDir, "prev" + ext), _Default.StoragePath(fileName, null), true);
|
||||
|
||||
var fileInfo = new FileInfo(_Default.StoragePath(fileName, null));
|
||||
fileInfo.LastWriteTimeUtc = DateTime.UtcNow;
|
||||
|
||||
var history = GetHistory(fileName);
|
||||
|
||||
context.Response.Write(jss.Serialize(history));
|
||||
}
|
||||
|
||||
private static void DownloadHistory(HttpContext context)
|
||||
{
|
||||
try
|
||||
@ -673,84 +504,5 @@ namespace OnlineEditorsExample
|
||||
|
||||
context.Response.Write(jss.Serialize(data));
|
||||
}
|
||||
|
||||
// get the document history
|
||||
private static Dictionary<string, object> GetHistory(string fileName)
|
||||
{
|
||||
var jss = new JavaScriptSerializer();
|
||||
var histDir = _Default.HistoryDir(_Default.StoragePath(fileName, null));
|
||||
|
||||
var history = new Dictionary<string, object>();
|
||||
|
||||
var currentVersion = _Default.GetFileVersion(histDir);
|
||||
var currentFileUri = _Default.FileUri(fileName, true);
|
||||
var currentKey = ServiceConverter.GenerateRevisionId(_Default.CurUserHostAddress(null)
|
||||
+ "/" + Path.GetFileName(currentFileUri)
|
||||
+ "/" + File.GetLastWriteTime(_Default.StoragePath(fileName, null)).GetHashCode());
|
||||
|
||||
var versionList = new List<Dictionary<string, object>>();
|
||||
for (var versionNum = 1; versionNum <= currentVersion; versionNum++)
|
||||
{
|
||||
var versionObj = new Dictionary<string, object>();
|
||||
var verDir = _Default.VersionDir(histDir, versionNum); // get the path to the given file version
|
||||
|
||||
var key = versionNum == currentVersion ? currentKey : File.ReadAllText(Path.Combine(verDir, "key.txt")); // get document key
|
||||
|
||||
versionObj.Add("key", key);
|
||||
versionObj.Add("version", versionNum);
|
||||
|
||||
var changesPath = Path.Combine(_Default.VersionDir(histDir, versionNum - 1), "changes.json");
|
||||
if (versionNum == 1 || !File.Exists(changesPath)) // check if the version number is equal to 1
|
||||
{
|
||||
var infoPath = Path.Combine(histDir, "createdInfo.json"); // get meta data of this file
|
||||
if (File.Exists(infoPath))
|
||||
{
|
||||
var info = jss.Deserialize<Dictionary<string, object>>(File.ReadAllText(infoPath));
|
||||
versionObj.Add("created", info["created"]); // write meta information to the object (user information and creation date)
|
||||
versionObj.Add("user", new Dictionary<string, object>()
|
||||
{
|
||||
{ "id", info["id"] },
|
||||
{ "name", info["name"] },
|
||||
});
|
||||
}
|
||||
}
|
||||
else if (versionNum > 1) // check if the version number is greater than 1 (the file was modified)
|
||||
{
|
||||
// get the path to the changes.json file
|
||||
var changes = jss.Deserialize<Dictionary<string, object>>(File.ReadAllText(changesPath));
|
||||
var changesArray = (ArrayList)changes["changes"];
|
||||
var change = changesArray.Count > 0
|
||||
? (Dictionary<string, object>)changesArray[0]
|
||||
: new Dictionary<string, object>();
|
||||
|
||||
// write information about changes to the object
|
||||
versionObj.Add("changes", change.Count > 0 ? changes["changes"] : null);
|
||||
versionObj.Add("serverVersion", changes["serverVersion"]);
|
||||
versionObj.Add("created", change.Count > 0 ? change["created"] : null);
|
||||
versionObj.Add("user", change.Count > 0 ? change["user"] : null);
|
||||
}
|
||||
|
||||
versionList.Add(versionObj);
|
||||
}
|
||||
|
||||
history.Add("currentVersion", currentVersion);
|
||||
history.Add("history", versionList);
|
||||
|
||||
return history;
|
||||
}
|
||||
|
||||
// create the public history url
|
||||
private static string MakePublicHistoryUrl(string filename, string version, string file, Boolean isServer = true)
|
||||
{
|
||||
var userAddress = isServer ? "&userAddress=" + HttpUtility.UrlEncode(_Default.CurUserHostAddress(HttpContext.Current.Request.UserHostAddress)) : "";
|
||||
var fileUrl = new UriBuilder(_Default.GetServerUrl(isServer));
|
||||
fileUrl.Path = HttpRuntime.AppDomainAppVirtualPath
|
||||
+ (HttpRuntime.AppDomainAppVirtualPath.EndsWith("/") ? "" : "/")
|
||||
+ "webeditor.ashx";
|
||||
fileUrl.Query = "type=downloadhistory&fileName=" + HttpUtility.UrlEncode(filename)
|
||||
+ "&ver=" + version + "&file=" + file
|
||||
+ userAddress;
|
||||
return fileUrl.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -128,7 +128,11 @@ See the detailed guide to learn how to install Document Server [for Linux](https
|
||||
|
||||
### Step 2. Install the prerequisites and run the website with the editors
|
||||
|
||||
1. Install **Java** following the instructions [here](https://docs.oracle.com/en/java/javase/20/install/installation-jdk-linux-platforms.html#GUID-737A84E4-2EFF-4D38-8E60-3E29D1B884B8).
|
||||
1. Install **Java**:
|
||||
|
||||
```
|
||||
sudo add-apt-repository ppa:webupd8team/java sudo apt-get update sudo apt-get install oracle-java11-installer
|
||||
```
|
||||
|
||||
2. Download the archive with the Java-Spring example and unpack the archive or clone git repository:
|
||||
|
||||
@ -206,51 +210,13 @@ Make sure that the Document Server has access to the server with the example ins
|
||||
|
||||
## For Docker
|
||||
|
||||
### Step 1. Install ONLYOFFICE Docs
|
||||
|
||||
Download and install ONLYOFFICE Docs (packaged as Document Server).
|
||||
|
||||
See the detailed guide to learn how to install Document Server [for Docker](https://helpcenter.onlyoffice.com/installation/docs-developer-install-docker.aspx).
|
||||
|
||||
### Step 2. Install the prerequisites and run the website with the editors
|
||||
|
||||
1. Install **Java** following the instructions [here](https://docs.oracle.com/en/java/javase/20/install/installation-jdk-linux-platforms.html#GUID-737A84E4-2EFF-4D38-8E60-3E29D1B884B8).
|
||||
|
||||
2. Download the archive with the Java-Spring example and unpack the archive or clone git repository:
|
||||
|
||||
a) archive with Java-Spring:
|
||||
|
||||
```
|
||||
wget https://api.onlyoffice.com/app_data/editor/Java%20Spring%20Example.zip
|
||||
```
|
||||
|
||||
```
|
||||
unzip Java\ Spring\ Example.zip
|
||||
```
|
||||
b) git repository:
|
||||
```
|
||||
git clone https://github.com/ONLYOFFICE/document-server-integration.git
|
||||
```
|
||||
|
||||
|
||||
3. Change the current directory for the project directory:
|
||||
|
||||
a) from archive
|
||||
|
||||
```
|
||||
cd Java\ Spring\ Example/
|
||||
```
|
||||
b) from git repository
|
||||
```
|
||||
cd document-server-integration/web/documentserver-example/java-spring
|
||||
```
|
||||
4. Edit the *application.properties* configuration file. Specify the name of your local server with the ONLYOFFICE Document Server installed:
|
||||
1. Edit the *application.properties* configuration file. Specify the name of your local server with the ONLYOFFICE Document Server installed ([installation instructions](https://helpcenter.onlyoffice.com/installation/docs-developer-install-docker.aspx)).
|
||||
|
||||
```
|
||||
nano src/main/resources/application.properties
|
||||
```
|
||||
|
||||
5. Edit the following lines:
|
||||
2. Edit the following lines:
|
||||
|
||||
```
|
||||
files.storage=
|
||||
@ -260,23 +226,17 @@ See the detailed guide to learn how to install Document Server [for Docker](http
|
||||
|
||||
where the **documentserver** is the name of the server with the ONLYOFFICE Docs installed, **port** is any available port and **files.storage** is the path where files will be created and stored (in the project folder by default). You can set an absolute path.
|
||||
|
||||
6. Run the next command in the java example directory:
|
||||
3. Run the next command in the java example directory:
|
||||
|
||||
```
|
||||
docker-compose up
|
||||
```
|
||||
7. Open your browser using **server.address** and **server.port**:
|
||||
4. Open your browser using **server.address** and **server.port**:
|
||||
|
||||
```
|
||||
http://server.address:server.port/
|
||||
```
|
||||
|
||||
### Step 3. Check accessibility
|
||||
|
||||
In case the example and Document Server are installed on different computers, make sure that your server with the example installed has access to the Document Server with the address which you specify instead of **documentserver** in the configuration files.
|
||||
|
||||
Make sure that the Document Server has access to the server with the example installed with the address which you specify instead of **example.com** in the configuration files.
|
||||
|
||||
## Important security info
|
||||
|
||||
Please keep in mind the following security aspects when you are using test examples:
|
||||
|
||||
@ -20,6 +20,7 @@ package com.onlyoffice.integration.controllers;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.onlyoffice.integration.documentserver.managers.history.HistoryManager;
|
||||
import com.onlyoffice.integration.documentserver.managers.jwt.JwtManager;
|
||||
import com.onlyoffice.integration.documentserver.models.enums.Action;
|
||||
import com.onlyoffice.integration.documentserver.storage.FileStoragePathBuilder;
|
||||
@ -72,6 +73,9 @@ public class EditorController {
|
||||
@Autowired
|
||||
private UserServices userService;
|
||||
|
||||
@Autowired
|
||||
private HistoryManager historyManager;
|
||||
|
||||
@Autowired
|
||||
private ObjectMapper objectMapper;
|
||||
|
||||
@ -136,6 +140,9 @@ public class EditorController {
|
||||
// add file model with the default parameters to the original model
|
||||
model.addAttribute("model", fileModel);
|
||||
|
||||
// get file history and add it to the model
|
||||
model.addAttribute("fileHistory", historyManager.getHistory(fileModel.getDocument()));
|
||||
|
||||
// create the document service api URL and add it to the model
|
||||
model.addAttribute("docserviceApiUrl", docserviceSite + docserviceApiUrl);
|
||||
|
||||
|
||||
@ -22,17 +22,11 @@ import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.onlyoffice.integration.documentserver.callbacks.CallbackHandler;
|
||||
import com.onlyoffice.integration.documentserver.managers.history.HistoryManager;
|
||||
import com.onlyoffice.integration.documentserver.managers.jwt.JwtManager;
|
||||
import com.onlyoffice.integration.documentserver.storage.FileStorageMutator;
|
||||
import com.onlyoffice.integration.documentserver.storage.FileStoragePathBuilder;
|
||||
import com.onlyoffice.integration.dto.Converter;
|
||||
import com.onlyoffice.integration.dto.ConvertedData;
|
||||
import com.onlyoffice.integration.dto.Reference;
|
||||
import com.onlyoffice.integration.dto.ReferenceData;
|
||||
import com.onlyoffice.integration.dto.Rename;
|
||||
import com.onlyoffice.integration.dto.Restore;
|
||||
import com.onlyoffice.integration.dto.SaveAs;
|
||||
import com.onlyoffice.integration.dto.Track;
|
||||
import com.onlyoffice.integration.entities.User;
|
||||
import com.onlyoffice.integration.documentserver.models.enums.DocumentType;
|
||||
@ -41,8 +35,6 @@ import com.onlyoffice.integration.documentserver.util.file.FileUtility;
|
||||
import com.onlyoffice.integration.documentserver.util.service.ServiceConverter;
|
||||
import com.onlyoffice.integration.documentserver.managers.document.DocumentManager;
|
||||
import com.onlyoffice.integration.documentserver.managers.callback.CallbackManager;
|
||||
|
||||
import org.json.simple.JSONArray;
|
||||
import org.json.simple.JSONObject;
|
||||
import org.json.simple.parser.JSONParser;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@ -57,7 +49,6 @@ import org.springframework.web.bind.annotation.CookieValue;
|
||||
import org.springframework.web.bind.annotation.CrossOrigin;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.PutMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
@ -65,21 +56,16 @@ import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.InetAddress;
|
||||
import java.net.URL;
|
||||
import java.net.URLEncoder;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
@ -119,8 +105,6 @@ public class FileController {
|
||||
private ServiceConverter serviceConverter;
|
||||
@Autowired
|
||||
private CallbackManager callbackManager;
|
||||
@Autowired
|
||||
private HistoryManager historyManager;
|
||||
|
||||
// create user metadata
|
||||
private String createUserMetadata(final String uid, final String fullFileName) {
|
||||
@ -371,13 +355,13 @@ public class FileController {
|
||||
@GetMapping("/assets")
|
||||
public ResponseEntity<Resource> assets(@RequestParam("name")
|
||||
final String name) { // get sample files from the assests
|
||||
String fileName = Path.of("assets", "document-templates", "sample", fileUtility.getFileName(name)).toString();
|
||||
String fileName = Path.of("assets", "sample", fileUtility.getFileName(name)).toString();
|
||||
return downloadFile(fileName);
|
||||
}
|
||||
|
||||
@GetMapping("/csv")
|
||||
public ResponseEntity<Resource> csv() { // download a csv file
|
||||
String fileName = Path.of("assets", "document-templates", "sample", "csv.csv").toString();
|
||||
String fileName = Path.of("assets", "sample", "csv.csv").toString();
|
||||
return downloadFile(fileName);
|
||||
}
|
||||
|
||||
@ -419,16 +403,19 @@ public class FileController {
|
||||
|
||||
@PostMapping("/saveas")
|
||||
@ResponseBody
|
||||
public String saveAs(@RequestBody final SaveAs body, @CookieValue("uid") final String uid) {
|
||||
public String saveAs(@RequestBody final JSONObject body, @CookieValue("uid") final String uid) {
|
||||
String title = (String) body.get("title");
|
||||
String saveAsFileUrl = (String) body.get("url");
|
||||
|
||||
try {
|
||||
String fileName = documentManager.getCorrectName(body.getTitle());
|
||||
String fileName = documentManager.getCorrectName(title);
|
||||
String curExt = fileUtility.getFileExtension(fileName);
|
||||
|
||||
if (!fileUtility.getFileExts().contains(curExt)) {
|
||||
return "{\"error\":\"File type is not supported\"}";
|
||||
}
|
||||
|
||||
URL url = new URL(body.getUrl());
|
||||
URL url = new URL(saveAsFileUrl);
|
||||
java.net.HttpURLConnection connection = (java.net.HttpURLConnection) url.openConnection();
|
||||
InputStream stream = connection.getInputStream();
|
||||
|
||||
@ -447,14 +434,25 @@ public class FileController {
|
||||
|
||||
@PostMapping("/rename")
|
||||
@ResponseBody
|
||||
public String rename(@RequestBody final Rename body) {
|
||||
String fileName = body.getFileName();
|
||||
public String rename(@RequestBody final JSONObject body) {
|
||||
String newfilename = (String) body.get("newfilename");
|
||||
String dockey = (String) body.get("dockey");
|
||||
String origExt = "." + (String) body.get("ext");
|
||||
String curExt = newfilename;
|
||||
|
||||
if (newfilename.indexOf(".") != -1) {
|
||||
curExt = (String) fileUtility.getFileExtension(newfilename);
|
||||
}
|
||||
|
||||
if (origExt.compareTo(curExt) != 0) {
|
||||
newfilename += origExt;
|
||||
}
|
||||
|
||||
HashMap<String, String> meta = new HashMap<>();
|
||||
meta.put("title", fileName + "." + body.getFileType());
|
||||
meta.put("title", newfilename);
|
||||
|
||||
try {
|
||||
callbackManager.commandRequest("meta", body.getFileKey(), meta);
|
||||
callbackManager.commandRequest("meta", dockey, meta);
|
||||
return "result ok";
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
@ -464,7 +462,7 @@ public class FileController {
|
||||
|
||||
@PostMapping("/reference")
|
||||
@ResponseBody
|
||||
public String reference(@RequestBody final Reference body) {
|
||||
public String reference(@RequestBody final JSONObject body) {
|
||||
try {
|
||||
JSONParser parser = new JSONParser();
|
||||
Gson gson = new GsonBuilder().disableHtmlEscaping().create();
|
||||
@ -472,11 +470,12 @@ public class FileController {
|
||||
String userAddress = "";
|
||||
String fileName = "";
|
||||
|
||||
if (body.getReferenceData() != null) {
|
||||
ReferenceData referenceData = body.getReferenceData();
|
||||
if (body.containsKey("referenceData")) {
|
||||
LinkedHashMap referenceDataObj = (LinkedHashMap) body.get("referenceData");
|
||||
String instanceId = (String) referenceDataObj.get("instanceId");
|
||||
|
||||
if (referenceData.getInstanceId().equals(storagePathBuilder.getServerUrl(false))) {
|
||||
JSONObject fileKey = (JSONObject) parser.parse(referenceData.getFileKey());
|
||||
if (instanceId.equals(storagePathBuilder.getServerUrl(false))) {
|
||||
JSONObject fileKey = (JSONObject) parser.parse((String) referenceDataObj.get("fileKey"));
|
||||
userAddress = (String) fileKey.get("userAddress");
|
||||
if (userAddress.equals(InetAddress.getLocalHost().getHostAddress())) {
|
||||
fileName = (String) fileKey.get("fileName");
|
||||
@ -487,7 +486,7 @@ public class FileController {
|
||||
|
||||
if (fileName.equals("")) {
|
||||
try {
|
||||
String path = (String) body.getPath();
|
||||
String path = (String) body.get("path");
|
||||
path = fileUtility.getFileName(path);
|
||||
File f = new File(storagePathBuilder.getFileLocation(path));
|
||||
if (f.exists()) {
|
||||
@ -502,6 +501,8 @@ public class FileController {
|
||||
return "{ \"error\": \"File not found\"}";
|
||||
}
|
||||
|
||||
boolean directUrl = (boolean) body.get("directUrl");
|
||||
|
||||
HashMap<String, Object> fileKey = new HashMap<>();
|
||||
fileKey.put("fileName", fileName);
|
||||
fileKey.put("userAddress", InetAddress.getLocalHost().getHostAddress());
|
||||
@ -513,7 +514,7 @@ public class FileController {
|
||||
HashMap<String, Object> data = new HashMap<>();
|
||||
data.put("fileType", fileUtility.getFileExtension(fileName).replace(".", ""));
|
||||
data.put("url", documentManager.getDownloadUrl(fileName, true));
|
||||
data.put("directUrl", body.getDirectUrl() ? documentManager.getDownloadUrl(fileName, false) : null);
|
||||
data.put("directUrl", directUrl ? documentManager.getDownloadUrl(fileName, false) : null);
|
||||
data.put("referenceData", referenceData);
|
||||
data.put("path", fileName);
|
||||
|
||||
@ -527,101 +528,4 @@ public class FileController {
|
||||
return "{ \"error\" : 1, \"message\" : \"" + e.getMessage() + "\"}";
|
||||
}
|
||||
}
|
||||
|
||||
@GetMapping("/history")
|
||||
@ResponseBody
|
||||
public String history(@RequestParam("fileName") final String fileName) {
|
||||
return historyManager.getHistory(fileName);
|
||||
}
|
||||
|
||||
@GetMapping("/historydata")
|
||||
@ResponseBody
|
||||
public String history(@RequestParam("fileName") final String fileName,
|
||||
@RequestParam("version") final String version,
|
||||
@RequestParam(value = "directUrl", defaultValue = "false") final Boolean directUrl) {
|
||||
return historyManager.getHistoryData(fileName, version, directUrl);
|
||||
}
|
||||
|
||||
@PutMapping("/restore")
|
||||
@ResponseBody
|
||||
public String restore(@RequestBody final Restore body, @CookieValue("uid") final Integer uid) {
|
||||
try {
|
||||
String sourceStringFile = storagePathBuilder.getFileLocation(body.getFileName());
|
||||
File sourceFile = new File(sourceStringFile);
|
||||
Path sourcePathFile = sourceFile.toPath();
|
||||
String historyDirectory = storagePathBuilder.getHistoryDir(sourcePathFile.toString());
|
||||
|
||||
Integer bumpedVersion = storagePathBuilder.getFileVersion(historyDirectory, false);
|
||||
String bumpedVersionStringDirectory = documentManager.versionDir(historyDirectory, bumpedVersion, true);
|
||||
File bumpedVersionDirectory = new File(bumpedVersionStringDirectory);
|
||||
if (!bumpedVersionDirectory.exists()) {
|
||||
bumpedVersionDirectory.mkdir();
|
||||
}
|
||||
|
||||
Path bumpedKeyPathFile = Paths.get(bumpedVersionStringDirectory, "key.txt");
|
||||
String bumpedKeyStringFile = bumpedKeyPathFile.toString();
|
||||
File bumpedKeyFile = new File(bumpedKeyStringFile);
|
||||
String bumpedKey = serviceConverter.generateRevisionId(
|
||||
storagePathBuilder.getStorageLocation()
|
||||
+ "/"
|
||||
+ body.getFileName()
|
||||
+ "/"
|
||||
+ Long.toString(sourceFile.lastModified())
|
||||
);
|
||||
FileWriter bumpedKeyFileWriter = new FileWriter(bumpedKeyFile);
|
||||
bumpedKeyFileWriter.write(bumpedKey);
|
||||
bumpedKeyFileWriter.close();
|
||||
|
||||
User user = userService.findUserById(uid).get();
|
||||
|
||||
Path bumpedChangesPathFile = Paths.get(bumpedVersionStringDirectory, "changes.json");
|
||||
String bumpedChangesStringFile = bumpedChangesPathFile.toString();
|
||||
File bumpedChangesFile = new File(bumpedChangesStringFile);
|
||||
JSONObject bumpedChangesUser = new JSONObject();
|
||||
// Don't add the `uid-` prefix.
|
||||
// https://github.com/ONLYOFFICE/document-server-integration/issues/437#issuecomment-1663526562
|
||||
bumpedChangesUser.put("id", user.getId());
|
||||
bumpedChangesUser.put("name", user.getName());
|
||||
JSONObject bumpedChangesChangesItem = new JSONObject();
|
||||
bumpedChangesChangesItem.put("created", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
|
||||
bumpedChangesChangesItem.put("user", bumpedChangesUser);
|
||||
JSONArray bumpedChangesChanges = new JSONArray();
|
||||
bumpedChangesChanges.add(bumpedChangesChangesItem);
|
||||
JSONObject bumpedChanges = new JSONObject();
|
||||
bumpedChanges.put("serverVersion", null);
|
||||
bumpedChanges.put("changes", bumpedChangesChanges);
|
||||
String bumpedChangesContent = bumpedChanges.toJSONString();
|
||||
FileWriter bumpedChangesFileWriter = new FileWriter(bumpedChangesFile);
|
||||
bumpedChangesFileWriter.write(bumpedChangesContent);
|
||||
bumpedChangesFileWriter.close();
|
||||
|
||||
String sourceExtension = fileUtility.getFileExtension(body.getFileName());
|
||||
String previousBasename = "prev" + sourceExtension;
|
||||
|
||||
Path bumpedFile = Paths.get(bumpedVersionStringDirectory, previousBasename);
|
||||
Files.move(sourcePathFile, bumpedFile);
|
||||
|
||||
String recoveryVersionStringDirectory = documentManager.versionDir(
|
||||
historyDirectory,
|
||||
body.getVersion(),
|
||||
true
|
||||
);
|
||||
Path recoveryPathFile = Paths.get(recoveryVersionStringDirectory, previousBasename);
|
||||
String recoveryStringFile = recoveryPathFile.toString();
|
||||
FileInputStream recoveryStream = new FileInputStream(recoveryStringFile);
|
||||
storageMutator.createFile(sourcePathFile, recoveryStream);
|
||||
recoveryStream.close();
|
||||
|
||||
JSONObject responseBody = new JSONObject();
|
||||
responseBody.put("error", null);
|
||||
responseBody.put("success", true);
|
||||
return responseBody.toJSONString();
|
||||
} catch (Exception error) {
|
||||
error.printStackTrace();
|
||||
JSONObject responseBody = new JSONObject();
|
||||
responseBody.put("error", error.getMessage());
|
||||
responseBody.put("success", false);
|
||||
return responseBody.toJSONString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -217,14 +217,8 @@ public class DefaultDocumentManager implements DocumentManager {
|
||||
public String createDemo(final String fileExt, final Boolean sample, final String uid, final String uname) {
|
||||
String demoName = (sample ? "sample." : "new.")
|
||||
+ fileExt; // create sample or new template file with the necessary extension
|
||||
String demoPath =
|
||||
"assets"
|
||||
+ File.separator
|
||||
+ "document-templates"
|
||||
+ File.separator
|
||||
+ (sample ? "sample" : "new")
|
||||
+ File.separator
|
||||
+ demoName;
|
||||
String demoPath = "assets" + File.separator + (sample ? "sample" : "new")
|
||||
+ File.separator + demoName; // get the path to the sample document
|
||||
|
||||
// get a file name with an index if the file with such a name already exists
|
||||
String fileName = getCorrectName(demoName);
|
||||
|
||||
@ -25,7 +25,6 @@ import com.onlyoffice.integration.documentserver.managers.jwt.JwtManager;
|
||||
import com.onlyoffice.integration.documentserver.models.filemodel.Document;
|
||||
import com.onlyoffice.integration.documentserver.storage.FileStoragePathBuilder;
|
||||
import com.onlyoffice.integration.documentserver.util.file.FileUtility;
|
||||
import com.onlyoffice.integration.documentserver.util.service.ServiceConverter;
|
||||
import lombok.SneakyThrows;
|
||||
import org.json.simple.JSONArray;
|
||||
import org.json.simple.JSONObject;
|
||||
@ -63,9 +62,6 @@ public class DefaultHistoryManager implements HistoryManager {
|
||||
@Autowired
|
||||
private ObjectMapper objectMapper;
|
||||
|
||||
@Autowired
|
||||
private ServiceConverter serviceConverter;
|
||||
|
||||
// todo: Refactoring
|
||||
@SneakyThrows
|
||||
public String[] getHistory(final Document document) { // get document history
|
||||
@ -168,153 +164,6 @@ public class DefaultHistoryManager implements HistoryManager {
|
||||
return new String[]{"", ""};
|
||||
}
|
||||
|
||||
// todo: Refactoring
|
||||
@SneakyThrows
|
||||
public String getHistory(final String fileName) { // get document history
|
||||
|
||||
// get history directory
|
||||
String histDir = storagePathBuilder.getHistoryDir(storagePathBuilder.getFileLocation(fileName));
|
||||
Integer curVer = storagePathBuilder.getFileVersion(histDir, false); // get current file version
|
||||
|
||||
if (curVer > 0) { // check if the current file version is greater than 0
|
||||
List<Object> hist = new ArrayList<>();
|
||||
|
||||
for (Integer i = 1; i <= curVer; i++) { // run through all the file versions
|
||||
Map<String, Object> obj = new HashMap<String, Object>();
|
||||
String verDir = documentManager
|
||||
.versionDir(histDir, i, true); // get the path to the given file version
|
||||
|
||||
String key;
|
||||
if (i == curVer) {
|
||||
key = serviceConverter
|
||||
.generateRevisionId(storagePathBuilder.getStorageLocation()
|
||||
+ "/" + fileName + "/"
|
||||
+ new File(storagePathBuilder.getFileLocation(fileName)).lastModified());
|
||||
} else {
|
||||
key = readFileToEnd(new File(verDir + File.separator + "key.txt"));
|
||||
}
|
||||
|
||||
obj.put("key", key);
|
||||
obj.put("version", i);
|
||||
|
||||
if (i == 1) { // check if the version number is equal to 1
|
||||
String createdInfo = readFileToEnd(new File(histDir
|
||||
+ File.separator + "createdInfo.json")); // get file with meta data
|
||||
JSONObject json = (JSONObject) parser.parse(createdInfo); // and turn it into json object
|
||||
|
||||
// write meta information to the object (user information and creation date)
|
||||
obj.put("created", json.get("created"));
|
||||
Map<String, Object> user = new HashMap<String, Object>();
|
||||
user.put("id", json.get("id"));
|
||||
user.put("name", json.get("name"));
|
||||
obj.put("user", user);
|
||||
}
|
||||
|
||||
if (i > 1) { //check if the version number is greater than 1
|
||||
// if so, get the path to the changes.json file
|
||||
JSONObject changes = (JSONObject) parser.parse(readFileToEnd(new File(documentManager
|
||||
.versionDir(histDir, i - 1, true) + File.separator + "changes.json")));
|
||||
JSONObject change = (JSONObject) ((JSONArray) changes.get("changes")).get(0);
|
||||
|
||||
// write information about changes to the object
|
||||
obj.put("changes", changes.get("changes"));
|
||||
obj.put("serverVersion", changes.get("serverVersion"));
|
||||
obj.put("created", change.get("created"));
|
||||
obj.put("user", change.get("user"));
|
||||
}
|
||||
|
||||
hist.add(obj);
|
||||
}
|
||||
|
||||
// write history information about the current file version to the history object
|
||||
Map<String, Object> histObj = new HashMap<String, Object>();
|
||||
histObj.put("currentVersion", curVer);
|
||||
histObj.put("history", hist);
|
||||
|
||||
try {
|
||||
return objectMapper.writeValueAsString(histObj);
|
||||
} catch (JsonProcessingException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
// todo: Refactoring
|
||||
@SneakyThrows
|
||||
public String getHistoryData(final String fileName, final String version, final Boolean directUrl) {
|
||||
// get history directory
|
||||
String histDir = storagePathBuilder.getHistoryDir(storagePathBuilder.getFileLocation(fileName));
|
||||
Integer curVer = storagePathBuilder.getFileVersion(histDir, false); // get current file version
|
||||
|
||||
if (curVer > 0) { // check if the current file version is greater than 0
|
||||
Map<String, Object> histData = new HashMap<>();
|
||||
|
||||
for (Integer i = 1; i <= curVer; i++) { // run through all the file versions
|
||||
Map<String, Object> dataObj = new HashMap<String, Object>();
|
||||
String verDir = documentManager
|
||||
.versionDir(histDir, i, true); // get the path to the given file version
|
||||
|
||||
String key;
|
||||
if (i == curVer) {
|
||||
key = serviceConverter
|
||||
.generateRevisionId(storagePathBuilder.getStorageLocation()
|
||||
+ "/" + fileName + "/"
|
||||
+ new File(storagePathBuilder.getFileLocation(fileName)).lastModified());
|
||||
} else {
|
||||
key = readFileToEnd(new File(verDir + File.separator + "key.txt"));
|
||||
}
|
||||
|
||||
dataObj.put("fileType", fileUtility
|
||||
.getFileExtension(fileName).replace(".", ""));
|
||||
dataObj.put("key", key);
|
||||
dataObj.put("url", i == curVer ? documentManager.getDownloadUrl(fileName, true)
|
||||
: documentManager.getHistoryFileUrl(fileName, i, "prev" + fileUtility
|
||||
.getFileExtension(fileName), true));
|
||||
if (directUrl) {
|
||||
dataObj.put("directUrl", i == curVer
|
||||
? documentManager.getDownloadUrl(fileName, false)
|
||||
: documentManager.getHistoryFileUrl(fileName, i, "prev" + fileUtility
|
||||
.getFileExtension(fileName), false));
|
||||
}
|
||||
dataObj.put("version", i);
|
||||
|
||||
if (i > 1) { //check if the version number is greater than 1
|
||||
// get the history data from the previous file version
|
||||
Map<String, Object> prev = (Map<String, Object>) histData.get(Integer.toString(i - 1));
|
||||
Map<String, Object> prevInfo = new HashMap<String, Object>();
|
||||
prevInfo.put("fileType", prev.get("fileType"));
|
||||
prevInfo.put("key", prev.get("key")); // write key and URL information about previous file version
|
||||
prevInfo.put("url", prev.get("url"));
|
||||
if (directUrl) {
|
||||
prevInfo.put("directUrl", prev.get("directUrl"));
|
||||
}
|
||||
|
||||
// write information about previous file version to the data object
|
||||
dataObj.put("previous", prevInfo);
|
||||
// write the path to the diff.zip archive with differences in this file version
|
||||
Integer verdiff = i - 1;
|
||||
dataObj.put("changesUrl", documentManager
|
||||
.getHistoryFileUrl(fileName, verdiff, "diff.zip", true));
|
||||
}
|
||||
|
||||
if (jwtManager.tokenEnabled()) {
|
||||
dataObj.put("token", jwtManager.createToken(dataObj));
|
||||
}
|
||||
|
||||
histData.put(Integer.toString(i), dataObj);
|
||||
}
|
||||
|
||||
try {
|
||||
return objectMapper.writeValueAsString(histData.get(version));
|
||||
} catch (JsonProcessingException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
|
||||
// read a file
|
||||
private String readFileToEnd(final File file) {
|
||||
String output = "";
|
||||
|
||||
@ -18,9 +18,9 @@
|
||||
|
||||
package com.onlyoffice.integration.documentserver.managers.history;
|
||||
|
||||
import com.onlyoffice.integration.documentserver.models.filemodel.Document;
|
||||
|
||||
// specify the history manager functions
|
||||
public interface HistoryManager {
|
||||
String getHistory(String fileName); // get document history
|
||||
|
||||
String getHistoryData(String fileName, String version, Boolean directUrl); // get document history data
|
||||
String[] getHistory(Document document); // get document history
|
||||
}
|
||||
|
||||
@ -1,34 +0,0 @@
|
||||
/**
|
||||
*
|
||||
* (c) Copyright Ascensio System SIA 2023
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.onlyoffice.integration.dto;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class Reference {
|
||||
private Boolean directUrl;
|
||||
private ReferenceData referenceData;
|
||||
private String path;
|
||||
}
|
||||
@ -1,31 +0,0 @@
|
||||
/**
|
||||
*
|
||||
* (c) Copyright Ascensio System SIA 2023
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.onlyoffice.integration.dto;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class ReferenceData {
|
||||
private String fileKey;
|
||||
private String instanceId;
|
||||
}
|
||||
@ -1,34 +0,0 @@
|
||||
/**
|
||||
*
|
||||
* (c) Copyright Ascensio System SIA 2023
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.onlyoffice.integration.dto;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class Rename {
|
||||
private String fileName;
|
||||
private String fileKey;
|
||||
private String fileType;
|
||||
}
|
||||
@ -1,33 +0,0 @@
|
||||
/**
|
||||
*
|
||||
* (c) Copyright Ascensio System SIA 2023
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.onlyoffice.integration.dto;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class Restore {
|
||||
private String fileName;
|
||||
private Integer version;
|
||||
}
|
||||
@ -1,33 +0,0 @@
|
||||
/**
|
||||
*
|
||||
* (c) Copyright Ascensio System SIA 2023
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.onlyoffice.integration.dto;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class SaveAs {
|
||||
private String title;
|
||||
private String url;
|
||||
}
|
||||
@ -147,9 +147,9 @@
|
||||
|
||||
var newfilename = event.data;
|
||||
var data = {
|
||||
fileName: newfilename,
|
||||
fileKey: config.document.key,
|
||||
fileType: config.document.fileType
|
||||
newfilename: newfilename,
|
||||
dockey: config.document.key,
|
||||
ext: config.document.fileType
|
||||
};
|
||||
let xhr = new XMLHttpRequest();
|
||||
xhr.open("POST", "rename");
|
||||
@ -172,64 +172,6 @@
|
||||
}
|
||||
};
|
||||
|
||||
var onRequestHistory = function () {
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open("GET", "history?fileName=" + config.document.title, false);
|
||||
xhr.send();
|
||||
|
||||
if (xhr.status == 200) {
|
||||
var historyInfo = JSON.parse(xhr.responseText);
|
||||
docEditor.refreshHistory(historyInfo);
|
||||
}
|
||||
};
|
||||
|
||||
var onRequestHistoryData = function (event) {
|
||||
var version = event.data;
|
||||
var historyDataUri = "historydata?fileName=" + config.document.title
|
||||
+ "&version=" + version
|
||||
+ "&directUrl=" + !!config.document.directUrl;
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open("GET", historyDataUri, false);
|
||||
xhr.send();
|
||||
|
||||
if (xhr.status == 200) {
|
||||
var historyData = JSON.parse(xhr.responseText);
|
||||
docEditor.setHistoryData(historyData);
|
||||
}
|
||||
};
|
||||
|
||||
var onRequestHistoryClose = function() {
|
||||
document.location.reload();
|
||||
};
|
||||
|
||||
function onRequestRestore(event) {
|
||||
const query = new URLSearchParams(window.location.search)
|
||||
const payload = {
|
||||
fileName: query.get('fileName'),
|
||||
version: event.data.version
|
||||
}
|
||||
const request = new XMLHttpRequest()
|
||||
request.open('PUT', 'restore')
|
||||
request.setRequestHeader('Content-Type', 'application/json')
|
||||
request.send(JSON.stringify(payload))
|
||||
request.onload = function () {
|
||||
const response = JSON.parse(request.responseText);
|
||||
if (response.success && !response.error) {
|
||||
var historyInfoUri = "history?fileName=" + config.document.title;
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open("GET", historyInfoUri, false);
|
||||
xhr.send();
|
||||
|
||||
if (xhr.status == 200) {
|
||||
var historyInfo = JSON.parse(xhr.responseText);
|
||||
docEditor.refreshHistory(historyInfo);
|
||||
}
|
||||
} else {
|
||||
innerAlert(response.error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
config.width = "100%";
|
||||
config.height = "100%";
|
||||
config.events = {
|
||||
@ -242,15 +184,30 @@
|
||||
"onRequestInsertImage": onRequestInsertImage,
|
||||
"onRequestCompareFile": onRequestCompareFile,
|
||||
"onRequestMailMergeRecipients": onRequestMailMergeRecipients,
|
||||
"onRequestRestore": onRequestRestore,
|
||||
"onRequestHistory": onRequestHistory,
|
||||
"onRequestHistoryData": onRequestHistoryData,
|
||||
"onRequestHistoryClose": onRequestHistoryClose
|
||||
};
|
||||
|
||||
var histArray = [[${fileHistory}]];
|
||||
var hist = histArray[0];
|
||||
var historyData = histArray[1];
|
||||
var usersForMentions = [[${usersForMentions}]];
|
||||
|
||||
if (config.editorConfig.user.id != 4) {
|
||||
if (hist && historyData) {
|
||||
// the user is trying to show the document version history
|
||||
config.events['onRequestHistory'] = function () {
|
||||
docEditor.refreshHistory(JSON.parse(hist)); // show the document version history
|
||||
};
|
||||
// the user is trying to click the specific document version in the document version history
|
||||
config.events['onRequestHistoryData'] = function (event) {
|
||||
var ver = event.data;
|
||||
var histData = historyData;
|
||||
docEditor.setHistoryData(JSON.parse(histData)[ver - 1]); // send the link to the document for viewing the version history
|
||||
};
|
||||
// the user is trying to go back to the document from viewing the document version history
|
||||
config.events['onRequestHistoryClose'] = function () {
|
||||
document.location.reload();
|
||||
};
|
||||
}
|
||||
// add mentions for not anonymous users
|
||||
config.events['onRequestUsers'] = function () {
|
||||
docEditor.setUsers({ // set a list of users to mention in the comments
|
||||
|
||||
@ -140,7 +140,11 @@ See the detailed guide to learn how to [install Document Server for Linux](https
|
||||
|
||||
### Step 2. Install the prerequisites and run the website with the editors
|
||||
|
||||
1. Install **Java** following the instructions [here](https://docs.oracle.com/en/java/javase/20/install/installation-jdk-linux-platforms.html#GUID-737A84E4-2EFF-4D38-8E60-3E29D1B884B8).
|
||||
1. Install **Java**:
|
||||
|
||||
```
|
||||
sudo add-apt-repository ppa:webupd8team/java sudo apt-get update sudo apt-get install oracle-java8-installer
|
||||
```
|
||||
|
||||
2. Download the archive with the Java example and unpack the archive:
|
||||
|
||||
@ -237,39 +241,13 @@ Make sure that the Document Server has access to the server with the example ins
|
||||
|
||||
## For Docker
|
||||
|
||||
### Step 1. Install ONLYOFFICE Docs
|
||||
|
||||
Download and install ONLYOFFICE Docs (packaged as Document Server).
|
||||
|
||||
See the detailed guide to learn how to install Document Server [for Docker](https://helpcenter.onlyoffice.com/installation/docs-developer-install-docker.aspx).
|
||||
|
||||
### Step 2. Install the prerequisites and run the website with the editors
|
||||
|
||||
1. Install **Java** following the instructions [here](https://docs.oracle.com/en/java/javase/20/install/installation-jdk-linux-platforms.html#GUID-737A84E4-2EFF-4D38-8E60-3E29D1B884B8).
|
||||
|
||||
2. Download the archive with the Java example and unpack the archive:
|
||||
|
||||
```
|
||||
wget https://api.onlyoffice.com/app_data/editor/Java%20Example.zip
|
||||
```
|
||||
|
||||
```
|
||||
unzip Java\ Example.zip
|
||||
```
|
||||
|
||||
3. Change the current directory for the project directory:
|
||||
|
||||
```
|
||||
cd Java\ Example/
|
||||
```
|
||||
|
||||
4. Edit the *settings.properties* configuration file. Specify the name of your local server with the ONLYOFFICE Document Server installed:
|
||||
1. Edit the *settings.properties* configuration file. Specify the name of your local server with the ONLYOFFICE Document Server installed ([installation instructions](https://helpcenter.onlyoffice.com/installation/docs-developer-install-docker.aspx)).
|
||||
|
||||
```
|
||||
nano src/main/resources/settings.properties
|
||||
```
|
||||
|
||||
5. Edit the following lines:
|
||||
2. Edit the following lines:
|
||||
|
||||
```
|
||||
storage-folder = app_data
|
||||
@ -278,19 +256,13 @@ See the detailed guide to learn how to install Document Server [for Docker](http
|
||||
|
||||
where the **documentserver** is the name of the server with the ONLYOFFICE Document Server installed and the **storage-folder** is the path where files will be created and stored.
|
||||
|
||||
6. Run the next command in the Java example directory:
|
||||
3. Run the next command in the Java example directory:
|
||||
|
||||
```
|
||||
docker-compose up
|
||||
```
|
||||
|
||||
7. After it, all the *bin* files will be passed to the *./target* folder.
|
||||
|
||||
### Step 3. Check accessibility
|
||||
|
||||
In case the example and Document Server are installed on different computers, make sure that your server with the example installed has access to the Document Server with the address which you specify instead of **documentserver** in the configuration files.
|
||||
|
||||
Make sure that the Document Server has access to the server with the example installed with the address which you specify instead of **example.com** in the configuration files.
|
||||
4. After it, all the *bin* files will be passed to the *./target* folder.
|
||||
|
||||
## Important security info
|
||||
|
||||
|
||||
@ -48,7 +48,6 @@ import java.io.BufferedInputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.PrintWriter;
|
||||
@ -58,11 +57,8 @@ import java.net.URL;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Scanner;
|
||||
|
||||
@ -130,15 +126,6 @@ public class IndexServlet extends HttpServlet {
|
||||
case "reference":
|
||||
reference(request, response, writer);
|
||||
break;
|
||||
case "restore":
|
||||
restore(request, response, writer);
|
||||
break;
|
||||
case "history":
|
||||
history(request, response, writer);
|
||||
break;
|
||||
case "historydata":
|
||||
historyData(request, response, writer);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -464,7 +451,7 @@ public class IndexServlet extends HttpServlet {
|
||||
private static void csv(final HttpServletRequest request,
|
||||
final HttpServletResponse response,
|
||||
final PrintWriter writer) {
|
||||
String fileName = "assets/document-templates/sample/csv.csv";
|
||||
String fileName = "assets/sample/csv.csv";
|
||||
URL fileUrl = Thread.currentThread().getContextClassLoader().getResource(fileName);
|
||||
Path filePath = null;
|
||||
try {
|
||||
@ -479,7 +466,7 @@ public class IndexServlet extends HttpServlet {
|
||||
private static void assets(final HttpServletRequest request,
|
||||
final HttpServletResponse response,
|
||||
final PrintWriter writer) {
|
||||
String fileName = "assets/document-templates/sample/" + FileUtility.getFileName(request.getParameter("name"));
|
||||
String fileName = "assets/sample/" + FileUtility.getFileName(request.getParameter("name"));
|
||||
URL fileUrl = Thread.currentThread().getContextClassLoader().getResource(fileName);
|
||||
Path filePath = null;
|
||||
try {
|
||||
@ -741,267 +728,6 @@ public class IndexServlet extends HttpServlet {
|
||||
}
|
||||
}
|
||||
|
||||
private static void restore(final HttpServletRequest request,
|
||||
final HttpServletResponse response,
|
||||
final PrintWriter writer) {
|
||||
try {
|
||||
Scanner scanner = new Scanner(request.getInputStream());
|
||||
scanner.useDelimiter("\\A");
|
||||
String bodyString = scanner.hasNext() ? scanner.next() : "";
|
||||
scanner.close();
|
||||
|
||||
JSONParser parser = new JSONParser();
|
||||
JSONObject body = (JSONObject) parser.parse(bodyString);
|
||||
|
||||
String sourceBasename = (String) body.get("fileName");
|
||||
Integer version = ((Long) body.get("version")).intValue();
|
||||
String userID = (String) body.get("userId");
|
||||
|
||||
String sourceStringFile = DocumentManager.storagePath(sourceBasename, null);
|
||||
File sourceFile = new File(sourceStringFile);
|
||||
Path sourcePathFile = sourceFile.toPath();
|
||||
String historyDirectory = DocumentManager.historyDir(sourceStringFile);
|
||||
|
||||
Integer bumpedVersion = DocumentManager.getFileVersion(historyDirectory);
|
||||
String bumpedVersionStringDirectory = DocumentManager.versionDir(historyDirectory, bumpedVersion);
|
||||
File bumpedVersionDirectory = new File(bumpedVersionStringDirectory);
|
||||
if (!bumpedVersionDirectory.exists()) {
|
||||
bumpedVersionDirectory.mkdir();
|
||||
}
|
||||
|
||||
Path bumpedKeyPathFile = Paths.get(bumpedVersionStringDirectory, "key.txt");
|
||||
String bumpedKeyStringFile = bumpedKeyPathFile.toString();
|
||||
File bumpedKeyFile = new File(bumpedKeyStringFile);
|
||||
String bumpedKey = ServiceConverter.generateRevisionId(
|
||||
DocumentManager.curUserHostAddress(null)
|
||||
+ "/"
|
||||
+ sourceBasename
|
||||
+ "/"
|
||||
+ Long.toString(sourceFile.lastModified())
|
||||
);
|
||||
FileWriter bumpedKeyFileWriter = new FileWriter(bumpedKeyFile);
|
||||
bumpedKeyFileWriter.write(bumpedKey);
|
||||
bumpedKeyFileWriter.close();
|
||||
|
||||
User user = Users.getUser(userID);
|
||||
|
||||
Path bumpedChangesPathFile = Paths.get(bumpedVersionStringDirectory, "changes.json");
|
||||
String bumpedChangesStringFile = bumpedChangesPathFile.toString();
|
||||
File bumpedChangesFile = new File(bumpedChangesStringFile);
|
||||
JSONObject bumpedChangesUser = new JSONObject();
|
||||
bumpedChangesUser.put("id", user.getId());
|
||||
bumpedChangesUser.put("name", user.getName());
|
||||
JSONObject bumpedChangesChangesItem = new JSONObject();
|
||||
bumpedChangesChangesItem.put("created", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
|
||||
bumpedChangesChangesItem.put("user", bumpedChangesUser);
|
||||
JSONArray bumpedChangesChanges = new JSONArray();
|
||||
bumpedChangesChanges.add(bumpedChangesChangesItem);
|
||||
JSONObject bumpedChanges = new JSONObject();
|
||||
bumpedChanges.put("serverVersion", null);
|
||||
bumpedChanges.put("changes", bumpedChangesChanges);
|
||||
String bumpedChangesContent = bumpedChanges.toJSONString();
|
||||
FileWriter bumpedChangesFileWriter = new FileWriter(bumpedChangesFile);
|
||||
bumpedChangesFileWriter.write(bumpedChangesContent);
|
||||
bumpedChangesFileWriter.close();
|
||||
|
||||
String sourceExtension = FileUtility.getFileExtension(sourceBasename);
|
||||
String previousBasename = "prev" + sourceExtension;
|
||||
|
||||
Path bumpedFile = Paths.get(bumpedVersionStringDirectory, previousBasename);
|
||||
Files.move(sourcePathFile, bumpedFile);
|
||||
|
||||
String recoveryVersionStringDirectory = DocumentManager.versionDir(historyDirectory, version);
|
||||
Path recoveryPathFile = Paths.get(recoveryVersionStringDirectory, previousBasename);
|
||||
String recoveryStringFile = recoveryPathFile.toString();
|
||||
FileInputStream recoveryStream = new FileInputStream(recoveryStringFile);
|
||||
DocumentManager.createFile(sourcePathFile, recoveryStream);
|
||||
recoveryStream.close();
|
||||
|
||||
JSONObject responseBody = new JSONObject();
|
||||
responseBody.put("error", null);
|
||||
responseBody.put("success", true);
|
||||
String responseContent = responseBody.toJSONString();
|
||||
writer.write(responseContent);
|
||||
} catch (Exception error) {
|
||||
error.printStackTrace();
|
||||
JSONObject responseBody = new JSONObject();
|
||||
responseBody.put("error", error.getMessage());
|
||||
responseBody.put("success", false);
|
||||
String responseContent = responseBody.toJSONString();
|
||||
writer.write(responseContent);
|
||||
}
|
||||
}
|
||||
|
||||
private static void history(final HttpServletRequest request,
|
||||
final HttpServletResponse response,
|
||||
final PrintWriter writer) {
|
||||
String fileName = FileUtility.getFileName(request.getParameter("filename"));
|
||||
String path = DocumentManager.storagePath(fileName, null);
|
||||
|
||||
JSONParser parser = new JSONParser();
|
||||
response.setContentType("application/json");
|
||||
|
||||
// get history directory
|
||||
String histDir = DocumentManager.historyDir(path);
|
||||
if (DocumentManager.getFileVersion(histDir) > 0) {
|
||||
|
||||
// get current file version if it is greater than 0
|
||||
Integer curVer = DocumentManager.getFileVersion(histDir);
|
||||
|
||||
List<Object> hist = new ArrayList<>();
|
||||
Map<String, Object> histData = new HashMap<String, Object>();
|
||||
|
||||
for (Integer i = 1; i <= curVer; i++) { // run through all the file versions
|
||||
Map<String, Object> obj = new HashMap<String, Object>();
|
||||
String verDir = DocumentManager.versionDir(histDir, i); // get the path to the given file version
|
||||
|
||||
try {
|
||||
String key = null;
|
||||
|
||||
// get document key
|
||||
if (i == curVer) {
|
||||
key = ServiceConverter.generateRevisionId(
|
||||
DocumentManager.curUserHostAddress(null) + "/" + fileName + "/"
|
||||
+ Long.toString(new File(DocumentManager.storagePath(fileName, null))
|
||||
.lastModified()));
|
||||
} else {
|
||||
key = DocumentManager.readFileToEnd(new File(verDir + File.separator + "key.txt"));
|
||||
}
|
||||
|
||||
obj.put("key", key);
|
||||
obj.put("version", i);
|
||||
|
||||
if (i == 1) { // check if the version number is equal to 1
|
||||
String createdInfo = DocumentManager.readFileToEnd(new File(histDir + File.separator
|
||||
+ "createdInfo.json")); // get file with meta data
|
||||
JSONObject json = (JSONObject) parser.parse(createdInfo); // and turn it into json object
|
||||
|
||||
// write meta information to the object (user information and creation date)
|
||||
obj.put("created", json.get("created"));
|
||||
Map<String, Object> user = new HashMap<String, Object>();
|
||||
user.put("id", json.get("id"));
|
||||
user.put("name", json.get("name"));
|
||||
obj.put("user", user);
|
||||
}
|
||||
|
||||
if (i > 1) { //check if the version number is greater than 1
|
||||
// if so, get the path to the changes.json file
|
||||
JSONObject changes = (JSONObject) parser.parse(
|
||||
DocumentManager.readFileToEnd(new File(DocumentManager
|
||||
.versionDir(histDir, i - 1) + File.separator + "changes.json")));
|
||||
JSONObject change = (JSONObject) ((JSONArray) changes.get("changes")).get(0);
|
||||
|
||||
// write information about changes to the object
|
||||
obj.put("changes", !change.isEmpty() ? changes.get("changes") : null);
|
||||
obj.put("serverVersion", changes.get("serverVersion"));
|
||||
obj.put("created", !change.isEmpty() ? change.get("created") : null);
|
||||
obj.put("user", !change.isEmpty() ? change.get("user") : null);
|
||||
}
|
||||
|
||||
hist.add(obj);
|
||||
} catch (Exception ex) { }
|
||||
}
|
||||
|
||||
// write history information about the current file version to the history object
|
||||
Map<String, Object> histObj = new HashMap<String, Object>();
|
||||
histObj.put("currentVersion", curVer);
|
||||
histObj.put("history", hist);
|
||||
|
||||
Gson gson = new Gson();
|
||||
writer.write(gson.toJson(histObj));
|
||||
return;
|
||||
}
|
||||
writer.write("{}");
|
||||
}
|
||||
|
||||
private static void historyData(final HttpServletRequest request,
|
||||
final HttpServletResponse response,
|
||||
final PrintWriter writer) {
|
||||
String fileName = FileUtility.getFileName(request.getParameter("filename"));
|
||||
String version = request.getParameter("version");
|
||||
String directUrl = request.getParameter("directUrl");
|
||||
String path = DocumentManager.storagePath(fileName, null);
|
||||
|
||||
response.setContentType("application/json");
|
||||
// get history directory
|
||||
String histDir = DocumentManager.historyDir(path);
|
||||
if (DocumentManager.getFileVersion(histDir) > 0) {
|
||||
// get current file version if it is greater than 0
|
||||
Integer curVer = DocumentManager.getFileVersion(histDir);
|
||||
|
||||
Map<String, Object> histData = new HashMap<String, Object>();
|
||||
for (Integer i = 1; i <= curVer; i++) { // run through all the file versions
|
||||
Map<String, Object> dataObj = new HashMap<String, Object>();
|
||||
String verDir = DocumentManager.versionDir(histDir, i); // get the path to the given file version
|
||||
|
||||
try {
|
||||
String key = null;
|
||||
|
||||
// get document key
|
||||
if (i == curVer) {
|
||||
key = ServiceConverter.generateRevisionId(
|
||||
DocumentManager.curUserHostAddress(null) + "/" + fileName + "/"
|
||||
+ Long.toString(new File(DocumentManager.storagePath(fileName, null))
|
||||
.lastModified()));
|
||||
} else {
|
||||
key = DocumentManager.readFileToEnd(new File(verDir + File.separator + "key.txt"));
|
||||
}
|
||||
|
||||
dataObj.put("fileType", FileUtility.getFileExtension(fileName).substring(1));
|
||||
dataObj.put("key", key);
|
||||
dataObj.put("url", i == curVer
|
||||
? DocumentManager.getDownloadUrl(fileName, true)
|
||||
: DocumentManager.getDownloadHistoryUrl(fileName, i, "prev" + FileUtility
|
||||
.getFileExtension(fileName), true));
|
||||
if (directUrl.equals("true")) {
|
||||
dataObj.put("directUrl", i == curVer
|
||||
? DocumentManager.getDownloadUrl(fileName, false)
|
||||
: DocumentManager.getDownloadHistoryUrl(fileName, i, "prev" + FileUtility
|
||||
.getFileExtension(fileName), false));
|
||||
}
|
||||
|
||||
dataObj.put("version", i);
|
||||
|
||||
if (i > 1) { //check if the version number is greater than 1
|
||||
|
||||
// get the history data from the previous file version
|
||||
Map<String, Object> prev = (Map<String, Object>) histData.get(Integer.toString(i - 1));
|
||||
Map<String, Object> prevInfo = new HashMap<String, Object>();
|
||||
prevInfo.put("fileType", prev.get("fileType"));
|
||||
|
||||
// write key and url information about previous file version
|
||||
prevInfo.put("key", prev.get("key"));
|
||||
prevInfo.put("url", prev.get("url"));
|
||||
if (directUrl.equals("true")) {
|
||||
prevInfo.put("directUrl", prev.get("directUrl"));
|
||||
}
|
||||
|
||||
// write information about previous file version to the data object
|
||||
dataObj.put("previous", prevInfo);
|
||||
// write the path to the diff.zip archive with differences in this file version
|
||||
Integer verdiff = i - 1;
|
||||
String changesUrl = DocumentManager
|
||||
.getDownloadHistoryUrl(fileName, verdiff,
|
||||
"diff.zip", true);
|
||||
dataObj.put("changesUrl", changesUrl);
|
||||
}
|
||||
|
||||
if (DocumentManager.tokenEnabled()) {
|
||||
dataObj.put("token", DocumentManager.createToken(dataObj));
|
||||
}
|
||||
|
||||
histData.put(Integer.toString(i), dataObj);
|
||||
|
||||
} catch (Exception ex) { }
|
||||
}
|
||||
|
||||
Gson gson = new Gson();
|
||||
writer.write(gson.toJson(histData.get(version)));
|
||||
return;
|
||||
}
|
||||
writer.write("{}");
|
||||
}
|
||||
|
||||
// process get request
|
||||
@Override
|
||||
protected void doGet(final HttpServletRequest request,
|
||||
@ -1016,12 +742,6 @@ public class IndexServlet extends HttpServlet {
|
||||
processRequest(request, response);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doPut(final HttpServletRequest request,
|
||||
final HttpServletResponse response) throws ServletException, IOException {
|
||||
processRequest(request, response);
|
||||
}
|
||||
|
||||
// get servlet information
|
||||
@Override
|
||||
public String getServletInfo() {
|
||||
|
||||
@ -23,8 +23,12 @@ import com.google.gson.reflect.TypeToken;
|
||||
import helpers.DocumentManager;
|
||||
import helpers.FileUtility;
|
||||
import helpers.ServiceConverter;
|
||||
import org.json.simple.JSONArray;
|
||||
import org.json.simple.JSONObject;
|
||||
import org.json.simple.parser.JSONParser;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
@ -32,6 +36,7 @@ import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Scanner;
|
||||
|
||||
public class FileModel {
|
||||
private String type = "desktop";
|
||||
@ -187,6 +192,128 @@ public class FileModel {
|
||||
token = DocumentManager.createToken(map);
|
||||
}
|
||||
|
||||
// get document history
|
||||
public String[] getHistory() {
|
||||
JSONParser parser = new JSONParser();
|
||||
|
||||
// get history directory
|
||||
String histDir = DocumentManager.historyDir(DocumentManager.storagePath(document.getTitle(), null));
|
||||
if (DocumentManager.getFileVersion(histDir) > 0) {
|
||||
|
||||
// get current file version if it is greater than 0
|
||||
Integer curVer = DocumentManager.getFileVersion(histDir);
|
||||
|
||||
List<Object> hist = new ArrayList<>();
|
||||
Map<String, Object> histData = new HashMap<String, Object>();
|
||||
|
||||
for (Integer i = 1; i <= curVer; i++) { // run through all the file versions
|
||||
Map<String, Object> obj = new HashMap<String, Object>();
|
||||
Map<String, Object> dataObj = new HashMap<String, Object>();
|
||||
String verDir = DocumentManager.versionDir(histDir, i); // get the path to the given file version
|
||||
|
||||
try {
|
||||
String key = null;
|
||||
|
||||
// get document key
|
||||
key = i == curVer
|
||||
? document.getKey() : readFileToEnd(new File(verDir + File.separator + "key.txt"));
|
||||
|
||||
obj.put("key", key);
|
||||
obj.put("version", i);
|
||||
|
||||
if (i == 1) { // check if the version number is equal to 1
|
||||
String createdInfo = readFileToEnd(new File(histDir + File.separator
|
||||
+ "createdInfo.json")); // get file with meta data
|
||||
JSONObject json = (JSONObject) parser.parse(createdInfo); // and turn it into json object
|
||||
|
||||
// write meta information to the object (user information and creation date)
|
||||
obj.put("created", json.get("created"));
|
||||
Map<String, Object> user = new HashMap<String, Object>();
|
||||
user.put("id", json.get("id"));
|
||||
user.put("name", json.get("name"));
|
||||
obj.put("user", user);
|
||||
}
|
||||
|
||||
dataObj.put("fileType", FileUtility.getFileExtension(document.getTitle()).substring(1));
|
||||
dataObj.put("key", key);
|
||||
dataObj.put("url", i == curVer ? document.getUrl() : DocumentManager
|
||||
.getDownloadHistoryUrl(document.getTitle(), i, "prev" + FileUtility
|
||||
.getFileExtension(document.getTitle()), true));
|
||||
if (!document.getDirectUrl().equals("")) {
|
||||
dataObj.put("directUrl", i == curVer ? document.getUrl() : DocumentManager
|
||||
.getDownloadHistoryUrl(document.getTitle(), i, "prev" + FileUtility
|
||||
.getFileExtension(document.getTitle()), false));
|
||||
}
|
||||
dataObj.put("version", i);
|
||||
|
||||
if (i > 1) { //check if the version number is greater than 1
|
||||
// if so, get the path to the changes.json file
|
||||
JSONObject changes = (JSONObject) parser.parse(readFileToEnd(new File(DocumentManager
|
||||
.versionDir(histDir, i - 1) + File.separator + "changes.json")));
|
||||
JSONObject change = (JSONObject) ((JSONArray) changes.get("changes")).get(0);
|
||||
|
||||
// write information about changes to the object
|
||||
obj.put("changes", !change.isEmpty() ? changes.get("changes") : null);
|
||||
obj.put("serverVersion", changes.get("serverVersion"));
|
||||
obj.put("created", !change.isEmpty() ? change.get("created") : null);
|
||||
obj.put("user", !change.isEmpty() ? change.get("user") : null);
|
||||
|
||||
// get the history data from the previous file version
|
||||
Map<String, Object> prev = (Map<String, Object>) histData.get(Integer.toString(i - 2));
|
||||
Map<String, Object> prevInfo = new HashMap<String, Object>();
|
||||
prevInfo.put("fileType", prev.get("fileType"));
|
||||
|
||||
// write key and url information about previous file version
|
||||
prevInfo.put("key", prev.get("key"));
|
||||
prevInfo.put("url", prev.get("url"));
|
||||
|
||||
// write information about previous file version to the data object
|
||||
dataObj.put("previous", prevInfo);
|
||||
// write the path to the diff.zip archive with differences in this file version
|
||||
Integer verdiff = i - 1;
|
||||
String changesUrl = DocumentManager
|
||||
.getDownloadHistoryUrl(document.getTitle(), verdiff,
|
||||
"diff.zip", true);
|
||||
dataObj.put("changesUrl", changesUrl);
|
||||
}
|
||||
|
||||
if (DocumentManager.tokenEnabled()) {
|
||||
dataObj.put("token", DocumentManager.createToken(dataObj));
|
||||
}
|
||||
|
||||
hist.add(obj);
|
||||
histData.put(Integer.toString(i - 1), dataObj);
|
||||
|
||||
} catch (Exception ex) { }
|
||||
}
|
||||
|
||||
// write history information about the current file version to the history object
|
||||
Map<String, Object> histObj = new HashMap<String, Object>();
|
||||
histObj.put("currentVersion", curVer);
|
||||
histObj.put("history", hist);
|
||||
|
||||
Gson gson = new Gson();
|
||||
return new String[] {gson.toJson(histObj), gson.toJson(histData) };
|
||||
}
|
||||
return new String[] {"", "" };
|
||||
}
|
||||
|
||||
// read a file
|
||||
private String readFileToEnd(final File file) {
|
||||
String output = "";
|
||||
try {
|
||||
try (FileInputStream is = new FileInputStream(file)) {
|
||||
Scanner scanner = new Scanner(is); // read data from the source
|
||||
scanner.useDelimiter("\\A");
|
||||
while (scanner.hasNext()) {
|
||||
output += scanner.next();
|
||||
}
|
||||
scanner.close();
|
||||
}
|
||||
} catch (Exception e) { }
|
||||
return output;
|
||||
}
|
||||
|
||||
// the document parameters
|
||||
public class Document {
|
||||
private String title;
|
||||
|
||||
@ -31,7 +31,6 @@ import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.File;
|
||||
import java.io.FileFilter;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
@ -51,7 +50,6 @@ import java.util.Date;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Scanner;
|
||||
|
||||
import static utils.Constants.KILOBYTE_SIZE;
|
||||
import static utils.Constants.MAX_FILE_SIZE;
|
||||
@ -308,12 +306,7 @@ public final class DocumentManager {
|
||||
String demoName = (sample ? "sample." : "new.") + fileExt;
|
||||
|
||||
// get the path to the sample document
|
||||
String demoPath = "assets"
|
||||
+ File.separator
|
||||
+ "document-templates"
|
||||
+ File.separator
|
||||
+ (sample ? "sample" : "new")
|
||||
+ File.separator;
|
||||
String demoPath = "assets" + File.separator + (sample ? "sample" : "new") + File.separator;
|
||||
|
||||
// get a file name with an index if the file with such a name already exists
|
||||
String fileName = getCorrectName(demoName, null);
|
||||
@ -601,19 +594,4 @@ public final class DocumentManager {
|
||||
});
|
||||
return languages;
|
||||
}
|
||||
|
||||
public static String readFileToEnd(final File file) {
|
||||
String output = "";
|
||||
try {
|
||||
try (FileInputStream is = new FileInputStream(file)) {
|
||||
Scanner scanner = new Scanner(is); // read data from the source
|
||||
scanner.useDelimiter("\\A");
|
||||
while (scanner.hasNext()) {
|
||||
output += scanner.next();
|
||||
}
|
||||
scanner.close();
|
||||
}
|
||||
} catch (Exception e) { }
|
||||
return output;
|
||||
}
|
||||
}
|
||||
|
||||
@ -173,65 +173,6 @@
|
||||
}
|
||||
};
|
||||
|
||||
function onRequestRestore(event) {
|
||||
const query = new URLSearchParams(window.location.search)
|
||||
const payload = {
|
||||
fileName: query.get('fileName'),
|
||||
version: event.data.version,
|
||||
userId: config.editorConfig.user.id
|
||||
}
|
||||
const request = new XMLHttpRequest()
|
||||
request.open('PUT', 'IndexServlet?type=restore')
|
||||
request.send(JSON.stringify(payload))
|
||||
request.onload = function () {
|
||||
const response = JSON.parse(request.responseText);
|
||||
if (response.success && !response.error) {
|
||||
var historyInfoUri = "IndexServlet?type=history&filename=" + config.document.title;
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open("GET", historyInfoUri, false);
|
||||
xhr.send();
|
||||
|
||||
if (xhr.status == 200) {
|
||||
var historyInfo = JSON.parse(xhr.responseText);
|
||||
docEditor.refreshHistory(historyInfo);
|
||||
}
|
||||
} else {
|
||||
innerAlert(response.error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var onRequestHistory = function () {
|
||||
var historyInfoUri = "IndexServlet?type=history&filename=" + config.document.title;
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open("GET", historyInfoUri, false);
|
||||
xhr.send();
|
||||
|
||||
if (xhr.status == 200) {
|
||||
var historyInfo = JSON.parse(xhr.responseText);
|
||||
docEditor.refreshHistory(historyInfo);
|
||||
}
|
||||
};
|
||||
|
||||
var onRequestHistoryData = function (event) {
|
||||
var version = event.data;
|
||||
var historyDataUri = "IndexServlet?type=historyData&filename=" + config.document.title
|
||||
+ "&version=" + version
|
||||
+ "&directUrl=" + !!config.document.directUrl;
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open("GET", historyDataUri, false);
|
||||
xhr.send();
|
||||
|
||||
if (xhr.status == 200) {
|
||||
var historyData = JSON.parse(xhr.responseText);
|
||||
docEditor.setHistoryData(historyData);
|
||||
}
|
||||
};
|
||||
|
||||
var onRequestHistoryClose = function() {
|
||||
document.location.reload();
|
||||
};
|
||||
|
||||
config = JSON.parse('<%= FileModel.serialize(Model) %>');
|
||||
config.width = "100%";
|
||||
config.height = "100%";
|
||||
@ -245,17 +186,32 @@
|
||||
"onRequestInsertImage": onRequestInsertImage,
|
||||
"onRequestCompareFile": onRequestCompareFile,
|
||||
"onRequestMailMergeRecipients": onRequestMailMergeRecipients,
|
||||
"onRequestRestore": onRequestRestore,
|
||||
"onRequestHistory": onRequestHistory,
|
||||
"onRequestHistoryData": onRequestHistoryData,
|
||||
"onRequestHistoryClose": onRequestHistoryClose
|
||||
};
|
||||
|
||||
<%
|
||||
String[] histArray = Model.getHistory();
|
||||
String history = histArray[0];
|
||||
String historyData = histArray[1];
|
||||
String usersForMentions = (String) request.getAttribute("usersForMentions");
|
||||
%>
|
||||
|
||||
if (config.editorConfig.user.id) {
|
||||
<% if (!history.isEmpty() && !historyData.isEmpty()) { %>
|
||||
// the user is trying to show the document version history
|
||||
config.events['onRequestHistory'] = function () {
|
||||
docEditor.refreshHistory(<%= history %>); // show the document version history
|
||||
};
|
||||
// the user is trying to click the specific document version in the document version history
|
||||
config.events['onRequestHistoryData'] = function (event) {
|
||||
var ver = event.data;
|
||||
var histData = <%= historyData %>;
|
||||
docEditor.setHistoryData(histData[ver - 1]); // send the link to the document for viewing the version history
|
||||
};
|
||||
// the user is trying to go back to the document from viewing the document version history
|
||||
config.events['onRequestHistoryClose'] = function () {
|
||||
document.location.reload();
|
||||
};
|
||||
<% } %>
|
||||
// add mentions for not anonymous users
|
||||
config.events['onRequestUsers'] = function () {
|
||||
docEditor.setUsers({ // set a list of users to mention in the comments
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
/**
|
||||
/**
|
||||
*
|
||||
* (c) Copyright Ascensio System SIA 2023
|
||||
*
|
||||
@ -27,7 +27,6 @@ const jwt = require('jsonwebtoken');
|
||||
const config = require('config');
|
||||
const mime = require('mime');
|
||||
const urllib = require('urllib');
|
||||
const urlModule = require("url");
|
||||
const { emitWarning } = require('process');
|
||||
const DocManager = require('./helpers/docManager');
|
||||
const documentService = require('./helpers/documentService');
|
||||
@ -82,6 +81,14 @@ app.use((req, res, next) => {
|
||||
});
|
||||
|
||||
app.use(express.static(path.join(__dirname, 'public'))); // public directory
|
||||
// check if there are static files such as .js, .css files, images, samples and process them
|
||||
if (config.has('server.static')) {
|
||||
const staticContent = config.get('server.static');
|
||||
for (let i = 0; i < staticContent.length; i++) {
|
||||
const staticContentElem = staticContent[i];
|
||||
app.use(staticContentElem.name, express.static(staticContentElem.path, staticContentElem.options));
|
||||
}
|
||||
}
|
||||
app.use(favicon(`${__dirname}/public/images/favicon.ico`)); // use favicon
|
||||
|
||||
app.use(bodyParser.json()); // connect middleware that parses json
|
||||
@ -499,20 +506,6 @@ app.post('/reference', (req, res) => { // define a handler for renaming file
|
||||
}
|
||||
}
|
||||
|
||||
if (!fileName && !!req.body.link) {
|
||||
if (req.body.link.indexOf(req.DocManager.curUserHostAddress()) != -1) {
|
||||
result({ error: 'You do not have access to this site' });
|
||||
return;
|
||||
}
|
||||
|
||||
let urlObj = urlModule.parse(req.body.link, true);
|
||||
fileName = urlObj.query.fileName;
|
||||
if (!req.DocManager.existsSync(req.DocManager.storagePath(fileName, userAddress))) {
|
||||
result({ error: 'File is not exist' });
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!fileName && !!req.body.path) {
|
||||
const filePath = fileUtility.getFileName(req.body.path);
|
||||
|
||||
@ -528,14 +521,12 @@ app.post('/reference', (req, res) => { // define a handler for renaming file
|
||||
|
||||
const data = {
|
||||
fileType: fileUtility.getFileExtension(fileName).slice(1),
|
||||
key: req.DocManager.getKey(fileName),
|
||||
url: req.DocManager.getDownloadUrl(fileName, true),
|
||||
directUrl: req.body.directUrl ? req.DocManager.getDownloadUrl(fileName) : null,
|
||||
referenceData: {
|
||||
fileKey: JSON.stringify({ fileName, userAddress: req.DocManager.curUserHostAddress() }),
|
||||
instanceId: req.DocManager.getServerUrl(),
|
||||
},
|
||||
link: `${req.DocManager.getServerUrl()}/editor?fileName=${encodeURIComponent(fileName)}`,
|
||||
path: fileName,
|
||||
};
|
||||
|
||||
@ -558,16 +549,13 @@ app.put('/restore', (req, res) => { // define a handler for restore file version
|
||||
const filePath = req.DocManager.storagePath(fileName, userAddress);
|
||||
const historyPath = req.DocManager.historyPath(fileName, userAddress);
|
||||
const newVersion = req.DocManager.countVersion(historyPath) + 1;
|
||||
const versionPath = path.join(`${historyPath}`, `${version}`, `prev${fileUtility.getFileExtension(fileName)}`);
|
||||
const newVersionPath = path.join(`${historyPath}`, `${newVersion}`);
|
||||
const versionPath = `${historyPath}\\${version}\\prev${fileUtility.getFileExtension(fileName)}`;
|
||||
const newVersionPath = `${historyPath}\\${newVersion}`;
|
||||
|
||||
if (fileSystem.existsSync(versionPath)) {
|
||||
req.DocManager.createDirectory(newVersionPath);
|
||||
req.DocManager.copyFile(
|
||||
filePath,
|
||||
path.join(`${newVersionPath}`, `prev${fileUtility.getFileExtension(fileName)}`),
|
||||
);
|
||||
fileSystem.writeFileSync(path.join(`${newVersionPath}`, 'key.txt'), key);
|
||||
req.DocManager.copyFile(filePath, `${newVersionPath}\\prev${fileUtility.getFileExtension(fileName)}`);
|
||||
fileSystem.writeFileSync(`${newVersionPath}\\key.txt`, key);
|
||||
req.DocManager.copyFile(versionPath, filePath);
|
||||
result.success = true;
|
||||
} else {
|
||||
@ -694,6 +682,7 @@ app.post('/track', async (req, res) => { // define a handler for tracking file c
|
||||
try {
|
||||
const resp = documentService.getResponseUri(data);
|
||||
await callbackProcessSave(resp.uri, body, fileName, userAddress, fileName);
|
||||
return;
|
||||
} catch (ex) {
|
||||
console.log(ex);
|
||||
await callbackProcessSave(downloadUri, body, fileName, userAddress, newFileName);
|
||||
@ -722,22 +711,18 @@ app.post('/track', async (req, res) => { // define a handler for tracking file c
|
||||
|
||||
const downloadExt = `.${body.fileType}`;
|
||||
const isSubmitForm = body.forcesavetype === 3; // SubmitForm
|
||||
let correctName = fileName;
|
||||
let correctName = '';
|
||||
let forcesavePath = '';
|
||||
|
||||
if (isSubmitForm) {
|
||||
// new file
|
||||
if (newFileName) {
|
||||
correctName = req.DocManager.getCorrectName(
|
||||
`${fileUtility.getFileName(fileName, true)}-form${downloadExt}`,
|
||||
userAddress,
|
||||
);
|
||||
correctName = req.DocManager.getCorrectName(`${fileUtility.getFileName(fileName, true)}
|
||||
-form${downloadExt}`, userAddress);
|
||||
} else {
|
||||
const ext = fileUtility.getFileExtension(fileName);
|
||||
correctName = req.DocManager.getCorrectName(
|
||||
`${fileUtility.getFileName(fileName, true)}-form${ext}`,
|
||||
userAddress,
|
||||
);
|
||||
correctName = req.DocManager.getCorrectName(`${fileUtility.getFileName(fileName, true)}
|
||||
-form${ext}`, userAddress);
|
||||
}
|
||||
forcesavePath = req.DocManager.storagePath(correctName, userAddress);
|
||||
} else {
|
||||
@ -793,6 +778,7 @@ app.post('/track', async (req, res) => { // define a handler for tracking file c
|
||||
try {
|
||||
const resp = documentService.getResponseUri(data);
|
||||
await callbackProcessForceSave(resp.uri, body, fileName, userAddress, false);
|
||||
return;
|
||||
} catch (ex) {
|
||||
console.log(ex);
|
||||
await callbackProcessForceSave(downloadUri, body, fileName, userAddress, true);
|
||||
@ -961,7 +947,7 @@ app.get('/editor', (req, res) => { // define a handler for editing document
|
||||
if (!canEdit && mode === 'edit') {
|
||||
mode = 'view';
|
||||
}
|
||||
const submitForm = mode === 'fillForms' && userid === 'uid-1';
|
||||
const submitForm = mode === 'fillForms' && userid === 'uid-1' && !1;
|
||||
|
||||
// file config data
|
||||
const argss = {
|
||||
@ -1019,14 +1005,14 @@ app.get('/editor', (req, res) => { // define a handler for editing document
|
||||
url: `${req.DocManager.getServerUrl(true)}/images/logo.png`,
|
||||
directUrl: !userDirectUrl ? null : `${req.DocManager.getServerUrl()}/images/logo.png`,
|
||||
},
|
||||
dataDocument: {
|
||||
dataCompareFile: {
|
||||
fileType: 'docx',
|
||||
url: `${req.DocManager.getServerUrl(true)}/assets/document-templates/sample/sample.docx`,
|
||||
directUrl: !userDirectUrl
|
||||
? null
|
||||
: `${req.DocManager.getServerUrl()}/assets/document-templates/sample/sample.docx`,
|
||||
},
|
||||
dataSpreadsheet: {
|
||||
dataMailMergeRecipients: {
|
||||
fileType: 'csv',
|
||||
url: `${req.DocManager.getServerUrl(true)}/csv`,
|
||||
directUrl: !userDirectUrl ? null : `${req.DocManager.getServerUrl()}/csv`,
|
||||
@ -1051,13 +1037,13 @@ app.get('/editor', (req, res) => { // define a handler for editing document
|
||||
cfgSignatureSecret,
|
||||
{ expiresIn: cfgSignatureSecretExpiresIn },
|
||||
);
|
||||
argss.dataDocument.token = jwt.sign(
|
||||
argss.dataDocument,
|
||||
argss.dataCompareFile.token = jwt.sign(
|
||||
argss.dataCompareFile,
|
||||
cfgSignatureSecret,
|
||||
{ expiresIn: cfgSignatureSecretExpiresIn },
|
||||
);
|
||||
argss.dataSpreadsheet.token = jwt.sign(
|
||||
argss.dataSpreadsheet,
|
||||
argss.dataMailMergeRecipients.token = jwt.sign(
|
||||
argss.dataMailMergeRecipients,
|
||||
cfgSignatureSecret,
|
||||
{ expiresIn: cfgSignatureSecretExpiresIn },
|
||||
);
|
||||
|
||||
@ -26,6 +26,12 @@
|
||||
"storagePath": "/files",
|
||||
"maxFileSize": 1073741824,
|
||||
"mobileRegEx": "android|avantgo|playbook|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od|ad)|iris|kindle|lge |maemo|midp|mmp|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\\/|plucker|pocket|psp|symbian|treo|up\\.(browser|link)|vodafone|wap|windows (ce|phone)|xda|xiino",
|
||||
"static":[
|
||||
{
|
||||
"name": "/files",
|
||||
"path": "./files"
|
||||
}
|
||||
],
|
||||
"token": {
|
||||
"enable": false,
|
||||
"useforrequest": true,
|
||||
|
||||
@ -2,6 +2,12 @@
|
||||
"server": {
|
||||
"siteUrl": "/",
|
||||
"maxFileSize": 104857600,
|
||||
"storageFolder": "/var/lib/onlyoffice/documentserver-example/files"
|
||||
"storageFolder": "/var/lib/onlyoffice/documentserver-example/files",
|
||||
"static":[
|
||||
{
|
||||
"name": "/files",
|
||||
"path": "/var/lib/onlyoffice/documentserver-example/files"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,6 +1,13 @@
|
||||
{
|
||||
"server": {
|
||||
"siteUrl": "/",
|
||||
"maxFileSize": 104857600
|
||||
"maxFileSize": 104857600,
|
||||
"static":[
|
||||
{
|
||||
"name": "/files",
|
||||
"path": "./files",
|
||||
"options": {"maxAge": "7d"}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@ -389,14 +389,14 @@ DocManager.prototype.getTemplateImageUrl = function getTemplateImageUrl(fileType
|
||||
}
|
||||
|
||||
if (fileType === fileUtility.fileType.cell) { // for cell type
|
||||
return `${serverUrl}/images/file_xlsx.svg`;
|
||||
return `${path}/images/file_xlsx.svg`;
|
||||
}
|
||||
|
||||
if (fileType === fileUtility.fileType.slide) { // for slide type
|
||||
return `${serverUrl}/images/file_pptx.svg`;
|
||||
return `${path}/images/file_pptx.svg`;
|
||||
}
|
||||
|
||||
return `${serverUrl}/images/file_docx.svg`; // the default value
|
||||
return `${path}/images/file_docx.svg`; // the default value
|
||||
};
|
||||
|
||||
// get document key
|
||||
|
||||
@ -90,7 +90,9 @@ fileUtility.getFillExtensions = function getFillExtensions() {
|
||||
|
||||
fileUtility.getConvertExtensions = function getConvertExtensions() {
|
||||
return supportedFormats.filter(
|
||||
(format) => format.actions.includes('auto-convert'),
|
||||
(format) => (format.type === 'word' && format.convert.includes('docx'))
|
||||
|| (format.type === 'cell' && format.convert.includes('xlsx'))
|
||||
|| (format.type === 'slide' && format.convert.includes('pptx')),
|
||||
).reduce((extensions, format) => [...extensions, format.name], []);
|
||||
};
|
||||
|
||||
|
||||
@ -52,7 +52,7 @@ const descrUser1 = [
|
||||
'The file favorite state is undefined',
|
||||
'Can create files from templates using data from the editor',
|
||||
'Can see the information about all users',
|
||||
'Can submit forms',
|
||||
// "Can submit forms"
|
||||
];
|
||||
|
||||
const descrUser2 = [
|
||||
@ -62,7 +62,7 @@ const descrUser2 = [
|
||||
'This file is marked as favorite',
|
||||
'Can create new files from the editor',
|
||||
'Can see the information about users from Group2 and users who don’t belong to any group',
|
||||
'Can’t submit forms',
|
||||
// "Can’t submit forms"
|
||||
];
|
||||
|
||||
const descrUser3 = [
|
||||
@ -75,7 +75,7 @@ const descrUser3 = [
|
||||
'Can’t print the file',
|
||||
'Can create new files from the editor',
|
||||
'Can see the information about Group2 users',
|
||||
'Can’t submit forms',
|
||||
// "Can’t submit forms"
|
||||
];
|
||||
|
||||
const descrUser0 = [
|
||||
@ -91,7 +91,7 @@ const descrUser0 = [
|
||||
'Can\'t view chat',
|
||||
'Can\'t protect file',
|
||||
'View file without collaboration',
|
||||
'Can’t submit forms',
|
||||
// "Can’t submit forms"
|
||||
];
|
||||
|
||||
const users = [
|
||||
|
||||
@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "OnlineEditorsExampleNodeJS",
|
||||
"version": "1.6.0",
|
||||
"version": "4.1.0",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "OnlineEditorsExampleNodeJS",
|
||||
"version": "1.6.0",
|
||||
"version": "4.1.0",
|
||||
"license": "Apache",
|
||||
"dependencies": {
|
||||
"body-parser": "^1.19.0",
|
||||
|
||||
@ -172,21 +172,18 @@
|
||||
};
|
||||
|
||||
var onRequestInsertImage = function(event) { // the user is trying to insert an image by clicking the Image from Storage button
|
||||
var data = <%- JSON.stringify(dataInsertImage) %>;
|
||||
data.c = event.data.c;
|
||||
docEditor.insertImage(data); // insert an image into the file
|
||||
docEditor.insertImage({ // insert an image into the file
|
||||
"c": event.data.c,
|
||||
<%- JSON.stringify(dataInsertImage).substring(1, JSON.stringify(dataInsertImage).length - 1)%>
|
||||
})
|
||||
};
|
||||
|
||||
var onRequestSelectDocument = function() { // the user is trying to select document by clicking the Document from Storage button
|
||||
var data = <%- JSON.stringify(dataDocument) %>;
|
||||
data.c = event.data.c;
|
||||
docEditor.setRequestedDocument(data); // select a document
|
||||
var onRequestCompareFile = function() { // the user is trying to select document for comparing by clicking the Document from Storage button
|
||||
docEditor.setRevisedFile(<%- JSON.stringify(dataCompareFile) %>); // select a document for comparing
|
||||
};
|
||||
|
||||
var onRequestSelectSpreadsheet = function (event) { // the user is trying to select recipients data by clicking the Mail merge button
|
||||
var data = <%- JSON.stringify(dataSpreadsheet) %>;
|
||||
data.c = event.data.c;
|
||||
docEditor.setRequestedSpreadsheet(data); // insert recipient data for mail merge into the file
|
||||
var onRequestMailMergeRecipients = function (event) { // the user is trying to select recipients data by clicking the Mail merge button
|
||||
docEditor.setMailMergeRecipients(<%- JSON.stringify(dataMailMergeRecipients) %>); // insert recipient data for mail merge into the file
|
||||
};
|
||||
|
||||
var onRequestUsers = function (event) {
|
||||
@ -214,50 +211,26 @@
|
||||
innerAlert("onRequestSendNotify: " + data);
|
||||
};
|
||||
|
||||
var onRequestOpen = function(event) { // user open external data source
|
||||
innerAlert("onRequestOpen");
|
||||
var windowName = event.data.windowName;
|
||||
|
||||
requestReference(event.data, function (data) {
|
||||
if (data.error) {
|
||||
var winEditor = window.open("", windowName);
|
||||
winEditor.close();
|
||||
innerAlert(data.error, true);
|
||||
return;
|
||||
}
|
||||
|
||||
var link = data.link;
|
||||
window.open(link, windowName);
|
||||
});
|
||||
};
|
||||
|
||||
var onRequestReferenceData = function(event) { // user refresh external data source
|
||||
innerAlert("onRequestReferenceData");
|
||||
|
||||
requestReference(event.data, function (data) {
|
||||
docEditor.setReferenceData(data);
|
||||
});
|
||||
};
|
||||
|
||||
var requestReference = function(data, callback) {
|
||||
innerAlert(data);
|
||||
innerAlert(event.data);
|
||||
|
||||
event.data.directUrl = !!config.document.directUrl;
|
||||
|
||||
let xhr = new XMLHttpRequest();
|
||||
xhr.open("POST", "reference");
|
||||
xhr.setRequestHeader("Content-Type", "application/json");
|
||||
xhr.send(JSON.stringify(data));
|
||||
xhr.send(JSON.stringify(event.data));
|
||||
xhr.onload = function () {
|
||||
innerAlert(xhr.responseText);
|
||||
callback(JSON.parse(xhr.responseText));
|
||||
docEditor.setReferenceData(JSON.parse(xhr.responseText));
|
||||
}
|
||||
};
|
||||
|
||||
var onRequestReferenceSource = function (event) {
|
||||
innerAlert("onRequestReferenceSource");
|
||||
let xhr = new XMLHttpRequest();
|
||||
xhr.open("GET", "files/");
|
||||
xhr.open("GET", "files");
|
||||
xhr.setRequestHeader("Content-Type", "application/json");
|
||||
xhr.send();
|
||||
xhr.onload = function () {
|
||||
@ -347,9 +320,8 @@
|
||||
"onMakeActionLink": onMakeActionLink,
|
||||
"onMetaChange": onMetaChange,
|
||||
"onRequestInsertImage": onRequestInsertImage,
|
||||
"onRequestSelectDocument": onRequestSelectDocument,
|
||||
"onRequestSelectSpreadsheet": onRequestSelectSpreadsheet,
|
||||
"onRequestOpen": onRequestOpen,
|
||||
"onRequestCompareFile": onRequestCompareFile,
|
||||
"onRequestMailMergeRecipients": onRequestMailMergeRecipients,
|
||||
};
|
||||
|
||||
if (<%- JSON.stringify(editor.userid) %> != null) {
|
||||
|
||||
@ -35,11 +35,3 @@ License File: PHP_CodeSniffer.license
|
||||
PHPUnit - The PHP Unit Testing framework. (https://github.com/sebastianbergmann/phpunit/blob/main/LICENSE)
|
||||
License: BSD 3-Clause
|
||||
License File: phpunit.license
|
||||
|
||||
property-access - Provides functions to read and write from/to an object or array using a simple string notation. (https://github.com/symfony/property-access/blob/6.3/LICENSE)
|
||||
License: MIT
|
||||
License File: property-access.license
|
||||
|
||||
serializer - Handles serializing and deserializing data structures, including object graphs, into array structures or other formats like XML and JSON. (https://github.com/symfony/serializer/blob/6.3/LICENSE)
|
||||
License: MIT
|
||||
License File: serializer.license
|
||||
|
||||
@ -1,14 +0,0 @@
|
||||
FROM php:8.2.8-fpm-alpine3.18 AS example
|
||||
WORKDIR /srv
|
||||
COPY . .
|
||||
RUN \
|
||||
chown -R www-data:www-data /srv && \
|
||||
apk update && \
|
||||
apk add --no-cache \
|
||||
composer \
|
||||
make && \
|
||||
make prod
|
||||
CMD ["make", "server-prod"]
|
||||
|
||||
FROM nginx:1.23.4-alpine3.17 AS proxy
|
||||
COPY proxy/nginx.conf /etc/nginx/nginx.conf
|
||||
@ -4,16 +4,16 @@ ADDRESS := $(ADDRESS)
|
||||
PORT := $(PORT)
|
||||
|
||||
.PHONY: help
|
||||
help: # Show help message for each of the Makefile recipes.
|
||||
help: # Show help message for each of the Makefile recipes.
|
||||
@grep -E "^[a-z-]+: #" $(MAKEFILE_LIST) | \
|
||||
awk 'BEGIN {FS = ": # "}; {printf "%s: %s\n", $$1, $$2}'
|
||||
|
||||
.PHONY: dev
|
||||
dev: # Install development dependencies.
|
||||
dev: # Install development dependencies.
|
||||
@composer install
|
||||
|
||||
.PHONY: prod
|
||||
prod: # Install production dependencies.
|
||||
prod: # Install production dependencies.
|
||||
@composer install --no-dev
|
||||
|
||||
ifeq ($(ADDRESS),)
|
||||
@ -33,7 +33,7 @@ server-dev: \
|
||||
endif
|
||||
|
||||
.PHONY: server-dev
|
||||
server-dev: # Start the development server on localhost at $PORT (default: 9000).
|
||||
server-dev: # Start the development server on localhost at $PORT (default: 9000).
|
||||
@php --server $(ADDRESS):$(PORT)
|
||||
|
||||
ifeq ($(ADDRESS),)
|
||||
@ -53,20 +53,15 @@ server-prod: \
|
||||
endif
|
||||
|
||||
.PHONY: server-prod
|
||||
server-prod: # Start the production server on 0.0.0.0 at $PORT (default: 9000).
|
||||
server-prod: # Start the production server on 0.0.0.0 at $PORT (default: 9000).
|
||||
@php-fpm --fpm-config php-fpm.conf
|
||||
|
||||
.PHONY: compose-prod
|
||||
compose-prod: # Up containers in a production environment.
|
||||
@docker-compose build
|
||||
@docker-compose up --detach
|
||||
|
||||
.PHONY: lint
|
||||
lint: # Lint the source code for the style.
|
||||
@./vendor/bin/phpcs src index.php
|
||||
lint: # Lint the source code for the style.
|
||||
@./vendor/bin/phpcs .
|
||||
|
||||
.PHONY: test
|
||||
test: # Run tests recursively.
|
||||
test: # Run tests recursively.
|
||||
@./vendor/bin/phpunit \
|
||||
--test-suffix "Tests.php" \
|
||||
--display-incomplete \
|
||||
@ -74,4 +69,12 @@ test: # Run tests recursively.
|
||||
--display-errors \
|
||||
--display-notices \
|
||||
--display-warnings \
|
||||
src
|
||||
common
|
||||
@./vendor/bin/phpunit \
|
||||
--test-suffix "Tests.php" \
|
||||
--display-incomplete \
|
||||
--display-deprecations \
|
||||
--display-errors \
|
||||
--display-notices \
|
||||
--display-warnings \
|
||||
configuration
|
||||
|
||||
@ -15,14 +15,14 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
namespace Example;
|
||||
namespace OnlineEditorsExamplePhp;
|
||||
|
||||
use Exception;
|
||||
use Example\Common\Path;
|
||||
use Example\Configuration\ConfigurationManager;
|
||||
use Example\Format\FormatManager;
|
||||
use Example\Helpers\ExampleUsers;
|
||||
use Example\Helpers\JwtManager;
|
||||
use OnlineEditorsExamplePhp\Common\Path;
|
||||
use OnlineEditorsExamplePhp\Configuration\ConfigurationManager;
|
||||
use OnlineEditorsExamplePhp\Helpers\ConfigManager;
|
||||
use OnlineEditorsExamplePhp\Helpers\ExampleUsers;
|
||||
use OnlineEditorsExamplePhp\Helpers\JwtManager;
|
||||
|
||||
/**
|
||||
* Check if the request is an AJAX request
|
||||
@ -57,14 +57,14 @@ function getHttpOrigin()
|
||||
function saveas()
|
||||
{
|
||||
try {
|
||||
$configManager = new ConfigurationManager();
|
||||
$formatManager = new FormatManager();
|
||||
$config_manager = new ConfigurationManager();
|
||||
|
||||
$post = json_decode(file_get_contents('php://input'), true);
|
||||
$fileurl = $post["url"];
|
||||
$title = $post["title"];
|
||||
$extension = mb_strtolower(pathinfo($title, PATHINFO_EXTENSION));
|
||||
$allexts = $formatManager->allExtensions();
|
||||
$configManager = new ConfigManager();
|
||||
$allexts = $configManager->getSuppotredExtensions();
|
||||
$filename = GetCorrectName($title);
|
||||
|
||||
if (!in_array($extension, $allexts)) {
|
||||
@ -72,10 +72,10 @@ function saveas()
|
||||
return $result;
|
||||
}
|
||||
$headers = get_headers($fileurl, 1);
|
||||
$contentLength = $headers["Content-Length"];
|
||||
$content_length = $headers["Content-Length"];
|
||||
$data = file_get_contents(str_replace(" ", "%20", $fileurl));
|
||||
|
||||
if ($data === false || $contentLength <= 0 || $contentLength > $configManager->maximumFileSize()) {
|
||||
if ($data === false || $content_length <= 0 || $content_length > $config_manager->maximum_file_size()) {
|
||||
$result["error"] = "File size is incorrect";
|
||||
return $result;
|
||||
}
|
||||
@ -101,9 +101,9 @@ function saveas()
|
||||
*/
|
||||
function upload()
|
||||
{
|
||||
$configManager = new ConfigurationManager();
|
||||
$formatManager = new FormatManager();
|
||||
$config_manager = new ConfigurationManager();
|
||||
|
||||
$configManager = new ConfigManager();
|
||||
if ($_FILES['files']['error'] > 0) {
|
||||
$result["error"] = 'Error ' . json_encode($_FILES['files']['error']);
|
||||
return $result;
|
||||
@ -124,13 +124,13 @@ function upload()
|
||||
$ext = mb_strtolower(pathinfo($_FILES['files']['name'], PATHINFO_EXTENSION)); // get file extension
|
||||
|
||||
// check if the file size is correct (it should be less than the max file size, but greater than 0)
|
||||
if ($filesize <= 0 || $filesize > $configManager->maximumFileSize()) {
|
||||
if ($filesize <= 0 || $filesize > $config_manager->maximum_file_size()) {
|
||||
$result["error"] = 'File size is incorrect'; // if not, then an error occurs
|
||||
return $result;
|
||||
}
|
||||
|
||||
// check if the file extension is supported by the editor
|
||||
if (!in_array($ext, $formatManager->allExtensions())) {
|
||||
if (!in_array($ext, $configManager->getSuppotredExtensions())) {
|
||||
$result["error"] = 'File type is not supported'; // if not, then an error occurs
|
||||
return $result;
|
||||
}
|
||||
@ -173,7 +173,7 @@ function track()
|
||||
return $data;
|
||||
}
|
||||
|
||||
$trackerStatus = [
|
||||
$_trackerStatus = [
|
||||
0 => 'NotFound',
|
||||
1 => 'Editing',
|
||||
2 => 'MustSave',
|
||||
@ -182,7 +182,7 @@ function track()
|
||||
6 => 'MustForceSave',
|
||||
7 => 'CorruptedForceSave',
|
||||
];
|
||||
$status = $trackerStatus[$data->status]; // get status from the request body
|
||||
$status = $_trackerStatus[$data->status]; // get status from the request body
|
||||
|
||||
$userAddress = $_GET["userAddress"];
|
||||
$fileName = basename($_GET["fileName"]);
|
||||
@ -220,17 +220,16 @@ function track()
|
||||
*/
|
||||
function convert()
|
||||
{
|
||||
$formatManager = new FormatManager();
|
||||
|
||||
$post = json_decode(file_get_contents('php://input'), true);
|
||||
$fileName = basename($post["filename"]);
|
||||
$filePass = $post["filePass"];
|
||||
$lang = $_COOKIE["ulang"] ?? "";
|
||||
$extension = mb_strtolower(pathinfo($fileName, PATHINFO_EXTENSION));
|
||||
$internalExtension = "ooxml";
|
||||
$configManager = new ConfigManager();
|
||||
|
||||
// check if the file with such an extension can be converted
|
||||
if (in_array($extension, $formatManager->convertibleExtensions()) &&
|
||||
if (in_array($extension, $configManager->getConvertExtensions()) &&
|
||||
$internalExtension != "") {
|
||||
$fileUri = $post["fileUri"];
|
||||
if ($fileUri == null || $fileUri == "") {
|
||||
@ -341,7 +340,7 @@ function files()
|
||||
function assets()
|
||||
{
|
||||
$fileName = basename($_GET["name"]);
|
||||
$filePath = dirname(__FILE__) . DIRECTORY_SEPARATOR . '..' .
|
||||
$filePath = dirname(__FILE__) .
|
||||
DIRECTORY_SEPARATOR . "assets" . DIRECTORY_SEPARATOR . "document-templates"
|
||||
. DIRECTORY_SEPARATOR . "sample" . DIRECTORY_SEPARATOR . $fileName;
|
||||
downloadFile($filePath);
|
||||
@ -355,7 +354,7 @@ function assets()
|
||||
function csv()
|
||||
{
|
||||
$fileName = "csv.csv";
|
||||
$filePath = dirname(__FILE__) . DIRECTORY_SEPARATOR . '..' .
|
||||
$filePath = dirname(__FILE__) .
|
||||
DIRECTORY_SEPARATOR . "assets" . DIRECTORY_SEPARATOR . "document-templates"
|
||||
. DIRECTORY_SEPARATOR . "sample" . DIRECTORY_SEPARATOR . $fileName;
|
||||
downloadFile($filePath);
|
||||
@ -369,7 +368,7 @@ function csv()
|
||||
function historyDownload()
|
||||
{
|
||||
try {
|
||||
$configManager = new ConfigurationManager();
|
||||
$config_manager = new ConfigurationManager();
|
||||
|
||||
$fileName = basename($_GET["fileName"]); // get the file name
|
||||
$userAddress = $_GET["userAddress"];
|
||||
@ -379,7 +378,8 @@ function historyDownload()
|
||||
|
||||
$jwtManager = new JwtManager();
|
||||
if ($jwtManager->isJwtEnabled()) {
|
||||
$jwtHeader = $configManager->jwtHeader();
|
||||
$configManager = new ConfigManager();
|
||||
$jwtHeader = $config_manager->jwt_header();
|
||||
if (!empty(apache_request_headers()[$jwtHeader])) {
|
||||
$token = $jwtManager->jwtDecode(mb_substr(
|
||||
apache_request_headers()[$jwtHeader],
|
||||
@ -416,7 +416,7 @@ function historyDownload()
|
||||
function download()
|
||||
{
|
||||
try {
|
||||
$configManager = new ConfigurationManager();
|
||||
$config_manager = new ConfigurationManager();
|
||||
|
||||
$fileName = $_GET["fileName"];
|
||||
$userAddress = $_GET["userAddress"] ?? null;
|
||||
@ -424,7 +424,7 @@ function download()
|
||||
$jwtManager = new JwtManager();
|
||||
|
||||
if ($jwtManager->isJwtEnabled() && $isEmbedded == null && $userAddress) {
|
||||
$jwtHeader = $configManager->jwtHeader();
|
||||
$jwtHeader = $config_manager->jwt_header();
|
||||
if (!empty(apache_request_headers()[$jwtHeader])) {
|
||||
$token = $jwtManager->jwtDecode(mb_substr(
|
||||
apache_request_headers()[$jwtHeader],
|
||||
@ -464,10 +464,7 @@ function downloadFile($filePath)
|
||||
|
||||
// write headers to the response object
|
||||
@header('Content-Length: ' . filesize($filePath));
|
||||
@header(
|
||||
'Content-Disposition: attachment; filename*=UTF-8\'\'' .
|
||||
str_replace("+", "%20", urlencode(basename($filePath)))
|
||||
);
|
||||
@header('Content-Disposition: attachment; filename*=UTF-8\'\'' . str_replace("+", "%20", urlencode(basename($filePath))));
|
||||
@header('Content-Type: ' . mime_content_type($filePath));
|
||||
@header('Access-Control-Allow-Origin: *');
|
||||
|
||||
@ -591,31 +588,31 @@ function restore()
|
||||
$input = file_get_contents('php://input');
|
||||
$body = json_decode($input);
|
||||
|
||||
$sourceBasename = $body->fileName;
|
||||
$source_basename = $body->fileName;
|
||||
$version = $body->version;
|
||||
$userID = $body->userId;
|
||||
$user_id = $body->userId;
|
||||
|
||||
$sourceFile = getStoragePath($sourceBasename);
|
||||
$historyDirectory = getHistoryDir($sourceFile);
|
||||
$source_file = getStoragePath($source_basename);
|
||||
$history_directory = getHistoryDir($source_file);
|
||||
|
||||
$bumpedVersion = getFileVersion($historyDirectory);
|
||||
$bumpedVersionStringDirectory = getVersionDir($historyDirectory, $bumpedVersion);
|
||||
if (!file_exists($bumpedVersionStringDirectory)) {
|
||||
mkdir($bumpedVersionStringDirectory);
|
||||
$bumped_version = getFileVersion($history_directory);
|
||||
$bumped_version_string_directory = getVersionDir($history_directory, $bumped_version);
|
||||
if (!file_exists($bumped_version_string_directory)) {
|
||||
mkdir($bumped_version_string_directory);
|
||||
}
|
||||
$bumpedVersionDirectory = new Path($bumpedVersionStringDirectory);
|
||||
$bumped_version_directory = new Path($bumped_version_string_directory);
|
||||
|
||||
$bumpedKeyFile = $bumpedVersionDirectory->joinPath('key.txt');
|
||||
$bumpedKeyStringFile = $bumpedKeyFile->string();
|
||||
$bumpedKey = getDocEditorKey($sourceBasename);
|
||||
file_put_contents($bumpedKeyStringFile, $bumpedKey, LOCK_EX);
|
||||
$bumped_key_file = $bumped_version_directory->join_path('key.txt');
|
||||
$bumped_key_string_file = $bumped_key_file->string();
|
||||
$bumped_key = getDocEditorKey($source_basename);
|
||||
file_put_contents($bumped_key_string_file, $bumped_key, LOCK_EX);
|
||||
|
||||
$users = new ExampleUsers();
|
||||
$user = $users->getUser($userID);
|
||||
$user = $users->getUser($user_id);
|
||||
|
||||
$bumpedChangesFile = $bumpedVersionDirectory->joinPath('changes.json');
|
||||
$bumpedChangesStringFile = $bumpedChangesFile->string();
|
||||
$bumpedChanges = [
|
||||
$bumped_changes_file = $bumped_version_directory->join_path('changes.json');
|
||||
$bumped_changes_string_file = $bumped_changes_file->string();
|
||||
$bumped_changes = [
|
||||
'serverVersion' => null,
|
||||
'changes' => array(
|
||||
[
|
||||
@ -627,21 +624,21 @@ function restore()
|
||||
]
|
||||
)
|
||||
];
|
||||
$bumpedChangesContent = json_encode($bumpedChanges, JSON_PRETTY_PRINT);
|
||||
file_put_contents($bumpedChangesStringFile, $bumpedChangesContent, LOCK_EX);
|
||||
$bumped_changes_content = json_encode($bumped_changes, JSON_PRETTY_PRINT);
|
||||
file_put_contents($bumped_changes_string_file, $bumped_changes_content, LOCK_EX);
|
||||
|
||||
$sourceExtension = pathinfo($sourceBasename, PATHINFO_EXTENSION);
|
||||
$previousBasename = "prev.{$sourceExtension}";
|
||||
$source_extension = pathinfo($source_basename, PATHINFO_EXTENSION);
|
||||
$previous_basename = "prev.{$source_extension}";
|
||||
|
||||
$bumpedFile = $bumpedVersionDirectory->joinPath($previousBasename);
|
||||
$bumpedStringFile = $bumpedFile->string();
|
||||
copy($sourceFile, $bumpedStringFile);
|
||||
$bumped_file = $bumped_version_directory->join_path($previous_basename);
|
||||
$bumped_string_file = $bumped_file->string();
|
||||
copy($source_file, $bumped_string_file);
|
||||
|
||||
$recoveryVersionStringDirectory = getVersionDir($historyDirectory, $version);
|
||||
$recoveryVersionDirectory = new Path($recoveryVersionStringDirectory);
|
||||
$recoveryFile = $recoveryVersionDirectory->joinPath($previousBasename);
|
||||
$recoveryStringFile = $recoveryFile->string();
|
||||
copy($recoveryStringFile, $sourceFile);
|
||||
$recovery_version_string_directory = getVersionDir($history_directory, $version);
|
||||
$recovery_version_directory = new Path($recovery_version_string_directory);
|
||||
$recovery_file = $recovery_version_directory->join_path($previous_basename);
|
||||
$recovery_string_file = $recovery_file->string();
|
||||
copy($recovery_string_file, $source_file);
|
||||
|
||||
return [
|
||||
'error' => null,
|
||||
@ -15,9 +15,8 @@
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
namespace Example\Common;
|
||||
namespace OnlineEditorsExamplePhp\Common;
|
||||
|
||||
enum HTTPStatus: int
|
||||
{
|
||||
case NotFound = 404;
|
||||
enum HTTPStatus: int {
|
||||
case not_found = 404;
|
||||
}
|
||||
@ -15,53 +15,45 @@
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
namespace Example\Common;
|
||||
namespace OnlineEditorsExamplePhp\Common;
|
||||
|
||||
final class Path
|
||||
{
|
||||
final class Path {
|
||||
private string $separator = DIRECTORY_SEPARATOR;
|
||||
private string $string;
|
||||
|
||||
public function __construct(string $path)
|
||||
{
|
||||
public function __construct(string $path) {
|
||||
$this->string = $path;
|
||||
}
|
||||
|
||||
public function string(): string
|
||||
{
|
||||
public function string(): string {
|
||||
return $this->string;
|
||||
}
|
||||
|
||||
public function dirname(): ?string
|
||||
{
|
||||
public function dirname(): ?string {
|
||||
$string = $this->string();
|
||||
$parsed = pathinfo($string, PATHINFO_DIRNAME);
|
||||
return $parsed ?: null;
|
||||
}
|
||||
|
||||
public function basename(): ?string
|
||||
{
|
||||
public function basename(): ?string {
|
||||
$string = $this->string();
|
||||
$parsed = pathinfo($string, PATHINFO_BASENAME);
|
||||
return $parsed ?: null;
|
||||
}
|
||||
|
||||
public function extension(): ?string
|
||||
{
|
||||
public function extension(): ?string {
|
||||
$string = $this->string();
|
||||
$parsed = pathinfo($string, PATHINFO_EXTENSION);
|
||||
return $parsed ?: null;
|
||||
}
|
||||
|
||||
public function filename(): ?string
|
||||
{
|
||||
public function filename(): ?string {
|
||||
$string = $this->string();
|
||||
$parsed = pathinfo($string, PATHINFO_FILENAME);
|
||||
return $parsed ?: null;
|
||||
}
|
||||
|
||||
public function normalize(): self
|
||||
{
|
||||
public function normalize(): self {
|
||||
$string = $this->string();
|
||||
$filtered = array();
|
||||
$slugs = explode($this->separator, $string);
|
||||
@ -76,14 +68,13 @@ final class Path
|
||||
$filtered[] = $slug;
|
||||
}
|
||||
$joined = implode($this->separator, $filtered);
|
||||
$escapedSeparator = preg_quote($this->separator, $this->separator);
|
||||
$separatorRegex = "/{$escapedSeparator}{2,}/";
|
||||
$separated = preg_replace($separatorRegex, $this->separator, $joined);
|
||||
$escaped_separator = preg_quote($this->separator, $this->separator);
|
||||
$separator_regex = "/{$escaped_separator}{2,}/";
|
||||
$separated = preg_replace($separator_regex, $this->separator, $joined);
|
||||
return new Path($separated);
|
||||
}
|
||||
|
||||
public function joinPath(string $path): self
|
||||
{
|
||||
public function join_path(string $path): self {
|
||||
$string = $this->string();
|
||||
$separator =
|
||||
str_ends_with($string, $this->separator) ||
|
||||
@ -93,48 +84,43 @@ final class Path
|
||||
return new Path("{$string}{$separator}{$path}");
|
||||
}
|
||||
|
||||
public function absolute(): bool
|
||||
{
|
||||
public function absolute(): bool {
|
||||
$string = $this->string();
|
||||
|
||||
$ntRegex = '/^[A-Za-z]:\\\\/';
|
||||
if (preg_match($ntRegex, $string)) {
|
||||
$nt_regex = '/^[A-Za-z]:\\\\/';
|
||||
if (preg_match($nt_regex, $string)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$ntSeparator = '\\';
|
||||
if (str_starts_with($string, $ntSeparator)) {
|
||||
$nt_separator = '\\';
|
||||
if (str_starts_with($string, $nt_separator)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$posixSeparator = '/';
|
||||
if (str_starts_with($string, $posixSeparator)) {
|
||||
$posix_separator = '/';
|
||||
if (str_starts_with($string, $posix_separator)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function exists(): bool
|
||||
{
|
||||
public function exists(): bool {
|
||||
$string = $this->string();
|
||||
return file_exists($string);
|
||||
}
|
||||
|
||||
public function contents(): string
|
||||
{
|
||||
public function contents(): string {
|
||||
$string = $this->string();
|
||||
return file_get_contents($string);
|
||||
}
|
||||
|
||||
public function directory(): bool
|
||||
{
|
||||
public function directory(): bool {
|
||||
$string = $this->string();
|
||||
return is_dir($string);
|
||||
}
|
||||
|
||||
public function makeDirectory(): bool
|
||||
{
|
||||
public function make_directory(): bool {
|
||||
$string = $this->string();
|
||||
return mkdir($string);
|
||||
}
|
||||
@ -15,29 +15,23 @@
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
namespace Example\Common\Tests;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Example\Common\Path;
|
||||
use OnlineEditorsExamplePhp\Common\Path;
|
||||
|
||||
final class PathAbsolutePOSIXTests extends TestCase
|
||||
{
|
||||
public function testRecognizesAnEmptyAsANonAbsolute()
|
||||
{
|
||||
final class PathAbsolutePOSIXTests extends TestCase {
|
||||
public function test_recognizes_an_empty_as_a_non_absolute() {
|
||||
$path = new Path('');
|
||||
$absolute = $path->absolute();
|
||||
$this->assertFalse($absolute);
|
||||
}
|
||||
|
||||
public function testRecognizesARelativeAsANonAbsolute()
|
||||
{
|
||||
public function test_recognizes_a_relative_as_a_non_absolute() {
|
||||
$path = new Path('.');
|
||||
$absolute = $path->absolute();
|
||||
$this->assertFalse($absolute);
|
||||
}
|
||||
|
||||
public function testRecognizesAnAbsoluteAsAnAbsolute()
|
||||
{
|
||||
public function test_recognizes_an_absolute_as_an_absolute() {
|
||||
$path = new Path('/');
|
||||
$absolute = $path->absolute();
|
||||
$this->assertTrue($absolute);
|
||||
@ -15,77 +15,67 @@
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
namespace Example\Common\Tests;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Example\Common\Path;
|
||||
use OnlineEditorsExamplePhp\Common\Path;
|
||||
|
||||
final class PathJoinPOSIXTests extends TestCase
|
||||
{
|
||||
public function testJoinsARelativeToAnEmptyOne()
|
||||
{
|
||||
final class PathJoinPOSIXTests extends TestCase {
|
||||
public function test_joins_a_relative_to_an_empty_one() {
|
||||
$path = new Path('');
|
||||
$joined = $path->joinPath('srv');
|
||||
$joined = $path->join_path('srv');
|
||||
$this->assertEquals($joined->dirname(), '/');
|
||||
$this->assertEquals($joined->basename(), 'srv');
|
||||
$this->assertEquals($joined->extension(), null);
|
||||
$this->assertEquals($joined->filename(), 'srv');
|
||||
}
|
||||
|
||||
public function testJoinsARelativeToARelativeOne()
|
||||
{
|
||||
public function test_joins_a_relative_to_a_relative_one() {
|
||||
$path = new Path('.');
|
||||
$joined = $path->joinPath('srv');
|
||||
$joined = $path->join_path('srv');
|
||||
$this->assertEquals($joined->dirname(), '.');
|
||||
$this->assertEquals($joined->basename(), 'srv');
|
||||
$this->assertEquals($joined->extension(), null);
|
||||
$this->assertEquals($joined->filename(), 'srv');
|
||||
}
|
||||
|
||||
public function testJoinsARelativeToAnAbsoluteOne()
|
||||
{
|
||||
public function test_joins_a_relative_to_an_absolute_one() {
|
||||
$path = new Path('/');
|
||||
$joined = $path->joinPath('srv');
|
||||
$joined = $path->join_path('srv');
|
||||
$this->assertEquals($joined->dirname(), '/');
|
||||
$this->assertEquals($joined->basename(), 'srv');
|
||||
$this->assertEquals($joined->extension(), null);
|
||||
$this->assertEquals($joined->filename(), 'srv');
|
||||
}
|
||||
|
||||
public function testJoinsAnAbsoluteToAnEmptyOne()
|
||||
{
|
||||
public function test_joins_an_absolute_to_an_empty_one() {
|
||||
$path = new Path('');
|
||||
$joined = $path->joinPath('/srv');
|
||||
$joined = $path->join_path('/srv');
|
||||
$this->assertEquals($joined->dirname(), '/');
|
||||
$this->assertEquals($joined->basename(), 'srv');
|
||||
$this->assertEquals($joined->extension(), null);
|
||||
$this->assertEquals($joined->filename(), 'srv');
|
||||
}
|
||||
|
||||
public function testJoinsAnAbsoluteToARelativeOne()
|
||||
{
|
||||
public function test_joins_an_absolute_to_a_relative_one() {
|
||||
$path = new Path('.');
|
||||
$joined = $path->joinPath('/srv');
|
||||
$joined = $path->join_path('/srv');
|
||||
$this->assertEquals($joined->dirname(), '.');
|
||||
$this->assertEquals($joined->basename(), 'srv');
|
||||
$this->assertEquals($joined->extension(), null);
|
||||
$this->assertEquals($joined->filename(), 'srv');
|
||||
}
|
||||
|
||||
public function testJoinsAnAbsoluteToAnAbsoluteOne()
|
||||
{
|
||||
public function test_joins_an_absolute_to_an_absolute_one() {
|
||||
$path = new Path('/');
|
||||
$joined = $path->joinPath('/srv');
|
||||
$joined = $path->join_path('/srv');
|
||||
$this->assertEquals($joined->dirname(), '/');
|
||||
$this->assertEquals($joined->basename(), 'srv');
|
||||
$this->assertEquals($joined->extension(), null);
|
||||
$this->assertEquals($joined->filename(), 'srv');
|
||||
}
|
||||
|
||||
public function testJoinsAnUnnormalized()
|
||||
{
|
||||
public function test_joins_an_unnormalized() {
|
||||
$path = new Path('');
|
||||
$joined = $path->joinPath('../srv');
|
||||
$joined = $path->join_path('../srv');
|
||||
$this->assertEquals($joined->dirname(), '/..');
|
||||
$this->assertEquals($joined->basename(), 'srv');
|
||||
$this->assertEquals($joined->extension(), null);
|
||||
@ -15,15 +15,11 @@
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
namespace Example\Common\Tests;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Example\Common\Path;
|
||||
use OnlineEditorsExamplePhp\Common\Path;
|
||||
|
||||
final class PathNormalizePOSIXTests extends TestCase
|
||||
{
|
||||
public function testNormalizes()
|
||||
{
|
||||
final class PathNormalizePOSIXTests extends TestCase {
|
||||
public function test_normalizes() {
|
||||
$path = new Path('./srv///sub/.././sub/file.docx');
|
||||
$normalized = $path->normalize();
|
||||
$this->assertEquals($normalized->dirname(), 'srv/sub');
|
||||
@ -15,157 +15,133 @@
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
namespace Example\Common\Tests;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Example\Common\Path;
|
||||
use OnlineEditorsExamplePhp\Common\Path;
|
||||
|
||||
final class PathStringPOSIXTests extends TestCase
|
||||
{
|
||||
public function testGeneratesWithAnEmpty()
|
||||
{
|
||||
final class PathStringPOSIXTests extends TestCase {
|
||||
public function test_generates_with_an_empty() {
|
||||
$path = new Path('');
|
||||
$string = $path->string();
|
||||
$this->assertEquals($string, '');
|
||||
}
|
||||
|
||||
public function testGeneratesWithAnEmptyRelative()
|
||||
{
|
||||
public function test_generates_with_an_empty_relative() {
|
||||
$path = new Path('.');
|
||||
$string = $path->string();
|
||||
$this->assertEquals($string, '.');
|
||||
}
|
||||
|
||||
public function testGeneratesWithAnEmptyAbsolute()
|
||||
{
|
||||
public function test_generates_with_an_empty_absolute() {
|
||||
$path = new Path('/');
|
||||
$string = $path->string();
|
||||
$this->assertEquals($string, '/');
|
||||
}
|
||||
|
||||
public function testGeneratesWithARelative()
|
||||
{
|
||||
public function test_generates_with_a_relative() {
|
||||
$path = new Path('srv');
|
||||
$string = $path->string();
|
||||
$this->assertEquals($string, 'srv');
|
||||
}
|
||||
|
||||
public function testGeneratesWithARelativeContainingADirectory()
|
||||
{
|
||||
public function test_generates_with_a_relative_containing_a_directory() {
|
||||
$path = new Path('srv/sub');
|
||||
$string = $path->string();
|
||||
$this->assertEquals($string, 'srv/sub');
|
||||
}
|
||||
|
||||
public function testGeneratesWithARelativeContainingAFile()
|
||||
{
|
||||
public function test_generates_with_a_relative_containing_a_file() {
|
||||
$path = new Path('srv/file.json');
|
||||
$string = $path->string();
|
||||
$this->assertEquals($string, 'srv/file.json');
|
||||
}
|
||||
|
||||
public function testGeneratesWithARelativeContainingADirectoryWithAFile()
|
||||
{
|
||||
public function test_generates_with_a_relative_containing_a_directory_with_a_file() {
|
||||
$path = new Path('srv/sub/file.json');
|
||||
$string = $path->string();
|
||||
$this->assertEquals($string, 'srv/sub/file.json');
|
||||
}
|
||||
|
||||
public function testGeneratesWithAnUnnormalizedRelative()
|
||||
{
|
||||
public function test_generates_with_an_unnormalized_relative() {
|
||||
$path = new Path('srv////sub///file.json');
|
||||
$string = $path->string();
|
||||
$this->assertEquals($string, 'srv////sub///file.json');
|
||||
}
|
||||
|
||||
public function testGeneratesWithAnNormalizedRelative()
|
||||
{
|
||||
public function test_generates_with_an_normalized_relative() {
|
||||
$path = new Path('srv////sub///file.json');
|
||||
$normalized = $path->normalize();
|
||||
$string = $normalized->string();
|
||||
$this->assertEquals($string, 'srv/sub/file.json');
|
||||
}
|
||||
|
||||
public function testGeneratesWithAnExplicitRelative()
|
||||
{
|
||||
public function test_generates_with_an_explicit_relative() {
|
||||
$path = new Path('./srv');
|
||||
$string = $path->string();
|
||||
$this->assertEquals($string, './srv');
|
||||
}
|
||||
|
||||
public function testGeneratesWithAnExplicitRelativeContainingADirectory()
|
||||
{
|
||||
public function test_generates_with_an_explicit_relative_containing_a_directory() {
|
||||
$path = new Path('./srv/sub');
|
||||
$string = $path->string();
|
||||
$this->assertEquals($string, './srv/sub');
|
||||
}
|
||||
|
||||
public function testGeneratesWithAnExplicitRelativeContainingAFile()
|
||||
{
|
||||
public function test_generates_with_an_explicit_relative_containing_a_file() {
|
||||
$path = new Path('./srv/file.json');
|
||||
$string = $path->string();
|
||||
$this->assertEquals($string, './srv/file.json');
|
||||
}
|
||||
|
||||
public function testGeneratesWithAnExplicitRelativeContainingADirectoryWithAFile()
|
||||
{
|
||||
public function test_generates_with_an_explicit_relative_containing_a_directory_with_a_file() {
|
||||
$path = new Path('./srv/sub/file.json');
|
||||
$string = $path->string();
|
||||
$this->assertEquals($string, './srv/sub/file.json');
|
||||
}
|
||||
|
||||
public function testGeneratesWithAnExplicitUnnormalizedRelative()
|
||||
{
|
||||
public function test_generates_with_an_explicit_unnormalized_relative() {
|
||||
$path = new Path('./srv////sub///file.json');
|
||||
$string = $path->string();
|
||||
$this->assertEquals($string, './srv////sub///file.json');
|
||||
}
|
||||
|
||||
public function testGeneratesWithAnExplicitNormalizedRelative()
|
||||
{
|
||||
public function test_generates_with_an_explicit_normalized_relative() {
|
||||
$path = new Path('./srv////sub///file.json');
|
||||
$normalized = $path->normalize();
|
||||
$string = $normalized->string();
|
||||
$this->assertEquals($string, 'srv/sub/file.json');
|
||||
}
|
||||
|
||||
public function testGeneratesWithAnAbsolute()
|
||||
{
|
||||
public function test_generates_with_an_absolute() {
|
||||
$path = new Path('/srv');
|
||||
$string = $path->string();
|
||||
$this->assertEquals($string, '/srv');
|
||||
}
|
||||
|
||||
public function testGeneratesWithAnAbsoluteContainingADirectory()
|
||||
{
|
||||
public function test_generates_with_an_absolute_containing_a_directory() {
|
||||
$path = new Path('/srv/sub');
|
||||
$string = $path->string();
|
||||
$this->assertEquals($string, '/srv/sub');
|
||||
}
|
||||
|
||||
public function testGeneratesWithAnAbsoluteContainingAFile()
|
||||
{
|
||||
public function test_generates_with_an_absolute_containing_a_file() {
|
||||
$path = new Path('/srv/file.json');
|
||||
$string = $path->string();
|
||||
$this->assertEquals($string, '/srv/file.json');
|
||||
}
|
||||
|
||||
public function testGeneratesWithAnAbsoluteContainingADirectoryWithAFile()
|
||||
{
|
||||
public function test_generates_with_an_absolute_containing_a_directory_with_a_file() {
|
||||
$path = new Path('/srv/sub/file.json');
|
||||
$string = $path->string();
|
||||
$this->assertEquals($string, '/srv/sub/file.json');
|
||||
}
|
||||
|
||||
public function testGeneratesWithAnUnnormalizedAbsolute()
|
||||
{
|
||||
public function test_generates_with_an_unnormalized_absolute() {
|
||||
$path = new Path('/srv////sub///file.json');
|
||||
$string = $path->string();
|
||||
$this->assertEquals($string, '/srv////sub///file.json');
|
||||
}
|
||||
|
||||
public function testGeneratesWithAnNormalizedAbsolute()
|
||||
{
|
||||
public function test_generates_with_an_normalized_absolute() {
|
||||
$path = new Path('/srv////sub///file.json');
|
||||
$normalized = $path->normalize();
|
||||
$string = $normalized->string();
|
||||
@ -15,71 +15,60 @@
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
namespace Example\Common;
|
||||
namespace OnlineEditorsExamplePhp\Common;
|
||||
|
||||
final class URL
|
||||
{
|
||||
final class URL {
|
||||
private string $string;
|
||||
|
||||
public function __construct(string $url)
|
||||
{
|
||||
public function __construct(string $url) {
|
||||
$this->string = $url;
|
||||
}
|
||||
|
||||
public function string(): string
|
||||
{
|
||||
public function string(): string {
|
||||
return $this->string;
|
||||
}
|
||||
|
||||
public function scheme(): ?string
|
||||
{
|
||||
public function scheme(): ?string {
|
||||
$string = $this->string();
|
||||
return parse_url($string, PHP_URL_SCHEME) ?: null;
|
||||
}
|
||||
|
||||
public function host(): ?string
|
||||
{
|
||||
public function host(): ?string {
|
||||
$string = $this->string();
|
||||
return parse_url($string, PHP_URL_HOST) ?: null;
|
||||
}
|
||||
|
||||
public function port(): ?int
|
||||
{
|
||||
public function port(): ?int {
|
||||
$string = $this->string();
|
||||
return parse_url($string, PHP_URL_PORT) ?: null;
|
||||
}
|
||||
|
||||
public function user(): ?string
|
||||
{
|
||||
public function user(): ?string {
|
||||
$string = $this->string();
|
||||
return parse_url($string, PHP_URL_USER) ?: null;
|
||||
}
|
||||
|
||||
public function pass(): ?string
|
||||
{
|
||||
public function pass(): ?string {
|
||||
$string = $this->string();
|
||||
return parse_url($string, PHP_URL_PASS) ?: null;
|
||||
}
|
||||
|
||||
public function path(): ?string
|
||||
{
|
||||
public function path(): ?string {
|
||||
$string = $this->string();
|
||||
return parse_url($string, PHP_URL_PATH) ?: null;
|
||||
}
|
||||
|
||||
public function query(): ?string
|
||||
{
|
||||
public function query(): ?string {
|
||||
$string = $this->string();
|
||||
return parse_url($string, PHP_URL_QUERY) ?: null;
|
||||
}
|
||||
|
||||
public function fragment(): ?string
|
||||
{
|
||||
public function fragment(): ?string {
|
||||
$string = $this->string();
|
||||
return parse_url($string, PHP_URL_FRAGMENT) ?: null;
|
||||
}
|
||||
|
||||
public static function fromComponents(
|
||||
public static function from_components(
|
||||
?string $scheme,
|
||||
?string $host,
|
||||
?int $port,
|
||||
@ -117,20 +106,19 @@ final class URL
|
||||
return new URL($string);
|
||||
}
|
||||
|
||||
public function joinPath(string $path): self
|
||||
{
|
||||
$currentPath = $this->path();
|
||||
public function join_path(string $path): self {
|
||||
$current_path = $this->path();
|
||||
$separator =
|
||||
$currentPath &&
|
||||
$current_path &&
|
||||
(
|
||||
str_ends_with($currentPath, '/') ||
|
||||
str_ends_with($current_path, '/') ||
|
||||
str_starts_with($path, '/')
|
||||
) ||
|
||||
!$currentPath && str_starts_with($path, '/')
|
||||
!$current_path && str_starts_with($path, '/')
|
||||
? ''
|
||||
: '/';
|
||||
$separated = "{$currentPath}{$separator}{$path}";
|
||||
return URL::fromComponents(
|
||||
$separated = "{$current_path}{$separator}{$path}";
|
||||
return URL::from_components(
|
||||
$this->scheme(),
|
||||
$this->host(),
|
||||
$this->port(),
|
||||
@ -15,16 +15,12 @@
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
namespace Example\Common\Tests;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Example\Common\URL;
|
||||
use OnlineEditorsExamplePhp\Common\URL;
|
||||
|
||||
final class URLFromComponentsTests extends TestCase
|
||||
{
|
||||
public function testCreates()
|
||||
{
|
||||
$url = URL::fromComponents(
|
||||
final class URLFromComponentsTests extends TestCase {
|
||||
public function test_creates() {
|
||||
$url = URL::from_components(
|
||||
'http',
|
||||
'localhost',
|
||||
8080,
|
||||
@ -15,17 +15,13 @@
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
namespace Example\Common\Tests;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Example\Common\URL;
|
||||
use OnlineEditorsExamplePhp\Common\URL;
|
||||
|
||||
final class URLJoinPathTests extends TestCase
|
||||
{
|
||||
public function testJoinsARelativeToAnEmptyOne()
|
||||
{
|
||||
final class URLJoinPathTests extends TestCase {
|
||||
public function test_joins_a_relative_to_an_empty_one() {
|
||||
$url = new URL('http://localhost');
|
||||
$joined = $url->joinPath('first');
|
||||
$joined = $url->join_path('first');
|
||||
$this->assertEquals('http', $joined->scheme());
|
||||
$this->assertEquals('localhost', $joined->host());
|
||||
$this->assertEquals(null, $joined->port());
|
||||
@ -36,10 +32,9 @@ final class URLJoinPathTests extends TestCase
|
||||
$this->assertEquals(null, $joined->fragment());
|
||||
}
|
||||
|
||||
public function testJoinsARelative()
|
||||
{
|
||||
public function test_joins_a_relative() {
|
||||
$url = new URL('http://localhost/first');
|
||||
$joined = $url->joinPath('second');
|
||||
$joined = $url->join_path('second');
|
||||
$this->assertEquals('http', $joined->scheme());
|
||||
$this->assertEquals('localhost', $joined->host());
|
||||
$this->assertEquals(null, $joined->port());
|
||||
@ -50,10 +45,9 @@ final class URLJoinPathTests extends TestCase
|
||||
$this->assertEquals(null, $joined->fragment());
|
||||
}
|
||||
|
||||
public function testJoinsAnAbsoluteToAnEmptyOne()
|
||||
{
|
||||
public function test_joins_an_absolute_to_an_empty_one() {
|
||||
$url = new URL('http://localhost');
|
||||
$joined = $url->joinPath('/first');
|
||||
$joined = $url->join_path('/first');
|
||||
$this->assertEquals('http', $joined->scheme());
|
||||
$this->assertEquals('localhost', $joined->host());
|
||||
$this->assertEquals(null, $joined->port());
|
||||
@ -64,10 +58,9 @@ final class URLJoinPathTests extends TestCase
|
||||
$this->assertEquals(null, $joined->fragment());
|
||||
}
|
||||
|
||||
public function testJoinsAnAbsolute()
|
||||
{
|
||||
public function test_joins_an_absolute() {
|
||||
$url = new URL('http://localhost/first');
|
||||
$joined = $url->joinPath('/second');
|
||||
$joined = $url->join_path('/second');
|
||||
$this->assertEquals('http', $joined->scheme());
|
||||
$this->assertEquals('localhost', $joined->host());
|
||||
$this->assertEquals(null, $joined->port());
|
||||
@ -15,15 +15,11 @@
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
namespace Example\Common\Tests;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Example\Common\URL;
|
||||
use OnlineEditorsExamplePhp\Common\URL;
|
||||
|
||||
final class URLStringTests extends TestCase
|
||||
{
|
||||
public function testGenerates()
|
||||
{
|
||||
final class URLStringTests extends TestCase {
|
||||
public function test_generates() {
|
||||
$url = new URL('http://user:password@localhost:8080/path?q=value#fragment');
|
||||
$string = $url->string();
|
||||
$this->assertEquals(
|
||||
@ -1,9 +1,7 @@
|
||||
{
|
||||
"require": {
|
||||
"ext-mbstring": "*",
|
||||
"firebase/php-jwt": "^6.8.1",
|
||||
"symfony/serializer": "^6.3",
|
||||
"symfony/property-access": "^6.3"
|
||||
"firebase/php-jwt": "^6.8.1"
|
||||
},
|
||||
"require-dev": {
|
||||
"squizlabs/php_codesniffer": "^3.7.2",
|
||||
@ -11,12 +9,11 @@
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Example\\Common\\": "src/common/",
|
||||
"Example\\Configuration\\" : "src/configuration/",
|
||||
"Example\\Format\\" : "src/format/",
|
||||
"Example\\Helpers\\" : "src/helpers/",
|
||||
"Example\\Proxy\\": "src/proxy/",
|
||||
"Example\\Views\\" : "src/views/"
|
||||
"OnlineEditorsExamplePhp\\" : "",
|
||||
"OnlineEditorsExamplePhp\\Common\\": "common/",
|
||||
"OnlineEditorsExamplePhp\\Configuration\\" : "configuration/",
|
||||
"OnlineEditorsExamplePhp\\Helpers\\" : "helpers/",
|
||||
"OnlineEditorsExamplePhp\\Views\\" : "views/"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
738
web/documentserver-example/php/composer.lock
generated
@ -4,7 +4,7 @@
|
||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "5d476b9c61f48836ee5e6c9cab7a1980",
|
||||
"content-hash": "1408ebe84361a11eb7a751e9603b937f",
|
||||
"packages": [
|
||||
{
|
||||
"name": "firebase/php-jwt",
|
||||
@ -68,742 +68,6 @@
|
||||
"source": "https://github.com/firebase/php-jwt/tree/v6.8.1"
|
||||
},
|
||||
"time": "2023-07-14T18:33:00+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/deprecation-contracts",
|
||||
"version": "v3.3.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/deprecation-contracts.git",
|
||||
"reference": "7c3aff79d10325257a001fcf92d991f24fc967cf"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/7c3aff79d10325257a001fcf92d991f24fc967cf",
|
||||
"reference": "7c3aff79d10325257a001fcf92d991f24fc967cf",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=8.1"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-main": "3.4-dev"
|
||||
},
|
||||
"thanks": {
|
||||
"name": "symfony/contracts",
|
||||
"url": "https://github.com/symfony/contracts"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"files": [
|
||||
"function.php"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Nicolas Grekas",
|
||||
"email": "p@tchwork.com"
|
||||
},
|
||||
{
|
||||
"name": "Symfony Community",
|
||||
"homepage": "https://symfony.com/contributors"
|
||||
}
|
||||
],
|
||||
"description": "A generic function and convention to trigger deprecation notices",
|
||||
"homepage": "https://symfony.com",
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/deprecation-contracts/tree/v3.3.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://symfony.com/sponsor",
|
||||
"type": "custom"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/fabpot",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2023-05-23T14:45:45+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-ctype",
|
||||
"version": "v1.27.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-ctype.git",
|
||||
"reference": "5bbc823adecdae860bb64756d639ecfec17b050a"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/5bbc823adecdae860bb64756d639ecfec17b050a",
|
||||
"reference": "5bbc823adecdae860bb64756d639ecfec17b050a",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=7.1"
|
||||
},
|
||||
"provide": {
|
||||
"ext-ctype": "*"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-ctype": "For best performance"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-main": "1.27-dev"
|
||||
},
|
||||
"thanks": {
|
||||
"name": "symfony/polyfill",
|
||||
"url": "https://github.com/symfony/polyfill"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"files": [
|
||||
"bootstrap.php"
|
||||
],
|
||||
"psr-4": {
|
||||
"Symfony\\Polyfill\\Ctype\\": ""
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Gert de Pagter",
|
||||
"email": "BackEndTea@gmail.com"
|
||||
},
|
||||
{
|
||||
"name": "Symfony Community",
|
||||
"homepage": "https://symfony.com/contributors"
|
||||
}
|
||||
],
|
||||
"description": "Symfony polyfill for ctype functions",
|
||||
"homepage": "https://symfony.com",
|
||||
"keywords": [
|
||||
"compatibility",
|
||||
"ctype",
|
||||
"polyfill",
|
||||
"portable"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/polyfill-ctype/tree/v1.27.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://symfony.com/sponsor",
|
||||
"type": "custom"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/fabpot",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2022-11-03T14:55:06+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-intl-grapheme",
|
||||
"version": "v1.27.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-intl-grapheme.git",
|
||||
"reference": "511a08c03c1960e08a883f4cffcacd219b758354"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/511a08c03c1960e08a883f4cffcacd219b758354",
|
||||
"reference": "511a08c03c1960e08a883f4cffcacd219b758354",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=7.1"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-intl": "For best performance"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-main": "1.27-dev"
|
||||
},
|
||||
"thanks": {
|
||||
"name": "symfony/polyfill",
|
||||
"url": "https://github.com/symfony/polyfill"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"files": [
|
||||
"bootstrap.php"
|
||||
],
|
||||
"psr-4": {
|
||||
"Symfony\\Polyfill\\Intl\\Grapheme\\": ""
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Nicolas Grekas",
|
||||
"email": "p@tchwork.com"
|
||||
},
|
||||
{
|
||||
"name": "Symfony Community",
|
||||
"homepage": "https://symfony.com/contributors"
|
||||
}
|
||||
],
|
||||
"description": "Symfony polyfill for intl's grapheme_* functions",
|
||||
"homepage": "https://symfony.com",
|
||||
"keywords": [
|
||||
"compatibility",
|
||||
"grapheme",
|
||||
"intl",
|
||||
"polyfill",
|
||||
"portable",
|
||||
"shim"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.27.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://symfony.com/sponsor",
|
||||
"type": "custom"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/fabpot",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2022-11-03T14:55:06+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-intl-normalizer",
|
||||
"version": "v1.27.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-intl-normalizer.git",
|
||||
"reference": "19bd1e4fcd5b91116f14d8533c57831ed00571b6"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/19bd1e4fcd5b91116f14d8533c57831ed00571b6",
|
||||
"reference": "19bd1e4fcd5b91116f14d8533c57831ed00571b6",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=7.1"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-intl": "For best performance"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-main": "1.27-dev"
|
||||
},
|
||||
"thanks": {
|
||||
"name": "symfony/polyfill",
|
||||
"url": "https://github.com/symfony/polyfill"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"files": [
|
||||
"bootstrap.php"
|
||||
],
|
||||
"psr-4": {
|
||||
"Symfony\\Polyfill\\Intl\\Normalizer\\": ""
|
||||
},
|
||||
"classmap": [
|
||||
"Resources/stubs"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Nicolas Grekas",
|
||||
"email": "p@tchwork.com"
|
||||
},
|
||||
{
|
||||
"name": "Symfony Community",
|
||||
"homepage": "https://symfony.com/contributors"
|
||||
}
|
||||
],
|
||||
"description": "Symfony polyfill for intl's Normalizer class and related functions",
|
||||
"homepage": "https://symfony.com",
|
||||
"keywords": [
|
||||
"compatibility",
|
||||
"intl",
|
||||
"normalizer",
|
||||
"polyfill",
|
||||
"portable",
|
||||
"shim"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.27.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://symfony.com/sponsor",
|
||||
"type": "custom"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/fabpot",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2022-11-03T14:55:06+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-mbstring",
|
||||
"version": "v1.27.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-mbstring.git",
|
||||
"reference": "8ad114f6b39e2c98a8b0e3bd907732c207c2b534"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/8ad114f6b39e2c98a8b0e3bd907732c207c2b534",
|
||||
"reference": "8ad114f6b39e2c98a8b0e3bd907732c207c2b534",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=7.1"
|
||||
},
|
||||
"provide": {
|
||||
"ext-mbstring": "*"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-mbstring": "For best performance"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-main": "1.27-dev"
|
||||
},
|
||||
"thanks": {
|
||||
"name": "symfony/polyfill",
|
||||
"url": "https://github.com/symfony/polyfill"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"files": [
|
||||
"bootstrap.php"
|
||||
],
|
||||
"psr-4": {
|
||||
"Symfony\\Polyfill\\Mbstring\\": ""
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Nicolas Grekas",
|
||||
"email": "p@tchwork.com"
|
||||
},
|
||||
{
|
||||
"name": "Symfony Community",
|
||||
"homepage": "https://symfony.com/contributors"
|
||||
}
|
||||
],
|
||||
"description": "Symfony polyfill for the Mbstring extension",
|
||||
"homepage": "https://symfony.com",
|
||||
"keywords": [
|
||||
"compatibility",
|
||||
"mbstring",
|
||||
"polyfill",
|
||||
"portable",
|
||||
"shim"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/polyfill-mbstring/tree/v1.27.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://symfony.com/sponsor",
|
||||
"type": "custom"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/fabpot",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2022-11-03T14:55:06+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/property-access",
|
||||
"version": "v6.3.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/property-access.git",
|
||||
"reference": "db9358571ce63f09c439c2fee6c12e5b090b69ac"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/property-access/zipball/db9358571ce63f09c439c2fee6c12e5b090b69ac",
|
||||
"reference": "db9358571ce63f09c439c2fee6c12e5b090b69ac",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=8.1",
|
||||
"symfony/deprecation-contracts": "^2.5|^3",
|
||||
"symfony/property-info": "^5.4|^6.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"symfony/cache": "^5.4|^6.0"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Symfony\\Component\\PropertyAccess\\": ""
|
||||
},
|
||||
"exclude-from-classmap": [
|
||||
"/Tests/"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Fabien Potencier",
|
||||
"email": "fabien@symfony.com"
|
||||
},
|
||||
{
|
||||
"name": "Symfony Community",
|
||||
"homepage": "https://symfony.com/contributors"
|
||||
}
|
||||
],
|
||||
"description": "Provides functions to read and write from/to an object or array using a simple string notation",
|
||||
"homepage": "https://symfony.com",
|
||||
"keywords": [
|
||||
"access",
|
||||
"array",
|
||||
"extraction",
|
||||
"index",
|
||||
"injection",
|
||||
"object",
|
||||
"property",
|
||||
"property-path",
|
||||
"reflection"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/property-access/tree/v6.3.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://symfony.com/sponsor",
|
||||
"type": "custom"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/fabpot",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2023-05-19T08:06:44+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/property-info",
|
||||
"version": "v6.3.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/property-info.git",
|
||||
"reference": "7f3a03716112269741fe2a809f8f791a371d1fcd"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/property-info/zipball/7f3a03716112269741fe2a809f8f791a371d1fcd",
|
||||
"reference": "7f3a03716112269741fe2a809f8f791a371d1fcd",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=8.1",
|
||||
"symfony/string": "^5.4|^6.0"
|
||||
},
|
||||
"conflict": {
|
||||
"phpdocumentor/reflection-docblock": "<5.2",
|
||||
"phpdocumentor/type-resolver": "<1.5.1",
|
||||
"symfony/dependency-injection": "<5.4"
|
||||
},
|
||||
"require-dev": {
|
||||
"doctrine/annotations": "^1.10.4|^2",
|
||||
"phpdocumentor/reflection-docblock": "^5.2",
|
||||
"phpstan/phpdoc-parser": "^1.0",
|
||||
"symfony/cache": "^5.4|^6.0",
|
||||
"symfony/dependency-injection": "^5.4|^6.0",
|
||||
"symfony/serializer": "^5.4|^6.0"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Symfony\\Component\\PropertyInfo\\": ""
|
||||
},
|
||||
"exclude-from-classmap": [
|
||||
"/Tests/"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Kévin Dunglas",
|
||||
"email": "dunglas@gmail.com"
|
||||
},
|
||||
{
|
||||
"name": "Symfony Community",
|
||||
"homepage": "https://symfony.com/contributors"
|
||||
}
|
||||
],
|
||||
"description": "Extracts information about PHP class' properties using metadata of popular sources",
|
||||
"homepage": "https://symfony.com",
|
||||
"keywords": [
|
||||
"doctrine",
|
||||
"phpdoc",
|
||||
"property",
|
||||
"symfony",
|
||||
"type",
|
||||
"validator"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/property-info/tree/v6.3.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://symfony.com/sponsor",
|
||||
"type": "custom"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/fabpot",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2023-05-19T08:06:44+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/serializer",
|
||||
"version": "v6.3.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/serializer.git",
|
||||
"reference": "1d238ee3180bc047f8ab713bfb73848d553f4407"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/serializer/zipball/1d238ee3180bc047f8ab713bfb73848d553f4407",
|
||||
"reference": "1d238ee3180bc047f8ab713bfb73848d553f4407",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=8.1",
|
||||
"symfony/polyfill-ctype": "~1.8"
|
||||
},
|
||||
"conflict": {
|
||||
"doctrine/annotations": "<1.12",
|
||||
"phpdocumentor/reflection-docblock": "<3.2.2",
|
||||
"phpdocumentor/type-resolver": "<1.4.0",
|
||||
"symfony/dependency-injection": "<5.4",
|
||||
"symfony/property-access": "<5.4",
|
||||
"symfony/property-info": "<5.4",
|
||||
"symfony/uid": "<5.4",
|
||||
"symfony/yaml": "<5.4"
|
||||
},
|
||||
"require-dev": {
|
||||
"doctrine/annotations": "^1.12|^2",
|
||||
"phpdocumentor/reflection-docblock": "^3.2|^4.0|^5.0",
|
||||
"symfony/cache": "^5.4|^6.0",
|
||||
"symfony/config": "^5.4|^6.0",
|
||||
"symfony/console": "^5.4|^6.0",
|
||||
"symfony/dependency-injection": "^5.4|^6.0",
|
||||
"symfony/error-handler": "^5.4|^6.0",
|
||||
"symfony/filesystem": "^5.4|^6.0",
|
||||
"symfony/form": "^5.4|^6.0",
|
||||
"symfony/http-foundation": "^5.4|^6.0",
|
||||
"symfony/http-kernel": "^5.4|^6.0",
|
||||
"symfony/mime": "^5.4|^6.0",
|
||||
"symfony/property-access": "^5.4|^6.0",
|
||||
"symfony/property-info": "^5.4|^6.0",
|
||||
"symfony/uid": "^5.4|^6.0",
|
||||
"symfony/validator": "^5.4|^6.0",
|
||||
"symfony/var-dumper": "^5.4|^6.0",
|
||||
"symfony/var-exporter": "^5.4|^6.0",
|
||||
"symfony/yaml": "^5.4|^6.0"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Symfony\\Component\\Serializer\\": ""
|
||||
},
|
||||
"exclude-from-classmap": [
|
||||
"/Tests/"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Fabien Potencier",
|
||||
"email": "fabien@symfony.com"
|
||||
},
|
||||
{
|
||||
"name": "Symfony Community",
|
||||
"homepage": "https://symfony.com/contributors"
|
||||
}
|
||||
],
|
||||
"description": "Handles serializing and deserializing data structures, including object graphs, into array structures or other formats like XML and JSON.",
|
||||
"homepage": "https://symfony.com",
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/serializer/tree/v6.3.1"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://symfony.com/sponsor",
|
||||
"type": "custom"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/fabpot",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2023-06-21T19:54:33+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/string",
|
||||
"version": "v6.3.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/string.git",
|
||||
"reference": "f2e190ee75ff0f5eced645ec0be5c66fac81f51f"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/string/zipball/f2e190ee75ff0f5eced645ec0be5c66fac81f51f",
|
||||
"reference": "f2e190ee75ff0f5eced645ec0be5c66fac81f51f",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=8.1",
|
||||
"symfony/polyfill-ctype": "~1.8",
|
||||
"symfony/polyfill-intl-grapheme": "~1.0",
|
||||
"symfony/polyfill-intl-normalizer": "~1.0",
|
||||
"symfony/polyfill-mbstring": "~1.0"
|
||||
},
|
||||
"conflict": {
|
||||
"symfony/translation-contracts": "<2.5"
|
||||
},
|
||||
"require-dev": {
|
||||
"symfony/error-handler": "^5.4|^6.0",
|
||||
"symfony/http-client": "^5.4|^6.0",
|
||||
"symfony/intl": "^6.2",
|
||||
"symfony/translation-contracts": "^2.5|^3.0",
|
||||
"symfony/var-exporter": "^5.4|^6.0"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"files": [
|
||||
"Resources/functions.php"
|
||||
],
|
||||
"psr-4": {
|
||||
"Symfony\\Component\\String\\": ""
|
||||
},
|
||||
"exclude-from-classmap": [
|
||||
"/Tests/"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Nicolas Grekas",
|
||||
"email": "p@tchwork.com"
|
||||
},
|
||||
{
|
||||
"name": "Symfony Community",
|
||||
"homepage": "https://symfony.com/contributors"
|
||||
}
|
||||
],
|
||||
"description": "Provides an object-oriented API to strings and deals with bytes, UTF-8 code points and grapheme clusters in a unified way",
|
||||
"homepage": "https://symfony.com",
|
||||
"keywords": [
|
||||
"grapheme",
|
||||
"i18n",
|
||||
"string",
|
||||
"unicode",
|
||||
"utf-8",
|
||||
"utf8"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/string/tree/v6.3.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://symfony.com/sponsor",
|
||||
"type": "custom"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/fabpot",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2023-03-21T21:06:29+00:00"
|
||||
}
|
||||
],
|
||||
"packages-dev": [
|
||||
|
||||
@ -15,17 +15,15 @@
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
namespace Example\Configuration;
|
||||
namespace OnlineEditorsExamplePhp\Configuration;
|
||||
|
||||
use Example\Common\Path;
|
||||
use Example\Common\URL;
|
||||
use OnlineEditorsExamplePhp\Common\Path;
|
||||
use OnlineEditorsExamplePhp\Common\URL;
|
||||
|
||||
class ConfigurationManager
|
||||
{
|
||||
final class ConfigurationManager {
|
||||
public string $version = '1.6.0';
|
||||
|
||||
public function exampleURL(): ?URL
|
||||
{
|
||||
public function example_url(): ?URL {
|
||||
$url = getenv('EXAMPLE_URL');
|
||||
if (!$url) {
|
||||
return null;
|
||||
@ -33,65 +31,48 @@ class ConfigurationManager
|
||||
return new URL($url);
|
||||
}
|
||||
|
||||
public function documentServerPublicURL(): URL
|
||||
{
|
||||
$url = getenv('DOCUMENT_SERVER_PUBLIC_URL') ?: 'http://document-server';
|
||||
public function document_server_url(): URL {
|
||||
$url = getenv('DOCUMENT_SERVER_URL') ?: 'http://document-server';
|
||||
return new URL($url);
|
||||
}
|
||||
|
||||
public function documentServerPrivateURL(): URL
|
||||
{
|
||||
$url = getenv('DOCUMENT_SERVER_PRIVATE_URL');
|
||||
if (!$url) {
|
||||
return $this->documentServerPublicURL();
|
||||
}
|
||||
return new URL($url);
|
||||
}
|
||||
|
||||
public function documentServerAPIURL(): URL
|
||||
{
|
||||
$serverURL = $this->documentServerPublicURL();
|
||||
public function document_server_api_url(): URL {
|
||||
$server_url = $this->document_server_url();
|
||||
$path = getenv('DOCUMENT_SERVER_API_PATH')
|
||||
?: 'web-apps/apps/api/documents/api.js';
|
||||
return $serverURL->joinPath($path);
|
||||
return $server_url->join_path($path);
|
||||
}
|
||||
|
||||
public function documentServerPreloaderURL(): URL
|
||||
{
|
||||
$serverURL = $this->documentServerPublicURL();
|
||||
public function document_server_preloader_url(): URL {
|
||||
$server_url = $this->document_server_url();
|
||||
$path = getenv('DOCUMENT_SERVER_PRELOADER_PATH')
|
||||
?: 'web-apps/apps/api/documents/cache-scripts.html';
|
||||
return $serverURL->joinPath($path);
|
||||
return $server_url->join_path($path);
|
||||
}
|
||||
|
||||
public function documentServerCommandURL(): URL
|
||||
{
|
||||
$serverURL = $this->documentServerPrivateURL();
|
||||
public function document_server_command_url(): URL {
|
||||
$server_url = $this->document_server_url();
|
||||
$path = getenv('DOCUMENT_SERVER_COMMAND_PATH')
|
||||
?: 'coauthoring/CommandService.ashx';
|
||||
return $serverURL->joinPath($path);
|
||||
return $server_url->join_path($path);
|
||||
}
|
||||
|
||||
public function documentServerConverterURL(): URL
|
||||
{
|
||||
$serverURL = $this->documentServerPrivateURL();
|
||||
public function document_server_converter_url(): URL {
|
||||
$server_url = $this->document_server_url();
|
||||
$path = getenv('DOCUMENT_SERVER_CONVERTER_PATH')
|
||||
?: 'ConvertService.ashx';
|
||||
return $serverURL->joinPath($path);
|
||||
return $server_url->join_path($path);
|
||||
}
|
||||
|
||||
public function jwtSecret(): string
|
||||
{
|
||||
public function jwt_secret(): string {
|
||||
return getenv('JWT_SECRET') ?: '';
|
||||
}
|
||||
|
||||
public function jwtHeader(): string
|
||||
{
|
||||
public function jwt_header(): string {
|
||||
return getenv('JWT_HEADER') ?: 'Authorization';
|
||||
}
|
||||
|
||||
public function jwtUseForRequest(): bool
|
||||
{
|
||||
public function jwt_use_for_request(): bool {
|
||||
$use = getenv('JWT_USE_FOR_REQUEST');
|
||||
if (!$use) {
|
||||
return true;
|
||||
@ -99,8 +80,7 @@ class ConfigurationManager
|
||||
return filter_var($use, FILTER_VALIDATE_BOOLEAN);
|
||||
}
|
||||
|
||||
public function sslVerifyPeerModeEnabled(): bool
|
||||
{
|
||||
public function ssl_verify_peer_mode_enabled(): bool {
|
||||
$enabled = getenv('SSL_VERIFY_PEER_MODE_ENABLED');
|
||||
if (!$enabled) {
|
||||
return false;
|
||||
@ -108,25 +88,22 @@ class ConfigurationManager
|
||||
return filter_var($enabled, FILTER_VALIDATE_BOOLEAN);
|
||||
}
|
||||
|
||||
public function storagePath(): Path
|
||||
{
|
||||
$storagePath = getenv('STORAGE_PATH') ?: 'storage';
|
||||
$storageDirectory = new Path($storagePath);
|
||||
if ($storageDirectory->absolute()) {
|
||||
return $storageDirectory;
|
||||
public function storage_path(): Path {
|
||||
$storage_path = getenv('STORAGE_PATH') ?: 'storage';
|
||||
$storage_directory = new Path($storage_path);
|
||||
if ($storage_directory->absolute()) {
|
||||
return $storage_directory;
|
||||
}
|
||||
|
||||
$storageStringDirectory = $storageDirectory->string();
|
||||
$currentDirectory = new Path(__DIR__);
|
||||
$directory = $currentDirectory
|
||||
->joinPath('..')
|
||||
->joinPath('..')
|
||||
->joinPath($storageStringDirectory);
|
||||
$storage_string_directory = $storage_directory->string();
|
||||
$current_directory = new Path(__DIR__);
|
||||
$directory = $current_directory
|
||||
->join_path('..')
|
||||
->join_path($storage_string_directory);
|
||||
return $directory->normalize();
|
||||
}
|
||||
|
||||
public function singleUser(): bool
|
||||
{
|
||||
public function single_user(): bool {
|
||||
$single = getenv('SINGLE_USER');
|
||||
if (!$single) {
|
||||
return false;
|
||||
@ -134,8 +111,7 @@ class ConfigurationManager
|
||||
return filter_var($single, FILTER_VALIDATE_BOOLEAN);
|
||||
}
|
||||
|
||||
public function maximumFileSize(): int
|
||||
{
|
||||
public function maximum_file_size(): int {
|
||||
$size = getenv('MAXIMUM_FILE_SIZE');
|
||||
if (!$size) {
|
||||
return 5 * 1024 * 1024;
|
||||
@ -143,8 +119,7 @@ class ConfigurationManager
|
||||
return intval($size);
|
||||
}
|
||||
|
||||
public function conversionTimeout(): int
|
||||
{
|
||||
public function conversion_timeout(): int {
|
||||
$timeout = getenv('CONVERSION_TIMEOUT');
|
||||
if (!$timeout) {
|
||||
return 120 * 1000;
|
||||
@ -155,8 +130,7 @@ class ConfigurationManager
|
||||
/**
|
||||
* @return string[]
|
||||
*/
|
||||
public function languages(): array
|
||||
{
|
||||
public function languages(): array {
|
||||
return [
|
||||
'en' => "English",
|
||||
'hy' => 'Armenian',
|
||||
@ -15,40 +15,33 @@
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
namespace Example\Configuration\Tests;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Example\Configuration\ConfigurationManager;
|
||||
use OnlineEditorsExamplePhp\Configuration\ConfigurationManager;
|
||||
|
||||
final class ConfigurationManagerConversionTimeoutTests extends TestCase
|
||||
{
|
||||
final class ConfigurationManagerConversionTimeoutTests extends TestCase {
|
||||
public array $env;
|
||||
|
||||
public function __construct(string $name)
|
||||
{
|
||||
public function __construct(string $name) {
|
||||
$this->env = getenv();
|
||||
parent::__construct($name);
|
||||
}
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
protected function setUp(): void {
|
||||
foreach ($this->env as $key => $value) {
|
||||
putenv("{$key}={$value}");
|
||||
}
|
||||
}
|
||||
|
||||
public function testAssignsADefaultValue()
|
||||
{
|
||||
$configManager = new ConfigurationManager();
|
||||
$timeout = $configManager->conversionTimeout();
|
||||
public function test_assigns_a_default_value() {
|
||||
$config_manager = new ConfigurationManager();
|
||||
$timeout = $config_manager->conversion_timeout();
|
||||
$this->assertEquals(120_000, $timeout);
|
||||
}
|
||||
|
||||
public function testAssignsAValueFromTheEnvironment()
|
||||
{
|
||||
public function test_assigns_a_value_from_the_environment() {
|
||||
putenv('CONVERSION_TIMEOUT=10');
|
||||
$configManager = new ConfigurationManager();
|
||||
$timeout = $configManager->conversionTimeout();
|
||||
$config_manager = new ConfigurationManager();
|
||||
$timeout = $config_manager->conversion_timeout();
|
||||
$this->assertEquals(10, $timeout);
|
||||
}
|
||||
}
|
||||
@ -15,43 +15,36 @@
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
namespace Example\Configuration\Tests;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Example\Configuration\ConfigurationManager;
|
||||
use OnlineEditorsExamplePhp\Configuration\ConfigurationManager;
|
||||
|
||||
final class ConfigurationManagerDocumentServerAPIURLTests extends TestCase
|
||||
{
|
||||
final class ConfigurationManagerDocumentServerAPIURLTests extends TestCase {
|
||||
public array $env;
|
||||
|
||||
public function __construct(string $name)
|
||||
{
|
||||
public function __construct(string $name) {
|
||||
$this->env = getenv();
|
||||
parent::__construct($name);
|
||||
}
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
protected function setUp(): void {
|
||||
foreach ($this->env as $key => $value) {
|
||||
putenv("{$key}={$value}");
|
||||
}
|
||||
}
|
||||
|
||||
public function testAssignsADefaultValue()
|
||||
{
|
||||
$configManager = new ConfigurationManager();
|
||||
$url = $configManager->documentServerAPIURL();
|
||||
public function test_assigns_a_default_value() {
|
||||
$config_manager = new ConfigurationManager();
|
||||
$url = $config_manager->document_server_api_url();
|
||||
$this->assertEquals(
|
||||
'http://document-server/web-apps/apps/api/documents/api.js',
|
||||
$url->string()
|
||||
);
|
||||
}
|
||||
|
||||
public function testAssignsAValueFromTheEnvironment()
|
||||
{
|
||||
public function test_assigns_a_value_from_the_environment() {
|
||||
putenv('DOCUMENT_SERVER_API_PATH=/api');
|
||||
$configManager = new ConfigurationManager();
|
||||
$url = $configManager->documentServerAPIURL();
|
||||
$config_manager = new ConfigurationManager();
|
||||
$url = $config_manager->document_server_api_url();
|
||||
$this->assertEquals(
|
||||
'http://document-server/api',
|
||||
$url->string()
|
||||
@ -15,43 +15,36 @@
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
namespace Example\Configuration\Tests;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Example\Configuration\ConfigurationManager;
|
||||
use OnlineEditorsExamplePhp\Configuration\ConfigurationManager;
|
||||
|
||||
final class ConfigurationManagerDocumentServerCommandURLTests extends TestCase
|
||||
{
|
||||
final class ConfigurationManagerDocumentServerCommandURLTests extends TestCase {
|
||||
public array $env;
|
||||
|
||||
public function __construct(string $name)
|
||||
{
|
||||
public function __construct(string $name) {
|
||||
$this->env = getenv();
|
||||
parent::__construct($name);
|
||||
}
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
protected function setUp(): void {
|
||||
foreach ($this->env as $key => $value) {
|
||||
putenv("{$key}={$value}");
|
||||
}
|
||||
}
|
||||
|
||||
public function testAssignsADefaultValue()
|
||||
{
|
||||
$configManager = new ConfigurationManager();
|
||||
$url = $configManager->documentServerCommandURL();
|
||||
public function test_assigns_a_default_value() {
|
||||
$config_manager = new ConfigurationManager();
|
||||
$url = $config_manager->document_server_command_url();
|
||||
$this->assertEquals(
|
||||
'http://document-server/coauthoring/CommandService.ashx',
|
||||
$url->string()
|
||||
);
|
||||
}
|
||||
|
||||
public function testAssignsAValueFromTheEnvironment()
|
||||
{
|
||||
public function test_assigns_a_value_from_the_environment() {
|
||||
putenv('DOCUMENT_SERVER_COMMAND_PATH=/command');
|
||||
$configManager = new ConfigurationManager();
|
||||
$url = $configManager->documentServerCommandURL();
|
||||
$config_manager = new ConfigurationManager();
|
||||
$url = $config_manager->document_server_command_url();
|
||||
$this->assertEquals(
|
||||
'http://document-server/command',
|
||||
$url->string()
|
||||
@ -15,43 +15,36 @@
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
namespace Example\Configuration\Tests;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Example\Configuration\ConfigurationManager;
|
||||
use OnlineEditorsExamplePhp\Configuration\ConfigurationManager;
|
||||
|
||||
final class ConfigurationManagerDocumentServerConverterURLTests extends TestCase
|
||||
{
|
||||
final class ConfigurationManagerDocumentServerConverterURLTests extends TestCase {
|
||||
public array $env;
|
||||
|
||||
public function __construct(string $name)
|
||||
{
|
||||
public function __construct(string $name) {
|
||||
$this->env = getenv();
|
||||
parent::__construct($name);
|
||||
}
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
protected function setUp(): void {
|
||||
foreach ($this->env as $key => $value) {
|
||||
putenv("{$key}={$value}");
|
||||
}
|
||||
}
|
||||
|
||||
public function testAssignsADefaultValue()
|
||||
{
|
||||
$configManager = new ConfigurationManager();
|
||||
$url = $configManager->documentServerConverterURL();
|
||||
public function test_assigns_a_default_value() {
|
||||
$config_manager = new ConfigurationManager();
|
||||
$url = $config_manager->document_server_converter_url();
|
||||
$this->assertEquals(
|
||||
'http://document-server/ConvertService.ashx',
|
||||
$url->string()
|
||||
);
|
||||
}
|
||||
|
||||
public function testAssignsAValueFromTheEnvironment()
|
||||
{
|
||||
public function test_assigns_a_value_from_the_environment() {
|
||||
putenv('DOCUMENT_SERVER_CONVERTER_PATH=/converter');
|
||||
$configManager = new ConfigurationManager();
|
||||
$url = $configManager->documentServerConverterURL();
|
||||
$config_manager = new ConfigurationManager();
|
||||
$url = $config_manager->document_server_converter_url();
|
||||
$this->assertEquals(
|
||||
'http://document-server/converter',
|
||||
$url->string()
|
||||
@ -15,43 +15,36 @@
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
namespace Example\Configuration\Tests;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Example\Configuration\ConfigurationManager;
|
||||
use OnlineEditorsExamplePhp\Configuration\ConfigurationManager;
|
||||
|
||||
final class ConfigurationManagerDocumentServerPreloaderURLTests extends TestCase
|
||||
{
|
||||
final class ConfigurationManagerDocumentServerPreloaderURLTests extends TestCase {
|
||||
public array $env;
|
||||
|
||||
public function __construct(string $name)
|
||||
{
|
||||
public function __construct(string $name) {
|
||||
$this->env = getenv();
|
||||
parent::__construct($name);
|
||||
}
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
protected function setUp(): void {
|
||||
foreach ($this->env as $key => $value) {
|
||||
putenv("{$key}={$value}");
|
||||
}
|
||||
}
|
||||
|
||||
public function testAssignsADefaultValue()
|
||||
{
|
||||
$configManager = new ConfigurationManager();
|
||||
$url = $configManager->documentServerPreloaderURL();
|
||||
public function test_assigns_a_default_value() {
|
||||
$config_manager = new ConfigurationManager();
|
||||
$url = $config_manager->document_server_preloader_url();
|
||||
$this->assertEquals(
|
||||
'http://document-server/web-apps/apps/api/documents/cache-scripts.html',
|
||||
$url->string()
|
||||
);
|
||||
}
|
||||
|
||||
public function testAssignsAValueFromTheEnvironment()
|
||||
{
|
||||
public function test_assigns_a_value_from_the_environment() {
|
||||
putenv('DOCUMENT_SERVER_PRELOADER_PATH=/preloader');
|
||||
$configManager = new ConfigurationManager();
|
||||
$url = $configManager->documentServerPreloaderURL();
|
||||
$config_manager = new ConfigurationManager();
|
||||
$url = $config_manager->document_server_preloader_url();
|
||||
$this->assertEquals(
|
||||
'http://document-server/preloader',
|
||||
$url->string()
|
||||
@ -15,40 +15,33 @@
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
namespace Example\Configuration\Tests;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Example\Configuration\ConfigurationManager;
|
||||
use OnlineEditorsExamplePhp\Configuration\ConfigurationManager;
|
||||
|
||||
final class ConfigurationManagerDocumentServerPublicURLTests extends TestCase
|
||||
{
|
||||
final class ConfigurationManagerDocumentServerURLTests extends TestCase {
|
||||
public array $env;
|
||||
|
||||
public function __construct(string $name)
|
||||
{
|
||||
public function __construct(string $name) {
|
||||
$this->env = getenv();
|
||||
parent::__construct($name);
|
||||
}
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
protected function setUp(): void {
|
||||
foreach ($this->env as $key => $value) {
|
||||
putenv("{$key}={$value}");
|
||||
}
|
||||
}
|
||||
|
||||
public function testAssignsADefaultValue()
|
||||
{
|
||||
$configManager = new ConfigurationManager();
|
||||
$url = $configManager->documentServerPublicURL();
|
||||
public function test_assigns_a_default_value() {
|
||||
$config_manager = new ConfigurationManager();
|
||||
$url = $config_manager->document_server_url();
|
||||
$this->assertEquals('http://document-server', $url->string());
|
||||
}
|
||||
|
||||
public function testAssignsAValueFromTheEnvironment()
|
||||
{
|
||||
putenv('DOCUMENT_SERVER_PUBLIC_URL=http://localhost');
|
||||
$configManager = new ConfigurationManager();
|
||||
$url = $configManager->documentServerPublicURL();
|
||||
public function test_assigns_a_value_from_the_environment() {
|
||||
putenv('DOCUMENT_SERVER_URL=http://localhost');
|
||||
$config_manager = new ConfigurationManager();
|
||||
$url = $config_manager->document_server_url();
|
||||
$this->assertEquals('http://localhost', $url->string());
|
||||
}
|
||||
}
|
||||
@ -15,40 +15,33 @@
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
namespace Example\Configuration\Tests;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Example\Configuration\ConfigurationManager;
|
||||
use OnlineEditorsExamplePhp\Configuration\ConfigurationManager;
|
||||
|
||||
final class ConfigurationManagerExampleURLTests extends TestCase
|
||||
{
|
||||
final class ConfigurationManagerExampleURLTests extends TestCase {
|
||||
public array $env;
|
||||
|
||||
public function __construct(string $name)
|
||||
{
|
||||
public function __construct(string $name) {
|
||||
$this->env = getenv();
|
||||
parent::__construct($name);
|
||||
}
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
protected function setUp(): void {
|
||||
foreach ($this->env as $key => $value) {
|
||||
putenv("{$key}={$value}");
|
||||
}
|
||||
}
|
||||
|
||||
public function testAssignsADefaultValue()
|
||||
{
|
||||
$configManager = new ConfigurationManager();
|
||||
$url = $configManager->exampleURL();
|
||||
public function test_assigns_a_default_value() {
|
||||
$config_manager = new ConfigurationManager();
|
||||
$url = $config_manager->example_url();
|
||||
$this->assertNull($url);
|
||||
}
|
||||
|
||||
public function testAssignsAValueFromTheEnvironment()
|
||||
{
|
||||
public function test_assigns_a_value_from_the_environment() {
|
||||
putenv('EXAMPLE_URL=http://localhost');
|
||||
$configManager = new ConfigurationManager();
|
||||
$url = $configManager->exampleURL();
|
||||
$config_manager = new ConfigurationManager();
|
||||
$url = $config_manager->example_url();
|
||||
$this->assertEquals('http://localhost', $url->string());
|
||||
}
|
||||
}
|
||||
@ -15,40 +15,33 @@
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
namespace Example\Configuration\Tests;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Example\Configuration\ConfigurationManager;
|
||||
use OnlineEditorsExamplePhp\Configuration\ConfigurationManager;
|
||||
|
||||
final class ConfigurationManagerJWTHeaderTests extends TestCase
|
||||
{
|
||||
final class ConfigurationManagerJWTHeaderTests extends TestCase {
|
||||
public array $env;
|
||||
|
||||
public function __construct(string $name)
|
||||
{
|
||||
public function __construct(string $name) {
|
||||
$this->env = getenv();
|
||||
parent::__construct($name);
|
||||
}
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
protected function setUp(): void {
|
||||
foreach ($this->env as $key => $value) {
|
||||
putenv("{$key}={$value}");
|
||||
}
|
||||
}
|
||||
|
||||
public function testAssignsADefaultValue()
|
||||
{
|
||||
$configManager = new ConfigurationManager();
|
||||
$header = $configManager->jwtHeader();
|
||||
public function test_assigns_a_default_value() {
|
||||
$config_manager = new ConfigurationManager();
|
||||
$header = $config_manager->jwt_header();
|
||||
$this->assertEquals('Authorization', $header);
|
||||
}
|
||||
|
||||
public function testAssignsAValueFromTheEnvironment()
|
||||
{
|
||||
public function test_assigns_a_value_from_the_environment() {
|
||||
putenv('JWT_HEADER=Proxy-Authorization');
|
||||
$configManager = new ConfigurationManager();
|
||||
$header = $configManager->jwtHeader();
|
||||
$config_manager = new ConfigurationManager();
|
||||
$header = $config_manager->jwt_header();
|
||||
$this->assertEquals('Proxy-Authorization', $header);
|
||||
}
|
||||
}
|
||||
@ -15,40 +15,33 @@
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
namespace Example\Configuration\Tests;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Example\Configuration\ConfigurationManager;
|
||||
use OnlineEditorsExamplePhp\Configuration\ConfigurationManager;
|
||||
|
||||
final class ConfigurationManagerJWTSecretTests extends TestCase
|
||||
{
|
||||
final class ConfigurationManagerJWTSecretTests extends TestCase {
|
||||
public array $env;
|
||||
|
||||
public function __construct(string $name)
|
||||
{
|
||||
public function __construct(string $name) {
|
||||
$this->env = getenv();
|
||||
parent::__construct($name);
|
||||
}
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
protected function setUp(): void {
|
||||
foreach ($this->env as $key => $value) {
|
||||
putenv("{$key}={$value}");
|
||||
}
|
||||
}
|
||||
|
||||
public function testAssignsADefaultValue()
|
||||
{
|
||||
$configManager = new ConfigurationManager();
|
||||
$secret = $configManager->jwtSecret();
|
||||
public function test_assigns_a_default_value() {
|
||||
$config_manager = new ConfigurationManager();
|
||||
$secret = $config_manager->jwt_secret();
|
||||
$this->assertEquals('', $secret);
|
||||
}
|
||||
|
||||
public function testAssignsAValueFromTheEnvironment()
|
||||
{
|
||||
public function test_assigns_a_value_from_the_environment() {
|
||||
putenv('JWT_SECRET=your-256-bit-secret');
|
||||
$configManager = new ConfigurationManager();
|
||||
$secret = $configManager->jwtSecret();
|
||||
$config_manager = new ConfigurationManager();
|
||||
$secret = $config_manager->jwt_secret();
|
||||
$this->assertEquals('your-256-bit-secret', $secret);
|
||||
}
|
||||
}
|
||||
@ -15,40 +15,33 @@
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
namespace Example\Configuration\Tests;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Example\Configuration\ConfigurationManager;
|
||||
use OnlineEditorsExamplePhp\Configuration\ConfigurationManager;
|
||||
|
||||
final class ConfigurationManagerJWTUseForRequest extends TestCase
|
||||
{
|
||||
final class ConfigurationManagerJWTUseForRequest extends TestCase {
|
||||
public array $env;
|
||||
|
||||
public function __construct(string $name)
|
||||
{
|
||||
public function __construct(string $name) {
|
||||
$this->env = getenv();
|
||||
parent::__construct($name);
|
||||
}
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
protected function setUp(): void {
|
||||
foreach ($this->env as $key => $value) {
|
||||
putenv("{$key}={$value}");
|
||||
}
|
||||
}
|
||||
|
||||
public function testAssignsADefaultValue()
|
||||
{
|
||||
$configManager = new ConfigurationManager();
|
||||
$use = $configManager->jwtUseForRequest();
|
||||
public function test_assigns_a_default_value() {
|
||||
$config_manager = new ConfigurationManager();
|
||||
$use = $config_manager->jwt_use_for_request();
|
||||
$this->assertTrue($use);
|
||||
}
|
||||
|
||||
public function testAssignsAValueFromTheEnvironment()
|
||||
{
|
||||
public function test_assigns_a_value_from_the_environment() {
|
||||
putenv('JWT_USE_FOR_REQUEST=false');
|
||||
$configManager = new ConfigurationManager();
|
||||
$use = $configManager->jwtUseForRequest();
|
||||
$config_manager = new ConfigurationManager();
|
||||
$use = $config_manager->jwt_use_for_request();
|
||||
$this->assertFalse($use);
|
||||
}
|
||||
}
|
||||
@ -15,40 +15,33 @@
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
namespace Example\Configuration\Tests;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Example\Configuration\ConfigurationManager;
|
||||
use OnlineEditorsExamplePhp\Configuration\ConfigurationManager;
|
||||
|
||||
final class ConfigurationManagerMaximumFileSizeTests extends TestCase
|
||||
{
|
||||
final class ConfigurationManagerMaximumFileSizeTests extends TestCase {
|
||||
public array $env;
|
||||
|
||||
public function __construct(string $name)
|
||||
{
|
||||
public function __construct(string $name) {
|
||||
$this->env = getenv();
|
||||
parent::__construct($name);
|
||||
}
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
protected function setUp(): void {
|
||||
foreach ($this->env as $key => $value) {
|
||||
putenv("{$key}={$value}");
|
||||
}
|
||||
}
|
||||
|
||||
public function testAssignsADefaultValue()
|
||||
{
|
||||
$configManager = new ConfigurationManager();
|
||||
$size = $configManager->maximumFileSize();
|
||||
public function test_assigns_a_default_value() {
|
||||
$config_manager = new ConfigurationManager();
|
||||
$size = $config_manager->maximum_file_size();
|
||||
$this->assertEquals(5_242_880, $size);
|
||||
}
|
||||
|
||||
public function testAssignsAValueFromTheEnvironment()
|
||||
{
|
||||
public function test_assigns_a_value_from_the_environment() {
|
||||
putenv('MAXIMUM_FILE_SIZE=10');
|
||||
$configManager = new ConfigurationManager();
|
||||
$size = $configManager->maximumFileSize();
|
||||
$config_manager = new ConfigurationManager();
|
||||
$size = $config_manager->maximum_file_size();
|
||||
$this->assertEquals(10, $size);
|
||||
}
|
||||
}
|
||||
@ -15,40 +15,33 @@
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
namespace Example\Configuration\Tests;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Example\Configuration\ConfigurationManager;
|
||||
use OnlineEditorsExamplePhp\Configuration\ConfigurationManager;
|
||||
|
||||
final class ConfigurationManagerSSLTests extends TestCase
|
||||
{
|
||||
final class ConfigurationManagerSSLTests extends TestCase {
|
||||
public array $env;
|
||||
|
||||
public function __construct(string $name)
|
||||
{
|
||||
public function __construct(string $name) {
|
||||
$this->env = getenv();
|
||||
parent::__construct($name);
|
||||
}
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
protected function setUp(): void {
|
||||
foreach ($this->env as $key => $value) {
|
||||
putenv("{$key}={$value}");
|
||||
}
|
||||
}
|
||||
|
||||
public function testAssignsADefaultValue()
|
||||
{
|
||||
$configManager = new ConfigurationManager();
|
||||
$enabled = $configManager->sslVerifyPeerModeEnabled();
|
||||
public function test_assigns_a_default_value() {
|
||||
$config_manager = new ConfigurationManager();
|
||||
$enabled = $config_manager->ssl_verify_peer_mode_enabled();
|
||||
$this->assertFalse($enabled);
|
||||
}
|
||||
|
||||
public function testAssignsAValueFromTheEnvironment()
|
||||
{
|
||||
public function test_assigns_a_value_from_the_environment() {
|
||||
putenv('SSL_VERIFY_PEER_MODE_ENABLED=true');
|
||||
$configManager = new ConfigurationManager();
|
||||
$enabled = $configManager->sslVerifyPeerModeEnabled();
|
||||
$config_manager = new ConfigurationManager();
|
||||
$enabled = $config_manager->ssl_verify_peer_mode_enabled();
|
||||
$this->assertTrue($enabled);
|
||||
}
|
||||
}
|
||||
@ -15,40 +15,33 @@
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
namespace Example\Configuration\Tests;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Example\Configuration\ConfigurationManager;
|
||||
use OnlineEditorsExamplePhp\Configuration\ConfigurationManager;
|
||||
|
||||
final class ConfigurationManagerSingleUserTests extends TestCase
|
||||
{
|
||||
final class ConfigurationManagerSingleUserTests extends TestCase {
|
||||
public array $env;
|
||||
|
||||
public function __construct(string $name)
|
||||
{
|
||||
public function __construct(string $name) {
|
||||
$this->env = getenv();
|
||||
parent::__construct($name);
|
||||
}
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
protected function setUp(): void {
|
||||
foreach ($this->env as $key => $value) {
|
||||
putenv("{$key}={$value}");
|
||||
}
|
||||
}
|
||||
|
||||
public function testAssignsADefaultValue()
|
||||
{
|
||||
$configManager = new ConfigurationManager();
|
||||
$single = $configManager->singleUser();
|
||||
public function test_assigns_a_default_value() {
|
||||
$config_manager = new ConfigurationManager();
|
||||
$single = $config_manager->single_user();
|
||||
$this->assertFalse($single);
|
||||
}
|
||||
|
||||
public function testAssignsAValueFromTheEnvironment()
|
||||
{
|
||||
public function test_assigns_a_value_from_the_environment() {
|
||||
putenv('SINGLE_USER=true');
|
||||
$configManager = new ConfigurationManager();
|
||||
$single = $configManager->singleUser();
|
||||
$config_manager = new ConfigurationManager();
|
||||
$single = $config_manager->single_user();
|
||||
$this->assertTrue($single);
|
||||
}
|
||||
}
|
||||
@ -15,50 +15,42 @@
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
namespace Example\Configuration\Tests;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Example\Configuration\ConfigurationManager;
|
||||
use OnlineEditorsExamplePhp\Configuration\ConfigurationManager;
|
||||
|
||||
final class ConfigurationManagerStoragePathTests extends TestCase
|
||||
{
|
||||
final class ConfigurationManagerStoragePathTests extends TestCase {
|
||||
public array $env;
|
||||
|
||||
public function __construct(string $name)
|
||||
{
|
||||
public function __construct(string $name) {
|
||||
$this->env = getenv();
|
||||
parent::__construct($name);
|
||||
}
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
protected function setUp(): void {
|
||||
foreach ($this->env as $key => $value) {
|
||||
putenv("{$key}={$value}");
|
||||
}
|
||||
}
|
||||
|
||||
public function testAssignsADefaultValue()
|
||||
{
|
||||
$configManager = new ConfigurationManager();
|
||||
$path = $configManager->storagePath();
|
||||
public function test_assigns_a_default_value() {
|
||||
$config_manager = new ConfigurationManager();
|
||||
$path = $config_manager->storage_path();
|
||||
$this->assertTrue($path->absolute());
|
||||
$this->assertEquals($path->basename(), 'storage');
|
||||
}
|
||||
|
||||
public function testAssignsARelativePathFromTheEnvironment()
|
||||
{
|
||||
public function test_assigns_a_relative_path_from_the_environment() {
|
||||
putenv('STORAGE_PATH=directory');
|
||||
$configManager = new ConfigurationManager();
|
||||
$path = $configManager->storagePath();
|
||||
$config_manager = new ConfigurationManager();
|
||||
$path = $config_manager->storage_path();
|
||||
$this->assertTrue($path->absolute());
|
||||
$this->assertEquals($path->basename(), 'directory');
|
||||
}
|
||||
|
||||
public function testAssignsAnAbsolutePathFromTheEnvironment()
|
||||
{
|
||||
public function test_assigns_an_absolute_path_from_the_environment() {
|
||||
putenv('STORAGE_PATH=/directory');
|
||||
$configManager = new ConfigurationManager();
|
||||
$path = $configManager->storagePath();
|
||||
$config_manager = new ConfigurationManager();
|
||||
$path = $config_manager->storage_path();
|
||||
$this->assertEquals($path->string(), '/directory');
|
||||
}
|
||||
}
|
||||
@ -15,17 +15,12 @@
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
namespace Example\Format\Tests;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Example\Format\FormatManager;
|
||||
use OnlineEditorsExamplePhp\Configuration\ConfigurationManager;
|
||||
|
||||
final class FormatManagerEditableTests extends TestCase
|
||||
{
|
||||
public function testLoads()
|
||||
{
|
||||
$formatManager = new FormatManager();
|
||||
$formats = $formatManager->editable();
|
||||
$this->assertNotEmpty($formats);
|
||||
final class ConfigurationManagerTests extends TestCase {
|
||||
public function test_corresponds_the_latest_version() {
|
||||
$config_manager = new ConfigurationManager();
|
||||
$this->assertEquals('1.6.0', $config_manager->version);
|
||||
}
|
||||
}
|
||||
|
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 2.0 KiB |
|
Before Width: | Height: | Size: 8.2 KiB After Width: | Height: | Size: 8.2 KiB |
|
Before Width: | Height: | Size: 781 B After Width: | Height: | Size: 781 B |
|
Before Width: | Height: | Size: 547 B After Width: | Height: | Size: 547 B |
|
Before Width: | Height: | Size: 425 B After Width: | Height: | Size: 425 B |
|
Before Width: | Height: | Size: 331 B After Width: | Height: | Size: 331 B |
|
Before Width: | Height: | Size: 507 B After Width: | Height: | Size: 507 B |
|
Before Width: | Height: | Size: 757 B After Width: | Height: | Size: 757 B |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 593 B After Width: | Height: | Size: 593 B |
|
Before Width: | Height: | Size: 738 B After Width: | Height: | Size: 738 B |
|
Before Width: | Height: | Size: 477 B After Width: | Height: | Size: 477 B |
|
Before Width: | Height: | Size: 691 B After Width: | Height: | Size: 691 B |
|
Before Width: | Height: | Size: 992 B After Width: | Height: | Size: 992 B |
|
Before Width: | Height: | Size: 1004 B After Width: | Height: | Size: 1004 B |
|
Before Width: | Height: | Size: 379 B After Width: | Height: | Size: 379 B |
|
Before Width: | Height: | Size: 233 B After Width: | Height: | Size: 233 B |
|
Before Width: | Height: | Size: 832 B After Width: | Height: | Size: 832 B |
|
Before Width: | Height: | Size: 631 B After Width: | Height: | Size: 631 B |
|
Before Width: | Height: | Size: 832 B After Width: | Height: | Size: 832 B |
|
Before Width: | Height: | Size: 488 B After Width: | Height: | Size: 488 B |
|
Before Width: | Height: | Size: 673 B After Width: | Height: | Size: 673 B |
|
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 2.0 KiB |
|
Before Width: | Height: | Size: 5.5 KiB After Width: | Height: | Size: 5.5 KiB |
|
Before Width: | Height: | Size: 790 B After Width: | Height: | Size: 790 B |
|
Before Width: | Height: | Size: 506 B After Width: | Height: | Size: 506 B |
|
Before Width: | Height: | Size: 549 B After Width: | Height: | Size: 549 B |
|
Before Width: | Height: | Size: 438 B After Width: | Height: | Size: 438 B |