Compare commits

...

71 Commits

Author SHA1 Message Date
a9b82a299a [run] Port (#165)
Change develop port 8001 -> 8000
2021-05-31 09:25:59 +03:00
46961db654 Merge branch release/v6.3.0 into master 2021-05-20 11:58:44 +00:00
85255d878e Merge branch hotfix/v6.2.2 into release/v6.3.0 2021-05-07 11:59:45 +00:00
c8b17785e7 apache to license 2021-03-23 11:37:21 +03:00
988e336f43 forcesave is disabled by default (b541936473) 2021-03-05 11:20:12 +03:00
9ab94ee9c3 Merge remote-tracking branch 'origin/master' into release/v6.3.0 2021-03-04 11:12:08 +03:00
fe02c4914c converting xml 2021-03-01 14:26:43 +03:00
82981d3ce2 Merge remote-tracking branch 'remotes/origin/release/v6.2.0' into develop 2021-03-01 14:14:38 +03:00
6870923b94 Merge branch release/v6.2.0 into master 2021-03-01 08:43:26 +00:00
7d5c90e9cf python: set version pyjwt 1.7.1 2021-02-19 16:08:43 +03:00
b541936473 Merge pull request #126 from ONLYOFFICE/feature/submit-form
Feature/submit form
2021-02-19 15:45:20 +03:00
a2e59cf705 ruby: submit filled form 2021-02-19 15:01:32 +03:00
dc074d4baf python: submit filled form 2021-02-19 15:00:42 +03:00
1cf5b1eea5 php: submit filled form 2021-02-19 15:00:17 +03:00
2635306e2e csharp-mvc: submit filled form 2021-02-19 14:59:59 +03:00
f0cc80fd53 csharp: submit filled form 2021-02-19 14:59:36 +03:00
c9f58e3ca6 java: submit filled form 2021-02-19 14:59:14 +03:00
821e481734 nodejs: improved forcesave submit filled form 2021-02-19 14:58:21 +03:00
f0309615d6 Merge remote-tracking branch 'remotes/origin/develop' into feature/submit-form
# Conflicts:
#	web/documentserver-example/nodejs/app.js
2021-02-18 15:39:20 +03:00
47588d135e Merge pull request #115 from ONLYOFFICE/feature/reviewPermissions
Feature/review permissions
2021-02-18 15:33:56 +03:00
8e6ae3b915 Merge remote-tracking branch 'remotes/origin/develop' into feature/reviewPermissions
# Conflicts:
#	web/documentserver-example/csharp-mvc/Models/FileModel.cs
#	web/documentserver-example/csharp/DocEditor.aspx.cs
#	web/documentserver-example/java/src/main/java/entities/FileModel.java
#	web/documentserver-example/python/src/views/actions.py
#	web/documentserver-example/ruby/app/models/file_model.rb
2021-02-18 15:13:34 +03:00
8fc9d6125c Merge pull request #122 from ONLYOFFICE/feature/request-name
Feature/request name
2021-02-18 14:14:00 +03:00
b427594248 Merge pull request #125 from ONLYOFFICE/feature/favicon
Feature/favicon
2021-02-18 09:09:36 +03:00
5c43308e14 ruby: added dynamic favicon 2021-02-17 20:19:51 +03:00
c5b67b4b00 php: added dynamic favicon 2021-02-17 20:19:30 +03:00
8442def83c csharp-mvc: added dynamic favicon 2021-02-17 20:18:43 +03:00
2cb91eb8d5 csharp: added dynamic favicon 2021-02-17 20:18:15 +03:00
cf82b0ffc9 java: added dynamic favicon 2021-02-17 20:17:15 +03:00
ffcf787f94 python: renamed favicon 2021-02-17 20:16:32 +03:00
ce2714c684 nodejs: renamed favicon 2021-02-17 20:15:47 +03:00
4ccd78053f renamed parameter reviewGroup on reviewGroups 2021-02-17 10:11:36 +03:00
7602183cf9 Merge pull request #124 from ONLYOFFICE/feature/forcesave
Feature/forcesave
2021-02-17 09:48:34 +03:00
1a6744a814 Merge branch 'develop' into feature/forcesave
# Conflicts:
#	web/documentserver-example/java/src/main/resources/settings.properties
2021-02-16 15:07:23 +03:00
6a89a073fa ruby: download forcesaved file 2021-02-16 15:02:19 +03:00
353119145c python: download forcesaved file 2021-02-16 14:59:04 +03:00
0aaaedc4d6 php: download forcesaved file 2021-02-16 14:14:08 +03:00
246ddc9f9c csharp-mvc: download forcesaved file 2021-02-16 13:28:30 +03:00
3e8b6aaffa csharp: download forcesaved file 2021-02-16 13:28:14 +03:00
c95439c0db java: download forcesaved file 2021-02-16 13:27:53 +03:00
62873e4ce4 nodejs: fix forcesave conversion 2021-02-16 11:00:45 +03:00
e04155e7ad csharp: added forcesave 2021-02-15 17:27:29 +03:00
733f798968 csharp-mvc: added forcesave 2021-02-15 17:26:16 +03:00
f7f0a07239 ruby: added forcesave 2021-02-15 17:24:56 +03:00
ee79e02c54 python: added forcesave 2021-02-15 16:52:44 +03:00
d8afda9b56 php: added forcesave 2021-02-15 15:29:25 +03:00
0569dc7271 java: added forcesave 2021-02-15 13:37:40 +03:00
823374e2fe csharp-mvc: request user name 2021-02-08 22:28:56 +03:00
3b89aae808 csharp: request user name 2021-02-08 22:28:19 +03:00
cc488187b4 php: request user name 2021-02-08 22:27:14 +03:00
0e191eed91 python: request user name 2021-02-08 22:26:24 +03:00
6d27c1866b ruby: request user name 2021-02-08 22:25:08 +03:00
845b111a85 java: request user name 2021-02-08 22:21:25 +03:00
61c388a7af csharp-mvc: reviewGroup instead reviewPermissions 2021-02-07 19:35:29 +03:00
c6deb13712 csharp: reviewGroup instead reviewPermissions 2021-02-07 19:30:32 +03:00
13250e18b3 php: reviewGroup instead reviewPermissions 2021-02-07 19:21:41 +03:00
7d373fa1a9 ruby: reviewGroup instead reviewPermissions 2021-02-07 19:11:09 +03:00
8af2607e62 python: reviewGroup instead reviewPermissions 2021-02-07 19:00:34 +03:00
c2db28fbcf java: reviewGroup instead reviewPermissions 2021-02-07 18:38:47 +03:00
d075855065 nodejs: request user name 2021-02-04 15:24:09 +03:00
2ec0a3798d nodejs: reviewGroup instead reviewPermissions 2021-02-04 14:31:49 +03:00
4ba7b3f02e Add Dockerfile for nodejs (#110)
* Add Dockerfile for nodejs DS Example

* Removed unnecessary lines

* Add expose 3000 port to Dockerfile

Co-authored-by: Cyger <cyger@centos7.server>
2021-02-03 11:32:10 +03:00
620a097faa Merge remote-tracking branch 'remotes/origin/develop' into feature/reviewPermissions
# Conflicts:
#	web/documentserver-example/csharp-mvc/Models/FileModel.cs
#	web/documentserver-example/java/src/main/java/entities/FileModel.java
#	web/documentserver-example/python/src/views/actions.py
2021-02-02 13:59:17 +03:00
c3bb70aa9a nodejs: submit filled form 2021-02-02 09:52:24 +03:00
255ec7afe9 python: reviewPermissions 2021-01-27 12:48:46 +03:00
7996ea4825 ruby: reviewPermissions 2021-01-27 12:31:26 +03:00
38055f0b85 csharp: reviewPermissions 2021-01-25 11:53:34 +03:00
4e2a5fb175 csharp-mvc: reviewPermissions 2021-01-19 18:36:32 +03:00
c54b760526 Merge branch 'develop' into feature/reviewPermissions 2021-01-19 15:54:13 +03:00
cf4dd454f6 php: reviewPermission 2020-11-13 11:43:10 +03:00
858b437e80 java: reviewPermissions 2020-11-12 16:46:25 +03:00
715ab7d690 nodejs: reviewPermissions 2020-10-06 12:47:31 +03:00
87 changed files with 2525 additions and 877 deletions

View File

@ -80,4 +80,4 @@ If you have any problems with or questions about [ONLYOFFICE Document Server][2]
## License
document-server-integration is released under the MIT License. See the LICENSE.txt file for more information.
document-server-integration is released under the Apache-2.0 License. See the LICENSE.txt file for more information.

View File

Before

Width:  |  Height:  |  Size: 8.2 KiB

After

Width:  |  Height:  |  Size: 8.2 KiB

View File

Before

Width:  |  Height:  |  Size: 8.2 KiB

After

Width:  |  Height:  |  Size: 8.2 KiB

View File

Before

Width:  |  Height:  |  Size: 8.2 KiB

After

Width:  |  Height:  |  Size: 8.2 KiB

View File

@ -75,6 +75,39 @@ namespace OnlineEditorsExampleMVC.Helpers
return directory + Path.GetFileName(fileName);
}
public static string ForcesavePath(string fileName, string userAddress, Boolean create)
{
var directory = HttpRuntime.AppDomainAppPath + CurUserHostAddress(userAddress) + "\\";
if (!Directory.Exists(directory))
{
return "";
}
directory = directory + Path.GetFileName(fileName) + "-hist" + "\\";
if (!Directory.Exists(directory))
{
if (create)
{
Directory.CreateDirectory(directory);
}
else
{
return "";
}
}
directory = directory + Path.GetFileName(fileName);
if (!File.Exists(directory))
{
if (!create)
{
return "";
}
}
return directory;
}
public static string HistoryDir(string storagePath)
{
return storagePath += "-hist";
@ -101,13 +134,13 @@ namespace OnlineEditorsExampleMVC.Helpers
return GetFileVersion(HistoryDir(StoragePath(fileName, userAddress)));
}
public static string GetCorrectName(string fileName)
public static string GetCorrectName(string fileName, string userAddress = null)
{
var baseName = Path.GetFileNameWithoutExtension(fileName);
var ext = Path.GetExtension(fileName);
var name = baseName + ext;
for (var i = 1; File.Exists(StoragePath(name)); i++)
for (var i = 1; File.Exists(StoragePath(name, userAddress)); i++)
{
name = baseName + " (" + i + ")" + ext;
}
@ -138,9 +171,9 @@ namespace OnlineEditorsExampleMVC.Helpers
return fileName;
}
public static void CreateMeta(string fileName, string uid, string uname)
public static void CreateMeta(string fileName, string uid, string uname, string userAddress = null)
{
var histDir = HistoryDir(StoragePath(fileName, null));
var histDir = HistoryDir(StoragePath(fileName, userAddress));
Directory.CreateDirectory(histDir);
File.WriteAllText(Path.Combine(histDir, "createdInfo.json"), new JavaScriptSerializer().Serialize(new Dictionary<string, object> {
{ "created", DateTime.Now.ToString("yyyy'-'MM'-'dd HH':'mm':'ss") },

View File

@ -0,0 +1,290 @@
/**
*
* (c) Copyright Ascensio System SIA 2020
*
* 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.
*
*/
using System;
using System.IO;
using System.Net;
using System.Collections.Generic;
using System.Web.Script.Serialization;
using System.Web.Configuration;
using System.Linq;
using System.Web;
using System.Text;
namespace OnlineEditorsExampleMVC.Helpers
{
public class TrackManager
{
public static Dictionary<string, object> readBody(HttpContext context)
{
string body;
try
{
using (var receiveStream = context.Request.InputStream)
using (var readStream = new StreamReader(receiveStream))
{
body = readStream.ReadToEnd();
if (string.IsNullOrEmpty(body)) context.Response.Write("{\"error\":1,\"message\":\"Request stream is empty\"}");
}
}
catch (Exception e)
{
throw new HttpException((int)HttpStatusCode.BadRequest, e.Message);
}
var jss = new JavaScriptSerializer();
var fileData = jss.Deserialize<Dictionary<string, object>>(body);
if (JwtManager.Enabled)
{
string JWTheader = WebConfigurationManager.AppSettings["files.docservice.header"].Equals("") ? "Authorization" : WebConfigurationManager.AppSettings["files.docservice.header"];
string token = null;
if (fileData.ContainsKey("token"))
{
token = JwtManager.Decode(fileData["token"].ToString());
}
else if (context.Request.Headers.AllKeys.Contains(JWTheader, StringComparer.InvariantCultureIgnoreCase))
{
var headerToken = context.Request.Headers.Get(JWTheader).Substring("Bearer ".Length);
token = JwtManager.Decode(headerToken);
}
else
{
context.Response.Write("{\"error\":1,\"message\":\"JWT expected\"}");
}
if (token != null && !token.Equals(""))
{
fileData = (Dictionary<string, object>)jss.Deserialize<Dictionary<string, object>>(token)["payload"];
}
else
{
context.Response.Write("{\"error\":1,\"message\":\"JWT validation failed\"}");
}
}
return fileData;
}
public static int processSave(Dictionary<string, object> fileData, string fileName, string userAddress)
{
var downloadUri = (string)fileData["url"];
string curExt = Path.GetExtension(fileName);
string downloadExt = Path.GetExtension(downloadUri) ?? "";
var newFileName = fileName;
if (!curExt.Equals(downloadExt, StringComparison.InvariantCultureIgnoreCase))
{
try
{
string newFileUri;
var result = ServiceConverter.GetConvertedUri(downloadUri, downloadExt, curExt, ServiceConverter.GenerateRevisionId(downloadUri), false, out newFileUri);
if (string.IsNullOrEmpty(newFileUri))
{
newFileName = DocManagerHelper.GetCorrectName(Path.GetFileNameWithoutExtension(fileName) + downloadExt, userAddress);
}
else
{
downloadUri = newFileUri;
}
}
catch (Exception)
{
newFileName = DocManagerHelper.GetCorrectName(Path.GetFileNameWithoutExtension(fileName) + downloadExt, userAddress);
}
}
var storagePath = DocManagerHelper.StoragePath(newFileName, userAddress);
var histDir = DocManagerHelper.HistoryDir(storagePath);
if (!Directory.Exists(histDir)) Directory.CreateDirectory(histDir);
var versionDir = DocManagerHelper.VersionDir(histDir, DocManagerHelper.GetFileVersion(histDir));
if (!Directory.Exists(versionDir)) Directory.CreateDirectory(versionDir);
File.Move(DocManagerHelper.StoragePath(fileName, userAddress), Path.Combine(versionDir, "prev" + curExt));
DownloadToFile(downloadUri, storagePath);
DownloadToFile((string)fileData["changesurl"], Path.Combine(versionDir, "diff.zip"));
var hist = fileData.ContainsKey("changeshistory") ? (string)fileData["changeshistory"] : null;
if (string.IsNullOrEmpty(hist) && fileData.ContainsKey("history"))
{
var jss = new JavaScriptSerializer();
hist = jss.Serialize(fileData["history"]);
}
if (!string.IsNullOrEmpty(hist))
{
File.WriteAllText(Path.Combine(versionDir, "changes.json"), hist);
}
File.WriteAllText(Path.Combine(versionDir, "key.txt"), (string)fileData["key"]);
string forcesavePath = DocManagerHelper.ForcesavePath(newFileName, userAddress, false);
if (!forcesavePath.Equals(""))
{
File.Delete(forcesavePath);
}
return 0;
}
public static int processForceSave(Dictionary<string, object> fileData, string fileName, string userAddress)
{
var downloadUri = (string)fileData["url"];
string curExt = Path.GetExtension(fileName);
string downloadExt = Path.GetExtension(downloadUri);
var newFileName = fileName;
if (!curExt.Equals(downloadExt))
{
try
{
string newFileUri;
var result = ServiceConverter.GetConvertedUri(downloadUri, downloadExt, curExt, ServiceConverter.GenerateRevisionId(downloadUri), false, out newFileUri);
if (string.IsNullOrEmpty(newFileUri))
{
newFileName = DocManagerHelper.GetCorrectName(Path.GetFileNameWithoutExtension(fileName) + downloadExt, userAddress);
}
else
{
downloadUri = newFileUri;
}
}
catch (Exception)
{
newFileName = DocManagerHelper.GetCorrectName(Path.GetFileNameWithoutExtension(fileName) + downloadExt, userAddress);
}
}
string forcesavePath = "";
Boolean isSubmitForm = fileData["forcesavetype"].ToString().Equals("3");
if (isSubmitForm)
{
if (newFileName.Equals(fileName))
{
newFileName = DocManagerHelper.GetCorrectName(fileName, userAddress);
}
forcesavePath = DocManagerHelper.StoragePath(newFileName, userAddress);
}
else
{
forcesavePath = DocManagerHelper.ForcesavePath(newFileName, userAddress, false);
if (forcesavePath.Equals(""))
{
forcesavePath = DocManagerHelper.ForcesavePath(newFileName, userAddress, true);
}
}
DownloadToFile(downloadUri, forcesavePath);
if (isSubmitForm)
{
var jss = new JavaScriptSerializer();
var actions = jss.Deserialize<List<object>>(jss.Serialize(fileData["actions"]));
var action = jss.Deserialize<Dictionary<string, object>>(jss.Serialize(actions[0]));
var user = action["userid"].ToString();
DocManagerHelper.CreateMeta(newFileName, user, "Filling Form", userAddress);
}
return 0;
}
public static void commandRequest(string method, string key)
{
string documentCommandUrl = WebConfigurationManager.AppSettings["files.docservice.url.site"] + WebConfigurationManager.AppSettings["files.docservice.url.command"];
var request = (HttpWebRequest)WebRequest.Create(documentCommandUrl);
request.Method = "POST";
request.ContentType = "application/json";
var body = new Dictionary<string, object>() {
{ "c", method },
{ "key", key }
};
if (JwtManager.Enabled)
{
var payload = new Dictionary<string, object>
{
{ "payload", body }
};
var payloadToken = JwtManager.Encode(payload);
var bodyToken = JwtManager.Encode(body);
string JWTheader = WebConfigurationManager.AppSettings["files.docservice.header"].Equals("") ? "Authorization" : WebConfigurationManager.AppSettings["files.docservice.header"];
request.Headers.Add(JWTheader, "Bearer " + payloadToken);
body.Add("token", bodyToken);
}
var bytes = Encoding.UTF8.GetBytes(new JavaScriptSerializer().Serialize(body));
request.ContentLength = bytes.Length;
using (var requestStream = request.GetRequestStream())
{
requestStream.Write(bytes, 0, bytes.Length);
}
string dataResponse;
using (var response = request.GetResponse())
using (var stream = response.GetResponseStream())
{
if (stream == null) throw new Exception("Response is null");
using (var reader = new StreamReader(stream))
{
dataResponse = reader.ReadToEnd();
}
}
var jss = new JavaScriptSerializer();
var responseObj = jss.Deserialize<Dictionary<string, object>>(dataResponse);
if (!responseObj["error"].ToString().Equals("0"))
{
throw new Exception(dataResponse);
}
}
private static void DownloadToFile(string url, string path)
{
if (string.IsNullOrEmpty(url)) throw new ArgumentException("url");
if (string.IsNullOrEmpty(path)) throw new ArgumentException("path");
var req = (HttpWebRequest)WebRequest.Create(url);
using (var stream = req.GetResponse().GetResponseStream())
{
if (stream == null) throw new Exception("stream is null");
const int bufferSize = 4096;
using (var fs = File.Open(path, FileMode.Create))
{
var buffer = new byte[bufferSize];
int readed;
while ((readed = stream.Read(buffer, 0, bufferSize)) != 0)
{
fs.Write(buffer, 0, readed);
}
}
}
}
}
}

View File

@ -68,6 +68,22 @@ namespace OnlineEditorsExampleMVC.Models
var canEdit = DocManagerHelper.EditedExts.Contains(ext);
var mode = canEdit && editorsMode != "view" ? "edit" : "view";
var submitForm = canEdit && (editorsMode.Equals("edit") || editorsMode.Equals("fillForms"));
var userId = request.Cookies.GetOrDefault("uid", "uid-1");
var uname = userId.Equals("uid-0") ? null : request.Cookies.GetOrDefault("uname", "John Smith");
string userGroup = null;
List<string> reviewGroups = null;
if (userId.Equals("uid-2"))
{
userGroup = "group-2";
reviewGroups = new List<string>() { "group-2", "" };
}
if (userId.Equals("uid-3"))
{
userGroup = "group-3";
reviewGroups = new List<string>() { "group-2" };
}
object favorite = null;
if (!string.IsNullOrEmpty(request.Cookies.GetOrDefault("uid", null)))
@ -106,7 +122,8 @@ namespace OnlineEditorsExampleMVC.Models
{ "fillForms", editorsMode != "view" && editorsMode != "comment" && editorsMode != "embedded" && editorsMode != "blockcontent" },
{ "modifyFilter", editorsMode != "filter" },
{ "modifyContentControl", editorsMode != "blockcontent" },
{ "review", editorsMode == "edit" || editorsMode == "review" }
{ "review", editorsMode == "edit" || editorsMode == "review" },
{ "reviewGroups", reviewGroups }
}
}
}
@ -121,8 +138,9 @@ namespace OnlineEditorsExampleMVC.Models
{
"user", new Dictionary<string, object>
{
{ "id", request.Cookies.GetOrDefault("uid", "uid-1") },
{ "name", request.Cookies.GetOrDefault("uname", "John Smith") }
{ "id", userId },
{ "name", uname },
{ "group", userGroup }
}
},
{
@ -139,6 +157,8 @@ namespace OnlineEditorsExampleMVC.Models
{
{ "about", true },
{ "feedback", true },
{ "forcesave", false },
{ "submitForm", submitForm },
{
"goback", new Dictionary<string, object>
{
@ -247,7 +267,7 @@ namespace OnlineEditorsExampleMVC.Models
Path = HttpRuntime.AppDomainAppVirtualPath
+ (HttpRuntime.AppDomainAppVirtualPath.EndsWith("/") ? "" : "/")
+ "webeditor.ashx",
Query = "type=download&fileName=" + HttpUtility.UrlEncode("sample.docx")
Query = "type=assets&fileName=" + HttpUtility.UrlEncode("sample.docx")
};
var dataCompareFile = new Dictionary<string, object>

View File

@ -46,7 +46,7 @@ namespace OnlineEditorsExampleMVC.Models
".doc", ".docx", ".docm",
".dot", ".dotx", ".dotm",
".odt", ".fodt", ".ott", ".rtf", ".txt",
".html", ".htm", ".mht",
".html", ".htm", ".mht", ".xml",
".pdf", ".djvu", ".fb2", ".epub", ".xps"
};

View File

@ -105,6 +105,7 @@
<Compile Include="Global.asax.cs">
<DependentUpon>Global.asax</DependentUpon>
</Compile>
<Compile Include="Helpers\TrackManager.cs" />
<Compile Include="Helpers\DocManagerHelper.cs" />
<Compile Include="Helpers\DocumentConverter.cs" />
<Compile Include="Helpers\JwtManager.cs" />
@ -120,6 +121,7 @@
<Content Include="Content\editor.css" />
<Content Include="Content\images\alert.png" />
<Content Include="Content\images\block-content-24.png" />
<Content Include="Content\images\cell.ico" />
<Content Include="Content\images\close.png" />
<Content Include="Content\images\comment-24.png" />
<Content Include="Content\images\corner.png" />
@ -139,6 +141,8 @@
<Content Include="Content\images\mobile-24.png" />
<Content Include="Content\images\question_small.png" />
<Content Include="Content\images\review-24.png" />
<Content Include="Content\images\slide.ico" />
<Content Include="Content\images\word.ico" />
<Content Include="Content\jquery-ui.css" />
<Content Include="Content\stylesheet.css" />
<Content Include="favicon.ico" />

View File

@ -29,7 +29,7 @@
* limitations under the License.
*
-->
<link rel="icon" href="~/favicon.ico" type="image/x-icon" />
<link rel="icon" href="<%= "content/images/" + Model.DocumentType + ".ico" %>" type="image/x-icon" />
<title><%= Model.FileName + " - ONLYOFFICE" %></title>
<%: Styles.Render("~/Content/editor") %>

View File

@ -57,6 +57,7 @@
<option value="uid-1">John Smith</option>
<option value="uid-2">Mark Pottato</option>
<option value="uid-3">Hamish Mitchell</option>
<option value="uid-0">anonymous</option>
</select>
</td>
<td width="70%" valign="middle">Select user name before opening the document; you can open the same document using different users in different Web browser sessions, so you can check out multi-user editing functions.</td>
@ -160,7 +161,7 @@
<a class="stored-edit <%= docType %>" href="<%= Url.Action("Editor", "Home", new { fileName = storedFile.Name }) %>" target="_blank">
<span title="<%= storedFile.Name %>"><%= storedFile.Name %></span>
</a>
<a href="<%= Url.Content(DocManagerHelper.CurUserHostAddress() + "/" + storedFile) %>">
<a href="webeditor.ashx?type=download&filename=<%= HttpUtility.UrlEncode(storedFile.Name) %>">
<img class="icon-download" src="content/images/download-24.png" alt="Download" title="Download" />
</a>
<a class="delete-file" data-filename="<%= storedFile.Name %>">

View File

@ -27,6 +27,7 @@ using System.Web.Services;
using System.Web.Configuration;
using OnlineEditorsExampleMVC.Helpers;
using OnlineEditorsExampleMVC.Models;
using System.Diagnostics;
namespace OnlineEditorsExampleMVC
{
@ -41,6 +42,9 @@ namespace OnlineEditorsExampleMVC
case "upload":
Upload(context);
break;
case "download":
Download(context);
break;
case "convert":
Convert(context);
break;
@ -50,8 +54,8 @@ namespace OnlineEditorsExampleMVC
case "remove":
Remove(context);
break;
case "download":
Download(context);
case "assets":
Assets(context);
break;
case "csv":
GetCsv(context);
@ -170,103 +174,70 @@ namespace OnlineEditorsExampleMVC
MustSave = 2,
Corrupted = 3,
Closed = 4,
MustForceSave = 6,
CorruptedForceSave = 7
}
private static void Track(HttpContext context)
{
var fileData = TrackManager.readBody(context);
var userAddress = context.Request["userAddress"];
var fileName = Path.GetFileName(context.Request["fileName"]);
string body;
try
{
using (var receiveStream = context.Request.InputStream)
using (var readStream = new StreamReader(receiveStream))
{
body = readStream.ReadToEnd();
}
}
catch (Exception e)
{
throw new HttpException((int) HttpStatusCode.BadRequest, e.Message);
}
var jss = new JavaScriptSerializer();
if (string.IsNullOrEmpty(body)) return;
var fileData = jss.Deserialize<Dictionary<string, object>>(body);
if (JwtManager.Enabled)
{
string JWTheader = WebConfigurationManager.AppSettings["files.docservice.header"].Equals("") ? "Authorization" : WebConfigurationManager.AppSettings["files.docservice.header"];
string token = null;
if (fileData.ContainsKey("token"))
{
token = JwtManager.Decode(fileData["token"].ToString());
}
else if (context.Request.Headers.AllKeys.Contains(JWTheader, StringComparer.InvariantCultureIgnoreCase))
{
var headerToken = context.Request.Headers.Get(JWTheader).Substring("Bearer ".Length);
token = JwtManager.Decode(headerToken);
}
else
{
context.Response.Write("{\"error\":1,\"message\":\"JWT expected\"}");
}
if (token != null && !token.Equals(""))
{
fileData = (Dictionary<string, object>)jss.Deserialize<Dictionary<string, object>>(token)["payload"];
}
else
{
context.Response.Write("{\"error\":1,\"message\":\"JWT validation failed\"}");
}
}
var status = (TrackerStatus) (int) fileData["status"];
var saved = 1;
switch (status)
{
case TrackerStatus.MustSave:
case TrackerStatus.Corrupted:
var downloadUri = (string) fileData["url"];
var saved = 1;
case TrackerStatus.Editing:
try
{
var storagePath = DocManagerHelper.StoragePath(fileName, userAddress);
var histDir = DocManagerHelper.HistoryDir(storagePath);
var versionDir = DocManagerHelper.VersionDir(histDir, DocManagerHelper.GetFileVersion(histDir));
if (!Directory.Exists(versionDir)) Directory.CreateDirectory(versionDir);
File.Copy(storagePath, Path.Combine(versionDir, "prev" + Path.GetExtension(fileName)));
DownloadToFile(downloadUri, DocManagerHelper.StoragePath(fileName, userAddress));
DownloadToFile((string)fileData["changesurl"], Path.Combine(versionDir, "diff.zip"));
var hist = fileData.ContainsKey("changeshistory") ? (string)fileData["changeshistory"] : null;
if (string.IsNullOrEmpty(hist) && fileData.ContainsKey("history"))
var jss = new JavaScriptSerializer();
var actions = jss.Deserialize <List<object>> (jss.Serialize(fileData["actions"]));
var action = jss.Deserialize <Dictionary<string, object>> (jss.Serialize(actions[0]));
if (action != null && action["type"].ToString().Equals("0"))
{
hist = jss.Serialize(fileData["history"]);
}
var user = action["userid"].ToString();
var users = jss.Deserialize<List<object>>(jss.Serialize(fileData["users"]));
if (!users.Contains(user))
{
TrackManager.commandRequest("forcesave", fileData["key"].ToString());
}
if (!string.IsNullOrEmpty(hist))
{
File.WriteAllText(Path.Combine(versionDir, "changes.json"), hist);
}
}
catch (Exception e)
{
Debug.Print(e.StackTrace);
}
break;
File.WriteAllText(Path.Combine(versionDir, "key.txt"), (string)fileData["key"]);
case TrackerStatus.MustSave:
case TrackerStatus.Corrupted:
try
{
saved = TrackManager.processSave(fileData, fileName, userAddress);
}
catch (Exception)
{
saved = 0;
saved = 1;
}
context.Response.Write("{\"error\":" + saved + "}");
return;
break;
case TrackerStatus.MustForceSave:
case TrackerStatus.CorruptedForceSave:
try
{
saved = TrackManager.processForceSave(fileData, fileName, userAddress);
}
catch (Exception)
{
saved = 1;
}
context.Response.Write("{\"error\":" + saved + "}");
return;
}
context.Response.Write("{\"error\":0}");
}
@ -329,51 +300,48 @@ namespace OnlineEditorsExampleMVC
}
}
private static void Download(HttpContext context)
private static void Assets(HttpContext context)
{
var fileName = "sample/" + Path.GetFileName(context.Request["filename"]);
download(fileName, context);
var fileName = Path.GetFileName(context.Request["filename"]);
var filePath = HttpRuntime.AppDomainAppPath + "assets/sample/" + fileName;
download(filePath, context);
}
private static void GetCsv(HttpContext context)
{
var fileName = "sample/" + "csv.csv";
download(fileName, context);
var fileName = "csv.csv";
var filePath = HttpRuntime.AppDomainAppPath + "assets/sample/" + fileName;
download(filePath, context);
}
private static void download(string fileName, HttpContext context)
private static void Download(HttpContext context)
{
var csvPath = HttpRuntime.AppDomainAppPath + "assets/" + fileName;
var fileinf = new FileInfo(csvPath);
try
{
var fileName = Path.GetFileName(context.Request["filename"]);
var filePath = DocManagerHelper.ForcesavePath(fileName, null, false);
if (filePath.Equals(""))
{
filePath = DocManagerHelper.StoragePath(fileName, null);
}
download(filePath, context);
}
catch (Exception)
{
context.Response.Write("{ \"error\": \"File not found!\"}");
}
}
private static void download(string filePath, HttpContext context)
{
var fileinf = new FileInfo(filePath);
context.Response.AddHeader("Content-Length", fileinf.Length.ToString());
context.Response.AddHeader("Content-Type", MimeMapping.GetMimeMapping(csvPath));
var tmp = HttpUtility.UrlEncode(Path.GetFileName(csvPath));
context.Response.AddHeader("Content-Type", MimeMapping.GetMimeMapping(filePath));
var tmp = HttpUtility.UrlEncode(Path.GetFileName(filePath));
tmp = tmp.Replace("+", "%20");
context.Response.AddHeader("Content-Disposition", "attachment; filename*=UTF-8\'\'" + tmp);
context.Response.TransmitFile(csvPath);
}
private static void DownloadToFile(string url, string path)
{
if (string.IsNullOrEmpty(url)) throw new ArgumentException("url");
if (string.IsNullOrEmpty(path)) throw new ArgumentException("path");
var req = (HttpWebRequest)WebRequest.Create(url);
using (var stream = req.GetResponse().GetResponseStream())
{
if (stream == null) throw new Exception("stream is null");
const int bufferSize = 4096;
using (var fs = File.Open(path, FileMode.Create))
{
var buffer = new byte[bufferSize];
int readed;
while ((readed = stream.Read(buffer, 0, bufferSize)) != 0)
{
fs.Write(buffer, 0, readed);
}
}
}
context.Response.TransmitFile(filePath);
}
public bool IsReusable

View File

@ -11,17 +11,18 @@
<add key="files.docservice.viewed-docs" value=".pdf|.djvu|.xps"/>
<add key="files.docservice.edited-docs" value=".docx|.xlsx|.csv|.pptx|.txt"/>
<add key="files.docservice.convert-docs" value=".docm|.dotx|.dotm|.dot|.doc|.odt|.fodt|.ott|.xlsm|.xltx|.xltm|.xlt|.xls|.ods|.fods|.ots|.pptm|.ppt|.ppsx|.ppsm|.pps|.potx|.potm|.pot|.odp|.fodp|.otp|.rtf|.mht|.html|.htm|.epub|.fb2"/>
<add key="files.docservice.convert-docs" value=".docm|.dotx|.dotm|.dot|.doc|.odt|.fodt|.ott|.xlsm|.xltx|.xltm|.xlt|.xls|.ods|.fods|.ots|.pptm|.ppt|.ppsx|.ppsm|.pps|.potx|.potm|.pot|.odp|.fodp|.otp|.rtf|.mht|.html|.htm|.xml|.epub|.fb2"/>
<add key="files.docservice.timeout" value="120000" />
<add key="files.docservice.secret" value="" />
<add key="files.docservice.header" value="Authorization" />
<add key="files.docservice.url.site" value="http://documentserver/"/>
<add key="files.docservice.url.site" value="https://documentserver/"/>
<add key="files.docservice.url.converter" value="ConvertService.ashx"/>
<add key="files.docservice.url.api" value="web-apps/apps/api/documents/api.js"/>
<add key="files.docservice.url.preloader" value="web-apps/apps/api/documents/cache-scripts.html"/>
<add key="files.docservice.url.command" value="coauthoring/CommandService.ashx"/>
<add key="files.docservice.url.example" value=""/>
</appSettings>

View File

Before

Width:  |  Height:  |  Size: 8.2 KiB

After

Width:  |  Height:  |  Size: 8.2 KiB

View File

Before

Width:  |  Height:  |  Size: 8.2 KiB

After

Width:  |  Height:  |  Size: 8.2 KiB

View File

Before

Width:  |  Height:  |  Size: 8.2 KiB

After

Width:  |  Height:  |  Size: 8.2 KiB

View File

@ -77,6 +77,7 @@
<option value="uid-1">John Smith</option>
<option value="uid-2">Mark Pottato</option>
<option value="uid-3">Hamish Mitchell</option>
<option value="uid-0">anonymous</option>
</select>
</td>
<td width="70%" valign="middle">Select user name before opening the document; you can open the same document using different users in different Web browser sessions, so you can check out multi-user editing functions.</td>
@ -180,7 +181,7 @@
<a class="stored-edit <%= docType %>" href="<%= editUrl %>" target="_blank">
<span title="<%= storedFile.Name %>"><%= storedFile.Name %></span>
</a>
<a href="<%= VirtualPath + WebConfigurationManager.AppSettings["storage-path"] + storedFile.Name %>">
<a href="webeditor.ashx?type=download&filename=<%= HttpUtility.UrlEncode(storedFile.Name) %>">
<img class="icon-download" src="app_themes/images/download-24.png" alt="Download" title="Download" />
</a>
<a class="delete-file" data-filename="<%= storedFile.Name %>">

View File

@ -52,7 +52,7 @@ namespace OnlineEditorsExample
".doc", ".docx", ".docm",
".dot", ".dotx", ".dotm",
".odt", ".fodt", ".ott", ".rtf", ".txt",
".html", ".htm", ".mht",
".html", ".htm", ".mht", ".xml",
".pdf", ".djvu", ".fb2", ".epub", ".xps"
};
@ -135,6 +135,39 @@ namespace OnlineEditorsExample
return directory + Path.GetFileName(fileName);
}
public static string ForcesavePath(string fileName, string userAddress, Boolean create)
{
var directory = HttpRuntime.AppDomainAppPath + WebConfigurationManager.AppSettings["storage-path"] + CurUserHostAddress(userAddress) + "\\";
if (!Directory.Exists(directory))
{
return "";
}
directory = directory + Path.GetFileName(fileName) + "-hist" + "\\";
if (!Directory.Exists(directory))
{
if (create)
{
Directory.CreateDirectory(directory);
}
else
{
return "";
}
}
directory = directory + Path.GetFileName(fileName);
if (!File.Exists(directory))
{
if (!create)
{
return "";
}
}
return directory;
}
public static string HistoryDir(string storagePath)
{
return storagePath += "-hist";
@ -234,13 +267,7 @@ namespace OnlineEditorsExample
var savedFileName = StoragePath(_fileName, null);
httpPostedFile.SaveAs(savedFileName);
var histDir = HistoryDir(savedFileName);
Directory.CreateDirectory(histDir);
File.WriteAllText(Path.Combine(histDir, "createdInfo.json"), new JavaScriptSerializer().Serialize(new Dictionary<string, object> {
{ "created", DateTime.Now.ToString("yyyy'-'MM'-'dd HH':'mm':'ss") },
{ "id", context.Request.Cookies.GetOrDefault("uid", "uid-1") },
{ "name", context.Request.Cookies.GetOrDefault("uname", "John Smith") }
}));
DocEditor.CreateMeta(_fileName, context.Request.Cookies.GetOrDefault("uid", "uid-1"), context.Request.Cookies.GetOrDefault("uname", "John Smith"), null);
return _fileName;
}
@ -281,13 +308,7 @@ namespace OnlineEditorsExample
}
}
var histDir = HistoryDir(StoragePath(_fileName, null));
Directory.CreateDirectory(histDir);
File.WriteAllText(Path.Combine(histDir, "createdInfo.json"), new JavaScriptSerializer().Serialize(new Dictionary<string, object> {
{ "created", DateTime.Now.ToString("yyyy'-'MM'-'dd HH':'mm':'ss") },
{ "id", request.Cookies.GetOrDefault("uid", "uid-1") },
{ "name", request.Cookies.GetOrDefault("uname", "John Smith") }
}));
DocEditor.CreateMeta(_fileName, request.Cookies.GetOrDefault("uid", "uid-1"), request.Cookies.GetOrDefault("uname", "John Smith"), null);
}
catch (Exception)
{
@ -347,13 +368,7 @@ namespace OnlineEditorsExample
if (Directory.Exists(histDir)) Directory.Delete(histDir, true);
_fileName = fileName;
histDir = HistoryDir(StoragePath(_fileName, null));
Directory.CreateDirectory(histDir);
File.WriteAllText(Path.Combine(histDir, "createdInfo.json"), new JavaScriptSerializer().Serialize(new Dictionary<string, object> {
{ "created", DateTime.Now.ToString() },
{ "id", context.Request.Cookies.GetOrDefault("uid", "uid-1") },
{ "name", context.Request.Cookies.GetOrDefault("uname", "John Smith") }
}));
DocEditor.CreateMeta(_fileName, context.Request.Cookies.GetOrDefault("uid", "uid-1"), context.Request.Cookies.GetOrDefault("uname", "John Smith"), null);
}
return "{ \"filename\" : \"" + _fileName + "\"}";

View File

@ -11,7 +11,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no, minimal-ui" />
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="mobile-web-app-capable" content="yes" />
<link rel="icon" href="~/favicon.ico" type="image/x-icon" />
<link rel="icon" href="<%= "app_themes/images/" + documentType + ".ico" %>" type="image/x-icon" />
<title>ONLYOFFICE</title>
<!--
*

View File

@ -63,6 +63,7 @@ namespace OnlineEditorsExample
protected string InsertImageConfig { get; private set; }
protected string compareFileData { get; private set; }
protected string dataMailMergeRecipients { get; private set; }
protected string documentType { get { return _Default.DocumentType(FileName); } }
public static string CallbackUrl
{
@ -105,6 +106,22 @@ namespace OnlineEditorsExample
var canEdit = _Default.EditedExts.Contains(ext);
var mode = canEdit && editorsMode != "view" ? "edit" : "view";
var submitForm = canEdit && (editorsMode.Equals("edit") || editorsMode.Equals("fillForms"));
var userId = Request.Cookies.GetOrDefault("uid", "uid-1");
var uname = userId.Equals("uid-0") ? null : Request.Cookies.GetOrDefault("uname", "John Smith");
string userGroup = null;
List<string> reviewGroups = null;
if (userId.Equals("uid-2"))
{
userGroup = "group-2";
reviewGroups = new List<string>() { "group-2", "" };
}
if (userId.Equals("uid-3"))
{
userGroup = "group-3";
reviewGroups = new List<string>() { "group-2" };
}
var jss = new JavaScriptSerializer();
@ -120,7 +137,7 @@ namespace OnlineEditorsExample
var config = new Dictionary<string, object>
{
{ "type", Request.GetOrDefault("editorsType", "desktop") },
{ "documentType", _Default.DocumentType(FileName) },
{ "documentType", documentType },
{
"document", new Dictionary<string, object>
{
@ -145,7 +162,8 @@ namespace OnlineEditorsExample
{ "fillForms", editorsMode != "view" && editorsMode != "comment" && editorsMode != "embedded" && editorsMode != "blockcontent" },
{ "modifyFilter", editorsMode != "filter" },
{ "modifyContentControl", editorsMode != "blockcontent" },
{ "review", editorsMode == "edit" || editorsMode == "review" }
{ "review", editorsMode == "edit" || editorsMode == "review" },
{ "reviewGroups", reviewGroups }
}
}
}
@ -160,8 +178,9 @@ namespace OnlineEditorsExample
{
"user", new Dictionary<string, object>
{
{ "id", Request.Cookies.GetOrDefault("uid", "uid-1") },
{ "name", Request.Cookies.GetOrDefault("uname", "John Smith") }
{ "id", userId },
{ "name", uname },
{ "group", userGroup }
}
},
{
@ -178,6 +197,8 @@ namespace OnlineEditorsExample
{
{ "about", true },
{ "feedback", true },
{ "forcesave", false },
{ "submitForm", submitForm },
{
"goback", new Dictionary<string, object>
{
@ -328,7 +349,7 @@ namespace OnlineEditorsExample
compareFileUrl.Path = HttpRuntime.AppDomainAppVirtualPath
+ (HttpRuntime.AppDomainAppVirtualPath.EndsWith("/") ? "" : "/")
+ "webeditor.ashx";
compareFileUrl.Query = "type=download&fileName=" + HttpUtility.UrlEncode("sample.docx");
compareFileUrl.Query = "type=assets&fileName=" + HttpUtility.UrlEncode("sample.docx");
Dictionary<string, object> dataCompareFile = new Dictionary<string, object>
{
@ -400,12 +421,17 @@ namespace OnlineEditorsExample
var filePath = _Default.StoragePath(FileName, null);
File.Copy(HttpRuntime.AppDomainAppPath + demoPath + demoName, filePath);
var histDir = _Default.HistoryDir(filePath);
CreateMeta(FileName, request.Cookies.GetOrDefault("uid", "uid-1"), request.Cookies.GetOrDefault("uname", "John Smith"), null);
}
public static void CreateMeta(string fileName, string uid, string uname, string userAddress)
{
var histDir = _Default.HistoryDir(_Default.StoragePath(fileName, userAddress));
Directory.CreateDirectory(histDir);
File.WriteAllText(Path.Combine(histDir, "createdInfo.json"), new JavaScriptSerializer().Serialize(new Dictionary<string, object> {
{ "created", DateTime.Now.ToString("yyyy'-'MM'-'dd HH':'mm':'ss") },
{ "id", request.Cookies.GetOrDefault("uid", "uid-1") },
{ "name", request.Cookies.GetOrDefault("uname", "John Smith") }
{ "id", uid },
{ "name", uname }
}));
}
}

View File

@ -70,6 +70,7 @@
</ItemGroup>
<ItemGroup>
<Content Include="App_Themes\images\block-content-24.png" />
<Content Include="App_Themes\images\cell.ico" />
<Content Include="App_Themes\images\comment-24.png" />
<Content Include="App_Themes\images\delete-24.png" />
<Content Include="App_Themes\images\desktop-24.png" />
@ -86,6 +87,8 @@
<Content Include="App_Themes\images\icon_xlsx.png" />
<Content Include="App_Themes\images\mobile-24.png" />
<Content Include="App_Themes\images\review-24.png" />
<Content Include="App_Themes\images\slide.ico" />
<Content Include="App_Themes\images\word.ico" />
<Content Include="LICENSE" />
<Content Include="licenses\jquery.license" />
<Content Include="ReadMe.txt" />
@ -109,6 +112,7 @@
<Compile Include="Default.aspx.designer.cs">
<DependentUpon>Default.aspx</DependentUpon>
</Compile>
<Compile Include="TrackManager.cs" />
<Compile Include="Utils.cs" />
<Compile Include="WebEditor.ashx.cs">
<DependentUpon>WebEditor.ashx</DependentUpon>

View File

@ -0,0 +1,304 @@
/**
*
* (c) Copyright Ascensio System SIA 2020
*
* 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.
*
*/
using System;
using System.IO;
using System.Net;
using System.Collections.Generic;
using System.Web.Script.Serialization;
using System.Web.Configuration;
using System.Linq;
using System.Web;
using System.Text;
using ASC.Api.DocumentConverter;
namespace OnlineEditorsExample
{
public class TrackManager
{
public static Dictionary<string, object> readBody(HttpContext context)
{
string body;
try
{
using (var receiveStream = context.Request.InputStream)
using (var readStream = new StreamReader(receiveStream))
{
body = readStream.ReadToEnd();
if (string.IsNullOrEmpty(body)) context.Response.Write("{\"error\":1,\"message\":\"Request stream is empty\"}");
}
}
catch (Exception e)
{
throw new HttpException((int)HttpStatusCode.BadRequest, e.Message);
}
var jss = new JavaScriptSerializer();
var fileData = jss.Deserialize<Dictionary<string, object>>(body);
if (JwtManager.Enabled)
{
string JWTheader = WebConfigurationManager.AppSettings["files.docservice.header"].Equals("") ? "Authorization" : WebConfigurationManager.AppSettings["files.docservice.header"];
string token = null;
if (fileData.ContainsKey("token"))
{
token = JwtManager.Decode(fileData["token"].ToString());
}
else if (context.Request.Headers.AllKeys.Contains(JWTheader, StringComparer.InvariantCultureIgnoreCase))
{
var headerToken = context.Request.Headers.Get(JWTheader).Substring("Bearer ".Length);
token = JwtManager.Decode(headerToken);
}
else
{
context.Response.Write("{\"error\":1,\"message\":\"JWT expected\"}");
}
if (token != null && !token.Equals(""))
{
fileData = (Dictionary<string, object>)jss.Deserialize<Dictionary<string, object>>(token)["payload"];
}
else
{
context.Response.Write("{\"error\":1,\"message\":\"JWT validation failed\"}");
}
}
return fileData;
}
public static int processSave(Dictionary<string, object> fileData, string fileName, string userAddress)
{
var downloadUri = (string)fileData["url"];
var curExt = Path.GetExtension(fileName);
var downloadExt = Path.GetExtension(downloadUri) ?? "";
var newFileName = fileName;
if (!downloadExt.Equals(curExt, StringComparison.InvariantCultureIgnoreCase))
{
try
{
string newFileUri;
ServiceConverter.GetConvertedUri(downloadUri, downloadExt, curExt, ServiceConverter.GenerateRevisionId(downloadUri), false, out newFileUri);
if (string.IsNullOrEmpty(newFileUri))
{
newFileName = _Default.GetCorrectName(Path.GetFileNameWithoutExtension(fileName) + downloadExt, userAddress);
}
else
{
downloadUri = newFileUri;
}
}
catch (Exception)
{
newFileName = _Default.GetCorrectName(Path.GetFileNameWithoutExtension(fileName) + downloadExt, userAddress);
}
}
// hack. http://ubuntuforums.org/showthread.php?t=1841740
if (_Default.IsMono)
{
ServicePointManager.ServerCertificateValidationCallback += (s, ce, ca, p) => true;
}
var storagePath = _Default.StoragePath(newFileName, userAddress);
var histDir = _Default.HistoryDir(storagePath);
if (!Directory.Exists(histDir)) Directory.CreateDirectory(histDir);
var versionDir = _Default.VersionDir(histDir, _Default.GetFileVersion(histDir));
if (!Directory.Exists(versionDir)) Directory.CreateDirectory(versionDir);
File.Copy(_Default.StoragePath(fileName, userAddress), Path.Combine(versionDir, "prev" + curExt));
DownloadToFile(downloadUri, storagePath);
DownloadToFile((string)fileData["changesurl"], Path.Combine(versionDir, "diff.zip"));
var hist = fileData.ContainsKey("changeshistory") ? (string)fileData["changeshistory"] : null;
if (string.IsNullOrEmpty(hist) && fileData.ContainsKey("history"))
{
var jss = new JavaScriptSerializer();
hist = jss.Serialize(fileData["history"]);
}
if (!string.IsNullOrEmpty(hist))
{
File.WriteAllText(Path.Combine(versionDir, "changes.json"), hist);
}
File.WriteAllText(Path.Combine(versionDir, "key.txt"), (string)fileData["key"]);
string forcesavePath = _Default.ForcesavePath(newFileName, userAddress, false);
if (!forcesavePath.Equals(""))
{
File.Delete(forcesavePath);
}
return 0;
}
public static int processForceSave(Dictionary<string, object> fileData, string fileName, string userAddress)
{
var downloadUri = (string)fileData["url"];
string curExt = Path.GetExtension(fileName);
string downloadExt = Path.GetExtension(downloadUri);
var newFileName = fileName;
if (!curExt.Equals(downloadExt))
{
try
{
string newFileUri;
var result = ServiceConverter.GetConvertedUri(downloadUri, downloadExt, curExt, ServiceConverter.GenerateRevisionId(downloadUri), false, out newFileUri);
if (string.IsNullOrEmpty(newFileUri))
{
newFileName = _Default.GetCorrectName(Path.GetFileNameWithoutExtension(fileName) + downloadExt, userAddress);
}
else
{
downloadUri = newFileUri;
}
}
catch (Exception)
{
newFileName = _Default.GetCorrectName(Path.GetFileNameWithoutExtension(fileName) + downloadExt, userAddress);
}
}
// hack. http://ubuntuforums.org/showthread.php?t=1841740
if (_Default.IsMono)
{
ServicePointManager.ServerCertificateValidationCallback += (s, ce, ca, p) => true;
}
string forcesavePath = "";
Boolean isSubmitForm = fileData["forcesavetype"].ToString().Equals("3");
if (isSubmitForm)
{
if (newFileName.Equals(fileName))
{
newFileName = _Default.GetCorrectName(fileName, userAddress);
}
forcesavePath = _Default.StoragePath(newFileName, userAddress);
}
else
{
forcesavePath = _Default.ForcesavePath(newFileName, userAddress, false);
if (forcesavePath.Equals(""))
{
forcesavePath = _Default.ForcesavePath(newFileName, userAddress, true);
}
}
DownloadToFile(downloadUri, forcesavePath);
if (isSubmitForm)
{
var jss = new JavaScriptSerializer();
var actions = jss.Deserialize<List<object>>(jss.Serialize(fileData["actions"]));
var action = jss.Deserialize<Dictionary<string, object>>(jss.Serialize(actions[0]));
var user = action["userid"].ToString();
DocEditor.CreateMeta(newFileName, user, "Filling Form", userAddress);
}
return 0;
}
public static void commandRequest(string method, string key)
{
string documentCommandUrl = WebConfigurationManager.AppSettings["files.docservice.url.site"] + WebConfigurationManager.AppSettings["files.docservice.url.command"];
var request = (HttpWebRequest)WebRequest.Create(documentCommandUrl);
request.Method = "POST";
request.ContentType = "application/json";
var body = new Dictionary<string, object>() {
{ "c", method },
{ "key", key }
};
if (JwtManager.Enabled)
{
var payload = new Dictionary<string, object>
{
{ "payload", body }
};
var payloadToken = JwtManager.Encode(payload);
var bodyToken = JwtManager.Encode(body);
string JWTheader = WebConfigurationManager.AppSettings["files.docservice.header"].Equals("") ? "Authorization" : WebConfigurationManager.AppSettings["files.docservice.header"];
request.Headers.Add(JWTheader, "Bearer " + payloadToken);
body.Add("token", bodyToken);
}
var bytes = Encoding.UTF8.GetBytes(new JavaScriptSerializer().Serialize(body));
request.ContentLength = bytes.Length;
using (var requestStream = request.GetRequestStream())
{
requestStream.Write(bytes, 0, bytes.Length);
}
string dataResponse;
using (var response = request.GetResponse())
using (var stream = response.GetResponseStream())
{
if (stream == null) throw new Exception("Response is null");
using (var reader = new StreamReader(stream))
{
dataResponse = reader.ReadToEnd();
}
}
var jss = new JavaScriptSerializer();
var responseObj = jss.Deserialize<Dictionary<string, object>>(dataResponse);
if (!responseObj["error"].ToString().Equals("0"))
{
throw new Exception(dataResponse);
}
}
private static void DownloadToFile(string url, string path)
{
if (string.IsNullOrEmpty(url)) throw new ArgumentException("url");
if (string.IsNullOrEmpty(path)) throw new ArgumentException("path");
var req = (HttpWebRequest)WebRequest.Create(url);
using (var stream = req.GetResponse().GetResponseStream())
{
if (stream == null) throw new Exception("stream is null");
const int bufferSize = 4096;
using (var fs = File.Open(path, FileMode.Create))
{
var buffer = new byte[bufferSize];
int readed;
while ((readed = stream.Read(buffer, 0, bufferSize)) != 0)
{
fs.Write(buffer, 0, readed);
}
}
}
}
}
}

View File

@ -16,16 +16,13 @@
*
*/
using ASC.Api.DocumentConverter;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Web;
using System.Web.Script.Serialization;
using System.Web.Services;
using System.Web.Configuration;
using System.Diagnostics;
namespace OnlineEditorsExample
{
@ -40,6 +37,9 @@ namespace OnlineEditorsExample
case "upload":
Upload(context);
break;
case "download":
Download(context);
break;
case "convert":
Convert(context);
break;
@ -49,8 +49,8 @@ namespace OnlineEditorsExample
case "remove":
Remove(context);
break;
case "download":
Download(context);
case "assets":
Assets(context);
break;
case "csv":
GetCsv(context);
@ -94,126 +94,68 @@ namespace OnlineEditorsExample
MustSave = 2,
Corrupted = 3,
Closed = 4,
MustForceSave = 6,
CorruptedForceSave = 7
}
private static void Track(HttpContext context)
{
var fileData = TrackManager.readBody(context);
var userAddress = context.Request["userAddress"];
var fileName = Path.GetFileName(context.Request["fileName"]);
string body;
try
{
using (var receiveStream = context.Request.InputStream)
using (var readStream = new StreamReader(receiveStream))
{
body = readStream.ReadToEnd();
}
}
catch (Exception e)
{
throw new HttpException((int) HttpStatusCode.BadRequest, e.Message);
}
var jss = new JavaScriptSerializer();
if (string.IsNullOrEmpty(body)) return;
var fileData = jss.Deserialize<Dictionary<string, object>>(body);
if (JwtManager.Enabled)
{
string JWTheader = WebConfigurationManager.AppSettings["files.docservice.header"].Equals("") ? "Authorization" : WebConfigurationManager.AppSettings["files.docservice.header"];
string token = null;
if (fileData.ContainsKey("token"))
{
token = JwtManager.Decode(fileData["token"].ToString());
}
else if (context.Request.Headers.AllKeys.Contains(JWTheader, StringComparer.InvariantCultureIgnoreCase))
{
var headerToken = context.Request.Headers.Get(JWTheader).Substring("Bearer ".Length);
token = JwtManager.Decode(headerToken);
}
else
{
context.Response.Write("{\"error\":1,\"message\":\"JWT expected\"}");
}
if (token != null && !token.Equals(""))
{
fileData = (Dictionary<string, object>)jss.Deserialize<Dictionary<string, object>>(token)["payload"];
}
else
{
context.Response.Write("{\"error\":1,\"message\":\"JWT validation failed\"}");
}
}
var status = (TrackerStatus) (int) fileData["status"];
var saved = 1;
switch (status)
{
case TrackerStatus.MustSave:
case TrackerStatus.Corrupted:
var downloadUri = (string) fileData["url"];
var curExt = Path.GetExtension(fileName);
var downloadExt = Path.GetExtension(downloadUri) ?? "";
if (!downloadExt.Equals(curExt, StringComparison.InvariantCultureIgnoreCase))
{
var key = ServiceConverter.GenerateRevisionId(downloadUri);
try
{
string newFileUri;
ServiceConverter.GetConvertedUri(downloadUri, downloadExt, curExt, key, false, out newFileUri);
downloadUri = newFileUri;
}
catch (Exception ex)
{
fileName = _Default.GetCorrectName(Path.GetFileNameWithoutExtension(fileName) + downloadExt, userAddress);
}
}
// hack. http://ubuntuforums.org/showthread.php?t=1841740
if (_Default.IsMono)
{
ServicePointManager.ServerCertificateValidationCallback += (s, ce, ca, p) => true;
}
var saved = 1;
case TrackerStatus.Editing:
try
{
var storagePath = _Default.StoragePath(fileName, userAddress);
var histDir = _Default.HistoryDir(storagePath);
var versionDir = _Default.VersionDir(histDir, _Default.GetFileVersion(histDir));
if (!Directory.Exists(versionDir)) Directory.CreateDirectory(versionDir);
File.Copy(storagePath, Path.Combine(versionDir, "prev" + curExt));
DownloadToFile(downloadUri, _Default.StoragePath(fileName, userAddress));
DownloadToFile((string)fileData["changesurl"], Path.Combine(versionDir, "diff.zip"));
var hist = fileData.ContainsKey("changeshistory") ? (string)fileData["changeshistory"] : null;
if (string.IsNullOrEmpty(hist) && fileData.ContainsKey("history"))
var jss = new JavaScriptSerializer();
var actions = jss.Deserialize<List<object>>(jss.Serialize(fileData["actions"]));
var action = jss.Deserialize<Dictionary<string, object>>(jss.Serialize(actions[0]));
if (action != null && action["type"].ToString().Equals("0"))
{
hist = jss.Serialize(fileData["history"]);
}
var user = action["userid"].ToString();
var users = jss.Deserialize<List<object>>(jss.Serialize(fileData["users"]));
if (!users.Contains(user))
{
TrackManager.commandRequest("forcesave", fileData["key"].ToString());
}
if (!string.IsNullOrEmpty(hist))
{
File.WriteAllText(Path.Combine(versionDir, "changes.json"), hist);
}
}
catch (Exception e)
{
Debug.Print(e.StackTrace);
}
break;
File.WriteAllText(Path.Combine(versionDir, "key.txt"), (string)fileData["key"]);
case TrackerStatus.MustSave:
case TrackerStatus.Corrupted:
try
{
saved = TrackManager.processSave(fileData, fileName, userAddress);
}
catch (Exception e)
{
saved = 1;
}
context.Response.Write("{\"error\":" + saved + "}");
return;
case TrackerStatus.MustForceSave:
case TrackerStatus.CorruptedForceSave:
try
{
saved = TrackManager.processForceSave(fileData, fileName, userAddress);
}
catch (Exception)
{
saved = 0;
saved = 1;
}
break;
context.Response.Write("{\"error\":" + saved + "}");
return;
}
context.Response.Write("{\"error\":0}");
}
@ -272,51 +214,48 @@ namespace OnlineEditorsExample
}
}
private static void Download(HttpContext context)
private static void Assets(HttpContext context)
{
var fileName = "sample/" + Path.GetFileName(context.Request["filename"]);
download(fileName, context);
var fileName = Path.GetFileName(context.Request["filename"]);
var filePath = HttpRuntime.AppDomainAppPath + "assets/sample/" + fileName;
download(filePath, context);
}
private static void GetCsv(HttpContext context)
{
var fileName = "sample/" + "csv.csv";
download(fileName, context);
var fileName = "csv.csv";
var filePath = HttpRuntime.AppDomainAppPath + "assets/sample/" + fileName;
download(filePath, context);
}
private static void download(string fileName, HttpContext context)
private static void Download(HttpContext context)
{
var csvPath = HttpRuntime.AppDomainAppPath + "assets/" + fileName;
FileInfo fileinf = new FileInfo(csvPath);
try
{
var fileName = Path.GetFileName(context.Request["filename"]);
var filePath = _Default.ForcesavePath(fileName, null, false);
if (filePath.Equals(""))
{
filePath = _Default.StoragePath(fileName, null);
}
download(filePath, context);
}
catch (Exception)
{
context.Response.Write("{ \"error\": \"File not found!\"}");
}
}
private static void download(string filePath, HttpContext context)
{
FileInfo fileinf = new FileInfo(filePath);
context.Response.AddHeader("Content-Length", "" + fileinf.Length);
context.Response.AddHeader("Content-Type", MimeMapping.GetMimeMapping(csvPath));
var tmp = HttpUtility.UrlEncode(Path.GetFileName(csvPath));
context.Response.AddHeader("Content-Type", MimeMapping.GetMimeMapping(filePath));
var tmp = HttpUtility.UrlEncode(Path.GetFileName(filePath));
tmp = tmp.Replace("+", "%20");
context.Response.AddHeader("Content-Disposition", "attachment; filename*=UTF-8\'\'" + tmp);
context.Response.TransmitFile(csvPath);
}
private static void DownloadToFile(string url, string path)
{
if (string.IsNullOrEmpty(url)) throw new ArgumentException("url");
if (string.IsNullOrEmpty(path)) throw new ArgumentException("path");
var req = (HttpWebRequest)WebRequest.Create(url);
using (var stream = req.GetResponse().GetResponseStream())
{
if (stream == null) throw new Exception("stream is null");
const int bufferSize = 4096;
using (var fs = File.Open(path, FileMode.Create))
{
var buffer = new byte[bufferSize];
int readed;
while ((readed = stream.Read(buffer, 0, bufferSize)) != 0)
{
fs.Write(buffer, 0, readed);
}
}
}
context.Response.TransmitFile(filePath);
}
public bool IsReusable

View File

@ -7,17 +7,18 @@
<add key="files.docservice.viewed-docs" value=".pdf|.djvu|.xps"/>
<add key="files.docservice.edited-docs" value=".docx|.xlsx|.csv|.pptx|.txt"/>
<add key="files.docservice.convert-docs" value=".docm|.dotx|.dotm|.dot|.doc|.odt|.fodt|.ott|.xlsm|.xltx|.xltm|.xlt|.xls|.ods|.fods|.ots|.pptm|.ppt|.ppsx|.ppsm|.pps|.potx|.potm|.pot|.odp|.fodp|.otp|.rtf|.mht|.html|.htm|.epub|.fb2"/>
<add key="files.docservice.convert-docs" value=".docm|.dotx|.dotm|.dot|.doc|.odt|.fodt|.ott|.xlsm|.xltx|.xltm|.xlt|.xls|.ods|.fods|.ots|.pptm|.ppt|.ppsx|.ppsm|.pps|.potx|.potm|.pot|.odp|.fodp|.otp|.rtf|.mht|.html|.htm|.xml|.epub|.fb2"/>
<add key="files.docservice.timeout" value="120000" />
<add key="files.docservice.secret" value="" />
<add key="files.docservice.header" value="Authorization" />
<add key="files.docservice.url.site" value="http://documentserver/"/>
<add key="files.docservice.url.site" value="https://documentserver/"/>
<add key="files.docservice.url.converter" value="ConvertService.ashx"/>
<add key="files.docservice.url.api" value="web-apps/apps/api/documents/api.js"/>
<add key="files.docservice.url.preloader" value="web-apps/apps/api/documents/cache-scripts.html"/>
<add key="files.docservice.url.command" value="coauthoring/CommandService.ashx"/>
<add key="files.docservice.url.example" value=""/>
</appSettings>

View File

@ -74,7 +74,7 @@ public class EditorServlet extends HttpServlet
Map<String, Object> dataCompareFile = new HashMap<>();
dataCompareFile.put("fileType", "docx");
dataCompareFile.put("url", DocumentManager.GetServerUrl(true) + "/IndexServlet?type=download&name=sample.docx");
dataCompareFile.put("url", DocumentManager.GetServerUrl(true) + "/IndexServlet?type=assets&name=sample.docx");
Map<String, Object> dataMailMergeRecipients = new HashMap<>();
dataMailMergeRecipients.put("fileType", "csv");

View File

@ -19,10 +19,7 @@
package controllers;
import com.google.gson.Gson;
import helpers.ConfigManager;
import helpers.CookieManager;
import helpers.DocumentManager;
import helpers.ServiceConverter;
import helpers.*;
import java.io.*;
import java.net.URISyntaxException;
@ -39,7 +36,7 @@ import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.Part;
import entities.FileType;
import helpers.FileUtility;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
@ -49,8 +46,6 @@ import org.primeframework.jwt.domain.JWT;
@MultipartConfig
public class IndexServlet extends HttpServlet
{
private static final String DocumentJwtHeader = ConfigManager.GetProperty("files.docservice.header");
protected void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
String action = request.getParameter("type");
@ -69,6 +64,8 @@ public class IndexServlet extends HttpServlet
case "upload":
Upload(request, response, writer);
break;
case "download":
Download(request, response, writer);
case "convert":
Convert(request, response, writer);
break;
@ -78,8 +75,8 @@ public class IndexServlet extends HttpServlet
case "remove":
Remove(request, response, writer);
break;
case "download":
Download(request, response, writer);
case "assets":
Assets(request, response, writer);
break;
case "csv":
CSV(request, response, writer);
@ -124,7 +121,7 @@ public class IndexServlet extends HttpServlet
InputStream fileStream = httpPostedFile.getInputStream();
fileName = DocumentManager.GetCorrectName(fileName);
fileName = DocumentManager.GetCorrectName(fileName, null);
String fileStoragePath = DocumentManager.StoragePath(fileName, null);
File file = new File(fileStoragePath);
@ -142,7 +139,7 @@ public class IndexServlet extends HttpServlet
}
CookieManager cm = new CookieManager(request);
DocumentManager.CreateMeta(fileName, cm.getCookie("uid"), cm.getCookie("uname"));
DocumentManager.CreateMeta(fileName, cm.getCookie("uid"), cm.getCookie("uname"), null);
writer.write("{ \"filename\": \"" + fileName + "\"}");
@ -177,7 +174,7 @@ public class IndexServlet extends HttpServlet
return;
}
String correctName = DocumentManager.GetCorrectName(FileUtility.GetFileNameWithoutExtension(fileName) + internalFileExt);
String correctName = DocumentManager.GetCorrectName(FileUtility.GetFileNameWithoutExtension(fileName) + internalFileExt, null);
URL url = new URL(newFileUri);
java.net.HttpURLConnection connection = (java.net.HttpURLConnection) url.openConnection();
@ -210,7 +207,7 @@ public class IndexServlet extends HttpServlet
fileName = correctName;
CookieManager cm = new CookieManager(request);
DocumentManager.CreateMeta(fileName, cm.getCookie("uid"), cm.getCookie("uname"));
DocumentManager.CreateMeta(fileName, cm.getCookie("uid"), cm.getCookie("uname"), null);
}
writer.write("{ \"filename\" : \"" + fileName + "\"}");
@ -224,132 +221,53 @@ public class IndexServlet extends HttpServlet
private static void Track(HttpServletRequest request, HttpServletResponse response, PrintWriter writer)
{
JSONObject body = null;
try {
body = TrackManager.readBody(request, writer);
} catch (Exception e) {
e.printStackTrace();
return;
}
int status = Math.toIntExact((long) body.get("status"));
int saved = 0;
if (status == 1) { //Editing
JSONArray actions = (JSONArray) body.get("actions");
JSONArray users = (JSONArray) body.get("users");
JSONObject action = (JSONObject) actions.get(0);
if (actions != null && action.get("type").toString().equals("0")) { //finished edit
String user = (String) action.get("userid");
if (users.indexOf(user) == -1) {
String key = (String) body.get("key");
try {
TrackManager.commandRequest("forcesave", key);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
String userAddress = request.getParameter("userAddress");
String fileName = FileUtility.GetFileName(request.getParameter("fileName"));
String storagePath = DocumentManager.StoragePath(fileName, userAddress);
String body = "";
try
{
Scanner scanner = new Scanner(request.getInputStream());
scanner.useDelimiter("\\A");
body = scanner.hasNext() ? scanner.next() : "";
scanner.close();
}
catch (Exception ex)
{
writer.write("get request.getInputStream error:" + ex.getMessage());
return;
}
if (body.isEmpty())
{
writer.write("empty request.getInputStream");
return;
}
JSONParser parser = new JSONParser();
JSONObject jsonObj;
try
{
Object obj = parser.parse(body);
jsonObj = (JSONObject) obj;
}
catch (Exception ex)
{
writer.write("JSONParser.parse error:" + ex.getMessage());
return;
}
int status;
String downloadUri;
String changesUri;
String key;
if (DocumentManager.TokenEnabled())
{
String token = (String) jsonObj.get("token");
if (token == null) {
String header = (String) request.getHeader(DocumentJwtHeader == null || DocumentJwtHeader.isEmpty() ? "Authorization" : DocumentJwtHeader);
if (header != null && !header.isEmpty()) {
token = header.startsWith("Bearer ") ? header.substring(7) : header;
}
if (status == 2 || status == 3) { //MustSave, Corrupted
try {
TrackManager.processSave(body, fileName, userAddress);
} catch (Exception ex) {
ex.printStackTrace();
saved = 1;
}
if (token == null || token.isEmpty()) {
writer.write("{\"error\":1,\"message\":\"JWT expected\"}");
return;
}
JWT jwt = DocumentManager.ReadToken(token);
if (jwt == null)
{
writer.write("{\"error\":1,\"message\":\"JWT validation failed\"}");
return;
}
if (jwt.getObject("payload") != null) {
try {
@SuppressWarnings("unchecked") LinkedHashMap<String, Object> payload =
(LinkedHashMap<String, Object>)jwt.getObject("payload");
jwt.claims = payload;
}
catch (Exception ex) {
writer.write("{\"error\":1,\"message\":\"Wrong payload\"}");
return;
}
}
status = jwt.getInteger("status");
downloadUri = jwt.getString("url");
changesUri = jwt.getString("changesurl");
key = jwt.getString("key");
}
else
{
status = Math.toIntExact((long) jsonObj.get("status"));
downloadUri = (String) jsonObj.get("url");
changesUri = (String) jsonObj.get("changesurl");
key = (String) jsonObj.get("key");
}
int saved = 0;
if (status == 2 || status == 3)//MustSave, Corrupted
{
try
{
String histDir = DocumentManager.HistoryDir(storagePath);
String versionDir = DocumentManager.VersionDir(histDir, DocumentManager.GetFileVersion(histDir));
File ver = new File(versionDir);
File toSave = new File(storagePath);
if (!ver.exists()) ver.mkdirs();
toSave.renameTo(new File(versionDir + File.separator + "prev" + FileUtility.GetFileExtension(fileName)));
downloadToFile(downloadUri, toSave);
downloadToFile(changesUri, new File(versionDir + File.separator + "diff.zip"));
String history = (String) jsonObj.get("changeshistory");
if (history == null && jsonObj.containsKey("history")) {
history = ((JSONObject) jsonObj.get("history")).toJSONString();
}
if (history != null && !history.isEmpty()) {
FileWriter fw = new FileWriter(new File(versionDir + File.separator + "changes.json"));
fw.write(history);
fw.close();
}
FileWriter fw = new FileWriter(new File(versionDir + File.separator + "key.txt"));
fw.write(key);
fw.close();
}
catch (Exception ex)
{
if (status == 6 || status == 7) { //MustForceSave, CorruptedForceSave
try {
TrackManager.processForceSave(body, fileName, userAddress);
} catch (Exception ex) {
ex.printStackTrace();
saved = 1;
}
}
@ -408,13 +326,41 @@ public class IndexServlet extends HttpServlet
private static void CSV(HttpServletRequest request, HttpServletResponse response, PrintWriter writer)
{
String fileName = "assets/sample/csv.csv";
download(fileName, response, writer);
URL fileUrl = Thread.currentThread().getContextClassLoader().getResource(fileName);
Path filePath = null;
try {
filePath = Paths.get(fileUrl.toURI());
} catch (URISyntaxException e) {
e.printStackTrace();
}
download(filePath.toString(), response, writer);
}
private static void Assets(HttpServletRequest request, HttpServletResponse response, PrintWriter writer)
{
String fileName = "assets/sample/" + FileUtility.GetFileName(request.getParameter("name"));
URL fileUrl = Thread.currentThread().getContextClassLoader().getResource(fileName);
Path filePath = null;
try {
filePath = Paths.get(fileUrl.toURI());
} catch (URISyntaxException e) {
e.printStackTrace();
}
download(filePath.toString(), response, writer);
}
private static void Download(HttpServletRequest request, HttpServletResponse response, PrintWriter writer)
{
String fileName = "assets/sample/" + FileUtility.GetFileName(request.getParameter("name"));
download(fileName, response, writer);
try {
String fileName = FileUtility.GetFileName(request.getParameter("name"));
String filePath = DocumentManager.ForcesavePath(fileName, null, false);
if (filePath.equals("")) {
filePath = DocumentManager.StoragePath(fileName, null);
}
download(filePath, response, writer);
} catch (Exception e) {
writer.write("{ \"error\": \"File not found\"}");
}
}
private static void delete(File f) throws Exception {
@ -426,18 +372,15 @@ public class IndexServlet extends HttpServlet
throw new Exception("Failed to delete file: " + f);
}
private static void download(String fileName, HttpServletResponse response, PrintWriter writer) {
URL fileUrl = Thread.currentThread().getContextClassLoader().getResource(fileName);
Path filePath = null;
private static void download(String filePath, HttpServletResponse response, PrintWriter writer) {
String fileType = null;
try {
filePath = Paths.get(fileUrl.toURI());
fileType = Files.probeContentType(filePath);
} catch (URISyntaxException | IOException e) {
fileType = Files.probeContentType(Paths.get(filePath));
} catch (IOException e) {
e.printStackTrace();
}
File file = new File(String.valueOf(filePath));
File file = new File(filePath);
response.setHeader("Content-Length", String.valueOf(file.length()));
response.setHeader("Content-Type", fileType);
@ -461,34 +404,6 @@ public class IndexServlet extends HttpServlet
}
}
private static void downloadToFile(String url, File file) throws Exception {
if (url == null || url.isEmpty()) throw new Exception("argument url");
if (file == null) throw new Exception("argument path");
URL uri = new URL(url);
java.net.HttpURLConnection connection = (java.net.HttpURLConnection) uri.openConnection();
InputStream stream = connection.getInputStream();
if (stream == null)
{
throw new Exception("Stream is null");
}
try (FileOutputStream out = new FileOutputStream(file))
{
int read;
final byte[] bytes = new byte[1024];
while ((read = stream.read(bytes)) != -1)
{
out.write(bytes, 0, read);
}
out.flush();
}
connection.disconnect();
}
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{

View File

@ -62,7 +62,9 @@ public class FileModel
if (lang != null) editorConfig.lang = lang;
if (uid != null) editorConfig.user.id = uid;
if (uname != null) editorConfig.user.name = uname;
if (uname != null) editorConfig.user.name = uid.equals("uid-0") ? null : uname;
if (editorConfig.user.id.equals("uid-2")) editorConfig.user.group = "group-2";
if (editorConfig.user.id.equals("uid-3")) editorConfig.user.group = "group-3";
editorConfig.customization.goback.url = DocumentManager.GetServerUrl(false) + "/IndexServlet";
@ -75,7 +77,7 @@ public class FileModel
if (_type != null) type = _type;
Boolean canEdit = DocumentManager.GetEditedExts().contains(FileUtility.GetFileExtension(document.title));
editorConfig.customization.submitForm = canEdit && (mode.equals("edit") || mode.equals("fillForms"));
editorConfig.mode = canEdit && !mode.equals("view") ? "edit" : "view";
document.permissions = new Permissions(mode, type, canEdit);
@ -211,6 +213,7 @@ public class FileModel
public Boolean modifyFilter;
public Boolean modifyContentControl;
public Boolean review;
public List<String> reviewGroups;
public Permissions(String mode, String type, Boolean canEdit)
{
@ -221,6 +224,16 @@ public class FileModel
modifyFilter = !mode.equals("filter");
modifyContentControl = !mode.equals("blockcontent");
review = mode.equals("edit") || mode.equals("review");
reviewGroups = editorConfig.user.group != null ? GetReviewGroups(editorConfig.user.group) : null;
}
private List<String> GetReviewGroups(String group){
Map<String, List<String>> reviewGroups = new HashMap<>();
reviewGroups.put("group-2", Arrays.asList("group-2", ""));
reviewGroups.put("group-3", Arrays.asList("group-2"));
return reviewGroups.get(group);
}
}
@ -262,14 +275,18 @@ public class FileModel
{
public String id = "uid-1";
public String name = "John Smith";
public String group = null;
}
public class Customization
{
public Goback goback;
public Boolean forcesave;
public Boolean submitForm;
public Customization()
{
forcesave = false;
goback = new Goback();
}

View File

@ -135,6 +135,32 @@ public class DocumentManager
return directory + FileUtility.GetFileName(fileName);
}
public static String ForcesavePath(String fileName, String userAddress, Boolean create)
{
String hostAddress = CurUserHostAddress(userAddress);
String serverPath = request.getSession().getServletContext().getRealPath("");
String storagePath = ConfigManager.GetProperty("storage-folder");
String directory = serverPath + storagePath + File.separator + hostAddress + File.separator;
File file = new File(directory);
if (!file.exists()) return "";
directory = directory + fileName + "-hist" + File.separator;
file = new File(directory);
if (!create && !file.exists()) return "";
file.mkdirs();
directory = directory + fileName;
file = new File(directory);
if (!create && !file.exists()) {
return "";
}
return directory;
}
public static String HistoryDir(String storagePath)
{
return storagePath += "-hist";
@ -171,26 +197,26 @@ public class DocumentManager
return GetFileVersion(HistoryDir(StoragePath(fileName, userAddress)));
}
public static String GetCorrectName(String fileName)
public static String GetCorrectName(String fileName, String userAddress)
{
String baseName = FileUtility.GetFileNameWithoutExtension(fileName);
String ext = FileUtility.GetFileExtension(fileName);
String name = baseName + ext;
File file = new File(StoragePath(name, null));
File file = new File(StoragePath(name, userAddress));
for (int i = 1; file.exists(); i++)
{
name = baseName + " (" + i + ")" + ext;
file = new File(StoragePath(name, null));
file = new File(StoragePath(name, userAddress));
}
return name;
}
public static void CreateMeta(String fileName, String uid, String uname) throws Exception
public static void CreateMeta(String fileName, String uid, String uname, String userAddress) throws Exception
{
String histDir = HistoryDir(StoragePath(fileName, null));
String histDir = HistoryDir(StoragePath(fileName, userAddress));
File dir = new File(histDir);
dir.mkdir();
@ -223,7 +249,7 @@ public class DocumentManager
{
String demoName = (sample ? "sample." : "new.") + fileExt;
String demoPath = "assets" + File.separator + (sample ? "sample" : "new") + File.separator;
String fileName = GetCorrectName(demoName);
String fileName = GetCorrectName(demoName, null);
InputStream stream = Thread.currentThread().getContextClassLoader().getResourceAsStream(demoPath + demoName);
@ -240,7 +266,7 @@ public class DocumentManager
out.flush();
}
CreateMeta(fileName, uid, uname);
CreateMeta(fileName, uid, uname, null);
return fileName;
}

View File

@ -50,7 +50,7 @@ public class FileUtility
".doc", ".docx", ".docm",
".dot", ".dotx", ".dotm",
".odt", ".fodt", ".ott", ".rtf", ".txt",
".html", ".htm", ".mht",
".html", ".htm", ".mht", ".xml",
".pdf", ".djvu", ".fb2", ".epub", ".xps"
);

View File

@ -223,7 +223,7 @@ public class ServiceConverter
return resultPercent >= 100l ? responseUri : "";
}
private static String ConvertStreamToString(InputStream stream) throws IOException
public static String ConvertStreamToString(InputStream stream) throws IOException
{
InputStreamReader inputStreamReader = new InputStreamReader(stream);
StringBuilder stringBuilder = new StringBuilder();
@ -241,7 +241,7 @@ public class ServiceConverter
return result;
}
private static JSONObject ConvertStringToJSON(String jsonString) throws ParseException
public static JSONObject ConvertStringToJSON(String jsonString) throws ParseException
{
JSONParser parser = new JSONParser();
Object obj = parser.parse(jsonString);

View File

@ -0,0 +1,299 @@
/**
*
* (c) Copyright Ascensio System SIA 2020
*
* 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 helpers;
import com.google.gson.Gson;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.primeframework.jwt.domain.JWT;
import javax.servlet.http.HttpServletRequest;
import java.io.*;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Scanner;
public class TrackManager {
private static final String DocumentJwtHeader = ConfigManager.GetProperty("files.docservice.header");
public static JSONObject readBody(HttpServletRequest request, PrintWriter writer) throws Exception {
String bodyString = "";
try {
Scanner scanner = new Scanner(request.getInputStream());
scanner.useDelimiter("\\A");
bodyString = scanner.hasNext() ? scanner.next() : "";
scanner.close();
}
catch (Exception ex) {
writer.write("get request.getInputStream error:" + ex.getMessage());
throw ex;
}
if (bodyString.isEmpty()) {
writer.write("empty request.getInputStream");
throw new Exception("empty request.getInputStream");
}
JSONParser parser = new JSONParser();
JSONObject body;
try {
Object obj = parser.parse(bodyString);
body = (JSONObject) obj;
} catch (Exception ex) {
writer.write("JSONParser.parse error:" + ex.getMessage());
throw ex;
}
if (DocumentManager.TokenEnabled()) {
String token = (String) body.get("token");
if (token == null) {
String header = (String) request.getHeader(DocumentJwtHeader == null || DocumentJwtHeader.isEmpty() ? "Authorization" : DocumentJwtHeader);
if (header != null && !header.isEmpty()) {
token = header.startsWith("Bearer ") ? header.substring(7) : header;
}
}
if (token == null || token.isEmpty()) {
writer.write("{\"error\":1,\"message\":\"JWT expected\"}");
throw new Exception("{\"error\":1,\"message\":\"JWT expected\"}");
}
JWT jwt = DocumentManager.ReadToken(token);
if (jwt == null) {
writer.write("{\"error\":1,\"message\":\"JWT validation failed\"}");
throw new Exception("{\"error\":1,\"message\":\"JWT validation failed\"}");
}
if (jwt.getObject("payload") != null) {
try {
@SuppressWarnings("unchecked") LinkedHashMap<String, Object> payload =
(LinkedHashMap<String, Object>)jwt.getObject("payload");
jwt.claims = payload;
} catch (Exception ex) {
writer.write("{\"error\":1,\"message\":\"Wrong payload\"}");
throw ex;
}
}
try {
Gson gson = new Gson();
Object obj = parser.parse(gson.toJson(jwt.claims));
body = (JSONObject) obj;
} catch (Exception ex) {
writer.write("JSONParser.parse error:" + ex.getMessage());
throw ex;
}
}
return body;
}
public static void processSave(JSONObject body, String fileName, String userAddress) throws Exception {
String downloadUri = (String) body.get("url");
String changesUri = (String) body.get("changesurl");
String key = (String) body.get("key");
String newFileName = fileName;
String curExt = FileUtility.GetFileExtension(fileName);
String downloadExt = FileUtility.GetFileExtension(downloadUri);
if (!curExt.equals(downloadExt)) {
try {
String newFileUri = ServiceConverter.GetConvertedUri(downloadUri, downloadExt, curExt, ServiceConverter.GenerateRevisionId(downloadUri), false);
if (newFileUri.isEmpty()) {
newFileName = DocumentManager.GetCorrectName(FileUtility.GetFileNameWithoutExtension(fileName) + downloadExt, userAddress);
} else {
downloadUri = newFileUri;
}
} catch (Exception e){
newFileName = DocumentManager.GetCorrectName(FileUtility.GetFileNameWithoutExtension(fileName) + downloadExt, userAddress);
}
}
String storagePath = DocumentManager.StoragePath(newFileName, userAddress);
File histDir = new File(DocumentManager.HistoryDir(storagePath));
if (!histDir.exists()) histDir.mkdirs();
String versionDir = DocumentManager.VersionDir(histDir.getAbsolutePath(), DocumentManager.GetFileVersion(histDir.getAbsolutePath()));
File ver = new File(versionDir);
File lastVersion = new File(DocumentManager.StoragePath(fileName, userAddress));
File toSave = new File(storagePath);
if (!ver.exists()) ver.mkdirs();
lastVersion.renameTo(new File(versionDir + File.separator + "prev" + curExt));
downloadToFile(downloadUri, toSave);
downloadToFile(changesUri, new File(versionDir + File.separator + "diff.zip"));
String history = (String) body.get("changeshistory");
if (history == null && body.containsKey("history")) {
history = ((JSONObject) body.get("history")).toJSONString();
}
if (history != null && !history.isEmpty()) {
FileWriter fw = new FileWriter(new File(versionDir + File.separator + "changes.json"));
fw.write(history);
fw.close();
}
FileWriter fw = new FileWriter(new File(versionDir + File.separator + "key.txt"));
fw.write(key);
fw.close();
String forcesavePath = DocumentManager.ForcesavePath(newFileName, userAddress, false);
if (!forcesavePath.equals("")) {
File forceSaveFile = new File(forcesavePath);
forceSaveFile.delete();
}
}
public static void processForceSave(JSONObject body, String fileName, String userAddress) throws Exception {
String downloadUri = (String) body.get("url");
String curExt = FileUtility.GetFileExtension(fileName);
String downloadExt = FileUtility.GetFileExtension(downloadUri);
String newFileName = fileName;
if (!curExt.equals(downloadExt)) {
try {
String newFileUri = ServiceConverter.GetConvertedUri(downloadUri, downloadExt, curExt, ServiceConverter.GenerateRevisionId(downloadUri), false);
if (newFileUri.isEmpty()) {
newFileName = DocumentManager.GetCorrectName(FileUtility.GetFileNameWithoutExtension(fileName) + downloadExt, userAddress);
} else {
downloadUri = newFileUri;
}
} catch (Exception e){
newFileName = DocumentManager.GetCorrectName(FileUtility.GetFileNameWithoutExtension(fileName) + downloadExt, userAddress);
}
}
String forcesavePath = "";
boolean isSubmitForm = body.get("forcesavetype").toString().equals("3");
if (isSubmitForm) {
//new file
if (newFileName.equals(fileName)){
newFileName = DocumentManager.GetCorrectName(fileName, userAddress);
}
forcesavePath = DocumentManager.StoragePath(newFileName, userAddress);
} else {
forcesavePath = DocumentManager.ForcesavePath(newFileName, userAddress, false);
if (forcesavePath == "") {
forcesavePath = DocumentManager.ForcesavePath(newFileName, userAddress, true);
}
}
File toSave = new File(forcesavePath);
downloadToFile(downloadUri, toSave);
if (isSubmitForm) {
JSONArray actions = (JSONArray) body.get("actions");
JSONObject action = (JSONObject) actions.get(0);
String user = (String) action.get("userid");
DocumentManager.CreateMeta(newFileName, user, "Filling Form", userAddress);
}
}
private static void downloadToFile(String url, File file) throws Exception {
if (url == null || url.isEmpty()) throw new Exception("argument url");
if (file == null) throw new Exception("argument path");
URL uri = new URL(url);
java.net.HttpURLConnection connection = (java.net.HttpURLConnection) uri.openConnection();
InputStream stream = connection.getInputStream();
if (stream == null)
{
throw new Exception("Stream is null");
}
try (FileOutputStream out = new FileOutputStream(file))
{
int read;
final byte[] bytes = new byte[1024];
while ((read = stream.read(bytes)) != -1)
{
out.write(bytes, 0, read);
}
out.flush();
}
connection.disconnect();
}
public static void commandRequest(String method, String key) throws Exception {
String DocumentCommandUrl = ConfigManager.GetProperty("files.docservice.url.site") + ConfigManager.GetProperty("files.docservice.url.command");
URL url = new URL(DocumentCommandUrl);
java.net.HttpURLConnection connection = (java.net.HttpURLConnection) url.openConnection();
HashMap<String, Object> params = new HashMap<String, Object>();
params.put("c", method);
params.put("key", key);
String headerToken = "";
if (DocumentManager.TokenEnabled())
{
Map<String, Object> payloadMap = new HashMap<String, Object>();
payloadMap.put("payload", params);
headerToken = DocumentManager.CreateToken(payloadMap);
connection.setRequestProperty(DocumentJwtHeader.equals("") ? "Authorization" : DocumentJwtHeader, "Bearer " + headerToken);
String token = DocumentManager.CreateToken(params);
params.put("token", token);
}
Gson gson = new Gson();
String bodyString = gson.toJson(params);
byte[] bodyByte = bodyString.getBytes(StandardCharsets.UTF_8);
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Type", "application/json; charset=UTF-8");
connection.setDoOutput(true);
connection.connect();
try (OutputStream os = connection.getOutputStream()) {
os.write(bodyByte);
}
InputStream stream = connection.getInputStream();;
if (stream == null)
throw new Exception("Could not get an answer");
String jsonString = ServiceConverter.ConvertStreamToString(stream);
connection.disconnect();
JSONObject response = ServiceConverter.ConvertStringToJSON(jsonString);
if (!response.get("error").toString().equals("0")){
throw new Exception(response.toJSONString());
}
}
}

View File

@ -3,11 +3,12 @@ storage-folder=app_data
files.docservice.viewed-docs=.pdf|.djvu|.xps
files.docservice.edited-docs=.docx|.xlsx|.csv|.pptx|.txt
files.docservice.convert-docs=.docm|.dotx|.dotm|.dot|.doc|.odt|.fodt|.ott|.xlsm|.xltx|.xltm|.xlt|.xls|.ods|.fods|.ots|.pptm|.ppt|.ppsx|.ppsm|.pps|.potx|.potm|.pot|.odp|.fodp|.otp|.rtf|.mht|.html|.htm|.epub|.fb2
files.docservice.convert-docs=.docm|.dotx|.dotm|.dot|.doc|.odt|.fodt|.ott|.xlsm|.xltx|.xltm|.xlt|.xls|.ods|.fods|.ots|.pptm|.ppt|.ppsx|.ppsm|.pps|.potx|.potm|.pot|.odp|.fodp|.otp|.rtf|.mht|.html|.htm|.xml|.epub|.fb2
files.docservice.timeout=120000
files.docservice.url.site=https://documentserver/
files.docservice.url.converter=ConvertService.ashx
files.docservice.url.command=coauthoring/CommandService.ashx
files.docservice.url.api=web-apps/apps/api/documents/api.js
files.docservice.url.preloader=web-apps/apps/api/documents/cache-scripts.html
files.docservice.url.example=

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.2 KiB

View File

@ -1,6 +1,8 @@
<%@page import="entities.FileModel"%>
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<% FileModel Model = (FileModel) request.getAttribute("file"); %>
<!DOCTYPE html>
<html>
<head>
@ -26,11 +28,9 @@
*
-->
<title>ONLYOFFICE</title>
<link rel="icon" href="favicon.ico" type="image/x-icon" />
<link rel="icon" href="css/img/<%= Model.documentType %>.ico" type="image/x-icon" />
<link rel="stylesheet" type="text/css" href="css/editor.css" />
<% FileModel Model = (FileModel) request.getAttribute("file"); %>
<script type="text/javascript" src="${docserviceApiUrl}"></script>
<script type="text/javascript" language="javascript">

View File

@ -56,6 +56,7 @@
<option value="uid-1">John Smith</option>
<option value="uid-2">Mark Pottato</option>
<option value="uid-3">Hamish Mitchell</option>
<option value="uid-0">anonymous</option>
</select>
</td>
<td width="70%" valign="middle">Select user name before opening the document; you can open the same document using different users in different Web browser sessions, so you can check out multi-user editing functions.</td>
@ -156,7 +157,7 @@
<a class="stored-edit <%= docType %>" href="EditorServlet?fileName=<%= URLEncoder.encode(files[i].getName(), "UTF-8") %>" target="_blank">
<span title="<%= files[i].getName() %>"><%= files[i].getName() %></span>
</a>
<a href="<%= DocumentManager.GetFileUri(files[i].getName(), false) %>">
<a href="IndexServlet?type=download&name=<%=URLEncoder.encode(files[i].getName(), "UTF-8")%>">
<img class="icon-download" src="css/img/download-24.png" alt="Download" title="Download" />
</a>
<a class="delete-file" data-filename="<%= files[i].getName() %>">

View File

@ -65,7 +65,7 @@ function key(k) {
};
var getDocumentType = function (ext) {
if (".doc.docx.docm.dot.dotx.dotm.odt.fodt.ott.rtf.txt.html.htm.mht.pdf.djvu.fb2.epub.xps".indexOf(ext) != -1) return "text";
if (".doc.docx.docm.dot.dotx.dotm.odt.fodt.ott.rtf.txt.html.htm.mht.xml.pdf.djvu.fb2.epub.xps".indexOf(ext) != -1) return "text";
if (".xls.xlsx.xlsm.xlt.xltx.xltm.ods.fods.ots.csv".indexOf(ext) != -1) return "spreadsheet";
if (".pps.ppsx.ppsm.ppt.pptx.pptm.pot.potx.potm.odp.fodp.otp".indexOf(ext) != -1) return "presentation";
return null;

View File

@ -0,0 +1,28 @@
FROM node:buster
LABEL maintainer Ascensio System SIA <support@onlyoffice.com>
ENV LANG=en_US.UTF-8 \
LANGUAGE=en_US:en \
LC_ALL=en_US.UTF-8 \
NODE_ENV=production-linux \
NODE_CONFIG_DIR=/etc/onlyoffice/documentserver-example/
WORKDIR /var/www/onlyoffice/documentserver-example/
COPY . /var/www/onlyoffice/documentserver-example/
RUN groupadd --system --gid 1001 ds && \
useradd --system -g ds --no-create-home --shell /sbin/nologin --uid 1001 ds && \
chown -R ds:ds /var/www/onlyoffice/documentserver-example/ && \
mkdir -p /var/lib/onlyoffice/documentserver-example/ && \
chown -R ds:ds /var/lib/onlyoffice/ && \
mv files /var/lib/onlyoffice/documentserver-example/ && \
mkdir -p /etc/onlyoffice/documentserver-example/ && \
chown -R ds:ds /etc/onlyoffice/ && \
mv config/* /etc/onlyoffice/documentserver-example/ && \
npm install
EXPOSE 3000
USER ds
ENTRYPOINT /var/www/onlyoffice/documentserver-example/docker-entrypoint.sh npm start

View File

@ -363,110 +363,155 @@ app.post("/track", function (req, res) {
var processTrack = function (response, body, fileName, userAddress) {
var processSave = function (downloadUri, body, fileName, userAddress, resp) {
var curExt = fileUtility.getFileExtension(fileName);
var downloadExt = fileUtility.getFileExtension(downloadUri);
if (downloadExt != curExt) {
var key = documentService.generateRevisionId(downloadUri);
try {
documentService.getConvertedUriSync(downloadUri, downloadExt, curExt, key, function (dUri) {
processSave(dUri, body, fileName, userAddress, resp)
});
return;
} catch (ex) {
console.log(ex);
fileName = docManager.getCorrectName(fileUtility.getFileName(fileName, true) + downloadExt, userAddress)
}
}
var callbackProcessSave = function (downloadUri, body, fileName, userAddress, newFileName) {
try {
var storagePath = docManager.storagePath(newFileName, userAddress);
var path = docManager.storagePath(fileName, userAddress);
if (docManager.existsSync(path)) {
var historyPath = docManager.historyPath(fileName, userAddress);
if (historyPath == "") {
historyPath = docManager.historyPath(fileName, userAddress, true);
docManager.createDirectory(historyPath);
}
var count_version = docManager.countVersion(historyPath);
version = count_version + 1;
var versionPath = docManager.versionPath(fileName, userAddress, version);
docManager.createDirectory(versionPath);
var downloadZip = body.changesurl;
if (downloadZip) {
var path_changes = docManager.diffPath(fileName, userAddress, version);
var diffZip = syncRequest("GET", downloadZip);
fileSystem.writeFileSync(path_changes, diffZip.getBody());
}
var changeshistory = body.changeshistory || JSON.stringify(body.history);
if (changeshistory) {
var path_changes_json = docManager.changesPath(fileName, userAddress, version);
fileSystem.writeFileSync(path_changes_json, changeshistory);
}
var path_key = docManager.keyPath(fileName, userAddress, version);
fileSystem.writeFileSync(path_key, body.key);
var path_prev = docManager.prevFilePath(fileName, userAddress, version);
fileSystem.writeFileSync(path_prev, fileSystem.readFileSync(path));
var file = syncRequest("GET", downloadUri);
fileSystem.writeFileSync(path, file.getBody());
var forcesavePath = docManager.forcesavePath(fileName, userAddress, false);
if (forcesavePath != "") {
fileSystem.unlinkSync(forcesavePath);
}
var historyPath = docManager.historyPath(newFileName, userAddress);
if (historyPath == "") {
historyPath = docManager.historyPath(newFileName, userAddress, true);
docManager.createDirectory(historyPath);
}
var count_version = docManager.countVersion(historyPath);
version = count_version + 1;
var versionPath = docManager.versionPath(newFileName, userAddress, version);
docManager.createDirectory(versionPath);
var downloadZip = body.changesurl;
if (downloadZip) {
var path_changes = docManager.diffPath(newFileName, userAddress, version);
var diffZip = syncRequest("GET", downloadZip);
fileSystem.writeFileSync(path_changes, diffZip.getBody());
}
var changeshistory = body.changeshistory || JSON.stringify(body.history);
if (changeshistory) {
var path_changes_json = docManager.changesPath(newFileName, userAddress, version);
fileSystem.writeFileSync(path_changes_json, changeshistory);
}
var path_key = docManager.keyPath(newFileName, userAddress, version);
fileSystem.writeFileSync(path_key, body.key);
var path_prev = path.join(versionPath, "prev" + fileUtility.getFileExtension(fileName));
fileSystem.renameSync(docManager.storagePath(fileName, userAddress), path_prev);
var file = syncRequest("GET", downloadUri);
fileSystem.writeFileSync(storagePath, file.getBody());
var forcesavePath = docManager.forcesavePath(newFileName, userAddress, false);
if (forcesavePath != "") {
fileSystem.unlinkSync(forcesavePath);
}
} catch (ex) {
console.log(ex);
response.write("{\"error\":1}");
response.end();
return;
}
response.write("{\"error\":0}");
response.end();
};
}
var processForceSave = function (downloadUri, body, fileName, userAddress, resp) {
var processSave = function (downloadUri, body, fileName, userAddress, resp) {
var curExt = fileUtility.getFileExtension(fileName);
var downloadExt = fileUtility.getFileExtension(downloadUri);
var newFileName = fileName;
if (downloadExt != curExt) {
var key = documentService.generateRevisionId(downloadUri);
newFileName = docManager.getCorrectName(fileUtility.getFileName(fileName, true) + downloadExt, userAddress);
try {
documentService.getConvertedUriSync(downloadUri, downloadExt, curExt, key, function (dUri) {
processForceSave(dUri, body, fileName, userAddress, resp)
documentService.getConvertedUriSync(downloadUri, downloadExt, curExt, key, function (err, data) {
if (err) {
callbackProcessSave(downloadUri, body, fileName, userAddress, newFileName);
return;
}
try {
var res = documentService.getResponseUri(data);
callbackProcessSave(res.value, body, fileName, userAddress, fileName);
return;
} catch (ex) {
console.log(ex);
callbackProcessSave(downloadUri, body, fileName, userAddress, newFileName);
return;
}
});
return;
} catch (ex) {
console.log(ex);
fileName = docManager.getCorrectName(fileUtility.getFileName(fileName, true) + downloadExt, userAddress)
}
}
callbackProcessSave(downloadUri, body, fileName, userAddress, newFileName);
};
var callbackProcessForceSave = function (downloadUri, body, fileName, userAddress, newFileName){
try {
var isSubmitForm = body.forcesavetype === 3; //SubmitForm
var path = docManager.storagePath(fileName, userAddress);
var forcesavePath = docManager.forcesavePath(fileName, userAddress, false);
if (forcesavePath == "") {
forcesavePath = docManager.forcesavePath(fileName, userAddress, true);
if (isSubmitForm) {
//new file
if (newFileName == fileName){
newFileName = docManager.getCorrectName(fileName, userAddress);
}
var forcesavePath = docManager.storagePath(newFileName, userAddress);
} else {
forcesavePath = docManager.forcesavePath(newFileName, userAddress, false);
if (forcesavePath == "") {
forcesavePath = docManager.forcesavePath(newFileName, userAddress, true);
}
}
var file = syncRequest("GET", downloadUri);
fileSystem.writeFileSync(forcesavePath, file.getBody());
if (isSubmitForm) {
var uid =body.actions[0].userid
docManager.saveFileData(newFileName, uid, "Filling Form", userAddress);
}
} catch (ex) {
console.log(ex);
response.write("{\"error\":1}");
response.end();
return;
}
response.write("{\"error\":0}");
response.end();
}
var processForceSave = function (downloadUri, body, fileName, userAddress, resp) {
var curExt = fileUtility.getFileExtension(fileName);
var downloadExt = fileUtility.getFileExtension(downloadUri);
var newFileName = fileName;
if (downloadExt != curExt) {
var key = documentService.generateRevisionId(downloadUri);
try {
documentService.getConvertedUriSync(downloadUri, downloadExt, curExt, key, function (err, data) {
if (err) {
newFileName = docManager.getCorrectName(fileUtility.getFileName(fileName, true) + downloadExt, userAddress);
callbackProcessForceSave(downloadUri, body, fileName, userAddress, newFileName);
return;
}
try {
var res = documentService.getResponseUri(data);
callbackProcessForceSave(res.value, body, fileName, userAddress, newFileName);
return;
} catch (ex) {
console.log(ex);
newFileName = docManager.getCorrectName(fileUtility.getFileName(fileName, true) + downloadExt, userAddress);
callbackProcessForceSave(downloadUri, body, fileName, userAddress, newFileName);
return;
}
});
return;
} catch (ex) {
console.log(ex);
}
}
callbackProcessForceSave (downloadUri, body, fileName, userAddress, newFileName);
};
if (body.status == 1) { //Editing
@ -553,9 +598,22 @@ app.get("/editor", function (req, res) {
var historyData = [];
var lang = docManager.getLang();
var userid = req.query.userid ? req.query.userid : "uid-1";
var name = req.query.name ? req.query.name : "John Smith";
var name = (userid == "uid-0" ? null : (req.query.name ? req.query.name : "John Smith"));
var actionData = req.query.action ? req.query.action : "null";
var userGroup = null;
var reviewGroups = null;
if (userid == "uid-2")
{
userGroup = "group-2";
// own and without group
reviewGroups = ["group-2", ""];
} else if (userid == "uid-3") {
userGroup = "group-3";
// other group only
reviewGroups = ["group-2"];
}
if (fileExt != null) {
var fileName = docManager.createDemo(!!req.query.sample, fileExt, userid, name);
@ -581,6 +639,7 @@ app.get("/editor", function (req, res) {
}
var canEdit = configServer.get('editedDocs').indexOf(fileUtility.getFileExtension(fileName)) != -1;
var submitForm = canEdit && (mode == "edit" || mode == "fillForms");
var countVersion = 1;
@ -666,7 +725,10 @@ app.get("/editor", function (req, res) {
lang: lang,
userid: userid,
name: name,
userGroup: userGroup,
reviewGroups: JSON.stringify(reviewGroups),
fileChoiceUrl: fileChoiceUrl,
submitForm: submitForm,
plugins: JSON.stringify(plugins),
actionData: actionData
},

View File

@ -20,7 +20,7 @@
"exampleUrl": null,
"viewedDocs": [".pdf", ".djvu", ".xps"],
"editedDocs": [".docx", ".xlsx", ".csv", ".pptx", ".txt"],
"convertedDocs": [".docm", ".doc", ".dotx", ".dotm", ".dot", ".odt", ".fodt", ".ott", ".xlsm", ".xls", ".xltx", ".xltm", ".xlt", ".ods", ".fods", ".ots", ".pptm", ".ppt", ".ppsx", ".ppsm", ".pps", ".potx", ".potm", ".pot", ".odp", ".fodp", ".otp", ".rtf", ".mht", ".html", ".htm", ".epub", ".fb2"],
"convertedDocs": [".docm", ".doc", ".dotx", ".dotm", ".dot", ".odt", ".fodt", ".ott", ".xlsm", ".xls", ".xltx", ".xltm", ".xlt", ".ods", ".fods", ".ots", ".pptm", ".ppt", ".ppsx", ".ppsm", ".pps", ".potx", ".potm", ".pot", ".odp", ".fodp", ".otp", ".rtf", ".mht", ".html", ".htm", ".xml", ".epub", ".fb2"],
"storageFolder": "./files",
"storagePath": "/files",
"maxFileSize": 1073741824,

View File

@ -1,7 +1,7 @@
{
"server": {
"port": 3000,
"siteUrl": "http://127.0.0.1:8001/",
"siteUrl": "http://127.0.0.1:8000/",
"apiUrl": "web-apps/apps/api/documents/api.js",
"preloaderUrl": "web-apps/apps/api/documents/cache-scripts.html"
}

View File

@ -1,7 +1,7 @@
{
"server": {
"port": 3000,
"siteUrl": "http://127.0.0.1:8001/",
"siteUrl": "http://127.0.0.1:8000/",
"apiUrl": "web-apps/apps/api/documents/api.js",
"preloaderUrl": "web-apps/apps/api/documents/cache-scripts.html"
}

View File

@ -1,7 +1,7 @@
{
"server": {
"port": 80,
"siteUrl": "http://127.0.0.1:8001/",
"siteUrl": "http://127.0.0.1:8000/",
"apiUrl": "web-apps/apps/api/documents/api.js",
"preloaderUrl": "web-apps/apps/api/documents/cache-scripts.html"
}

View File

@ -0,0 +1,13 @@
#!/bin/sh
set -e
export NODE_CONFIG='{
"server": {
"siteUrl": "'${DS_URL:-"/"}'",
"token": {
"enable": '${JWT_ENABLED:-false}',
"secret": "'${JWT_SECRET:-secret}'",
"authorizationHeader": "'${JWT_HEADER:-Authorization}'"
}
}
}'
exec "$@"

View File

@ -110,9 +110,11 @@ docManager.createDemo = function (isSample, fileExt, userid, username) {
return fileName;
};
docManager.saveFileData = function (fileName, userid, username) {
const userAddress = docManager.curUserHostAddress();
const date_create = fileSystem.statSync(docManager.storagePath(fileName)).mtime;
docManager.saveFileData = function (fileName, userid, username, userAddress) {
if (!userAddress) {
userAddress = docManager.curUserHostAddress();
}
const date_create = fileSystem.statSync(docManager.storagePath(fileName, userAddress)).mtime;
const minutes = (date_create.getMinutes() < 10 ? '0' : '') + date_create.getMinutes().toString();
const month = (date_create.getMonth() < 10 ? '0' : '') + (parseInt(date_create.getMonth().toString()) + 1);
const sec = (date_create.getSeconds() < 10 ? '0' : '') + date_create.getSeconds().toString();

View File

@ -39,12 +39,7 @@ documentService.userIp = null;
documentService.getConvertedUriSync = function (documentUri, fromExtension, toExtension, documentRevisionId, callback) {
documentService.getConvertedUri(documentUri, fromExtension, toExtension, documentRevisionId, false, function (err, data) {
if (err) {
callback();
return;
}
var res = documentService.getResponseUri(data);
callback(res.value);
callback(err, data);
});
};

View File

@ -59,7 +59,7 @@ fileUtility.fileType = {
slide: "slide"
}
fileUtility.documentExts = [".doc", ".docx", ".docm", ".dot", ".dotx", ".dotm", ".odt", ".fodt", ".ott", ".rtf", ".txt", ".html", ".htm", ".mht", ".pdf", ".djvu", ".fb2", ".epub", ".xps"];
fileUtility.documentExts = [".doc", ".docx", ".docm", ".dot", ".dotx", ".dotm", ".odt", ".fodt", ".ott", ".rtf", ".txt", ".html", ".htm", ".mht", ".xml", ".pdf", ".djvu", ".fb2", ".epub", ".xps"];
fileUtility.spreadsheetExts = [".xls", ".xlsx", ".xlsm", ".xlt", ".xltx", ".xltm", ".ods", ".fods", ".ots", ".csv"];

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.2 KiB

View File

@ -20,7 +20,8 @@
"fillForms": <%- editor.fillForms %>,
"modifyFilter": <%- editor.modifyFilter %>,
"modifyContentControl": <%- editor.modifyContentControl %>,
"review": <%- editor.review %>
"review": <%- editor.review %>,
"reviewGroups": <%- editor.reviewGroups %>
}
},
"editorConfig": {
@ -29,6 +30,7 @@
"lang": "<%- editor.lang %>",
"callbackUrl": "<%- editor.callbackUrl %>",
"user": {
"group": "<%- editor.userGroup %>",
"id": "<%- editor.userid %>",
"name": "<%- editor.name %>"
},
@ -46,7 +48,8 @@
"forcesave": false,
"goback": {
"url": "<%- editor.backUrl %>"
}
},
"submitForm": <%- editor.submitForm %>
},
"fileChoiceUrl": "<%- editor.fileChoiceUrl %>",
"plugins": <%- editor.plugins %>

View File

@ -47,6 +47,7 @@
<option value="uid-1">John Smith</option>
<option value="uid-2">Mark Pottato</option>
<option value="uid-3">Hamish Mitchell</option>
<option value="uid-0">anonymous</option>
</select>
</td>
<td valign="middle" width="70%">Select user name before opening the document; you can open the same document using different users in different Web browser sessions, so you can check out multi-user editing functions.</td>

View File

@ -198,6 +198,23 @@ function getStoragePath($fileName, $userAddress = NULL) {
return $directory . basename($fileName);
}
function getForcesavePath($fileName, $userAddress, $create) {
$storagePath = trim(str_replace(array('/','\\'), DIRECTORY_SEPARATOR, $GLOBALS['STORAGE_PATH']), DIRECTORY_SEPARATOR);
$directory = __DIR__ . DIRECTORY_SEPARATOR . $storagePath . getCurUserHostAddress($userAddress) . DIRECTORY_SEPARATOR;
if (!is_dir($directory)) return "";
$directory = $directory . $fileName . "-hist" . DIRECTORY_SEPARATOR;
if (!$create && !is_dir($directory)) return "";
mkdir($directory);
$directory = $directory . $fileName;
if (!$create && !file_exists($directory)) return "";
return $directory;
}
function getHistoryDir($storagePath) {
$directory = $storagePath . "-hist";
if (!file_exists($directory) && !is_dir($directory)) {
@ -272,8 +289,8 @@ function getVirtualPath($forDocumentServer) {
return $virtPath;
}
function createMeta($fileName, $uid = "0") {
$histDir = getHistoryDir(getStoragePath($fileName));
function createMeta($fileName, $uid = "0", $userAddress = NULL) {
$histDir = getHistoryDir(getStoragePath($fileName, $userAddress));
if (empty($uid)) $uid = "0";
@ -288,6 +305,9 @@ function createMeta($fileName, $uid = "0") {
case 2:
$name = "Hamish Mitchell";
break;
case 3:
$name = null;
break;
}
$json = [
@ -338,14 +358,14 @@ function getFileExts() {
return array_merge($GLOBALS['DOC_SERV_VIEWD'], $GLOBALS['DOC_SERV_EDITED'], $GLOBALS['DOC_SERV_CONVERT']);
}
function GetCorrectName($fileName) {
function GetCorrectName($fileName, $userAddress = NULL) {
$path_parts = pathinfo($fileName);
$ext = $path_parts['extension'];
$name = $path_parts['basename'];
$baseNameWithoutExt = substr($name, 0, strlen($name) - strlen($ext) - 1);
for ($i = 1; file_exists(getStoragePath($name)); $i++)
for ($i = 1; file_exists(getStoragePath($name, $userAddress)); $i++)
{
$name = $baseNameWithoutExt . " (" . $i . ")." . $ext;
}

View File

@ -6,7 +6,7 @@ $GLOBALS['ALONE'] = FALSE;
$GLOBALS['DOC_SERV_VIEWD'] = array(".pdf", ".djvu", ".xps");
$GLOBALS['DOC_SERV_EDITED'] = array(".docx", ".xlsx", ".csv", ".pptx", ".txt");
$GLOBALS['DOC_SERV_CONVERT'] = array(".docm", ".doc", ".dotx", ".dotm", ".dot", ".odt", ".fodt", ".ott", ".xlsm", ".xls", ".xltx", ".xltm", ".xlt", ".ods", ".fods", ".ots", ".pptm", ".ppt", ".ppsx", ".ppsm", ".pps", ".potx", ".potm", ".pot", ".odp", ".fodp", ".otp", ".rtf", ".mht", ".html", ".htm", ".epub", ".fb2");
$GLOBALS['DOC_SERV_CONVERT'] = array(".docm", ".doc", ".dotx", ".dotm", ".dot", ".odt", ".fodt", ".ott", ".xlsm", ".xls", ".xltx", ".xltm", ".xlt", ".ods", ".fods", ".ots", ".pptm", ".ppt", ".ppsx", ".ppsm", ".pps", ".potx", ".potm", ".pot", ".odp", ".fodp", ".otp", ".rtf", ".mht", ".html", ".htm", ".xml", ".epub", ".fb2");
$GLOBALS['DOC_SERV_TIMEOUT'] = "120000";
@ -16,6 +16,7 @@ $GLOBALS['DOC_SERV_SITE_URL'] = "https://documentserver/";
$GLOBALS['DOC_SERV_CONVERTER_URL'] = "ConvertService.ashx";
$GLOBALS['DOC_SERV_API_URL'] = "web-apps/apps/api/documents/api.js";
$GLOBALS['DOC_SERV_PRELOADER_URL'] = "web-apps/apps/api/documents/cache-scripts.html";
$GLOBALS['DOC_SERV_COMMAND_URL'] = "coauthoring/CommandService.ashx";
$GLOBALS['DOC_SERV_JWT_SECRET'] = "";
$GLOBALS['DOC_SERV_JWT_HEADER'] = "Authorization";
@ -37,7 +38,7 @@ $GLOBALS['ExtsPresentation'] = array(".pps", ".ppsx", ".ppsm",
$GLOBALS['ExtsDocument'] = array(".doc", ".docx", ".docm",
".dot", ".dotx", ".dotm",
".odt", ".fodt", ".ott", ".rtf", ".txt",
".html", ".htm", ".mht",
".html", ".htm", ".mht", ".xml",
".pdf", ".djvu", ".fb2", ".epub", ".xps");

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.2 KiB

View File

@ -57,14 +57,22 @@
break;
case 1:
$uname = "Mark Pottato";
$ugroup = "group-2";
$reviewGroups = ["group-2", ""];
break;
case 2:
$uname = "Hamish Mitchell";
$ugroup = "group-3";
$reviewGroups = ["group-2"];
break;
case 3:
$uname = null;
break;
}
$editorsMode = empty($_GET["action"]) ? "edit" : $_GET["action"];
$canEdit = in_array(strtolower('.' . pathinfo($filename, PATHINFO_EXTENSION)), $GLOBALS['DOC_SERV_EDITED']);
$submitForm = $canEdit && ($editorsMode == "edit" || $editorsMode == "fillForms");
$mode = $canEdit && $editorsMode != "view" ? "edit" : "view";
$config = [
@ -87,7 +95,8 @@
"fillForms" => $editorsMode != "view" && $editorsMode != "comment" && $editorsMode != "embedded" && $editorsMode != "blockcontent",
"modifyFilter" => $editorsMode != "filter",
"modifyContentControl" => $editorsMode != "blockcontent",
"review" => $editorsMode == "edit" || $editorsMode == "review"
"review" => $editorsMode == "edit" || $editorsMode == "review",
"reviewGroups" => $reviewGroups
]
],
"editorConfig" => [
@ -97,7 +106,8 @@
"callbackUrl" => getCallbackUrl($filename),
"user" => [
"id" => $uid,
"name" => $uname
"name" => $uname,
"group" => $ugroup
],
"embedded" => [
"saveUrl" => $fileuriUser,
@ -108,6 +118,8 @@
"customization" => [
"about" => true,
"feedback" => true,
"forcesave" => false,
"submitForm" => $submitForm,
"goback" => [
"url" => serverPath(),
]
@ -122,7 +134,7 @@
$dataCompareFile = [
"fileType" => "docx",
"url" => serverPath(true) . "/webeditor-ajax.php?type=download&name=sample.docx"
"url" => serverPath(true) . "/webeditor-ajax.php?type=assets&name=sample.docx"
];
$dataMailMergeRecipients = [
@ -243,7 +255,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no, minimal-ui" />
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="mobile-web-app-capable" content="yes" />
<link rel="icon" href="./favicon.ico" type="image/x-icon" />
<link rel="icon" href="css/images/<?php echo getDocumentType($filename) ?>.ico" type="image/x-icon" />
<title>ONLYOFFICE</title>
<style>

View File

@ -168,7 +168,7 @@ function SendRequestToConvertService($document_uri, $from_extension, $to_extensi
$opts['ssl'] = array( 'verify_peer' => FALSE );
}
$context = stream_context_create($opts);
$context = stream_context_create($opts);
$response_data = file_get_contents($urlToConverter, FALSE, $context);
return $response_data;

View File

@ -77,6 +77,7 @@
<option value="0">John Smith</option>
<option value="1">Mark Pottato</option>
<option value="2">Hamish Mitchell</option>
<option value="3">anonymous</option>
</select>
</td>
<td valign="middle" width="70%">Select user name before opening the document; you can open the same document using different users in different Web browser sessions, so you can check out multi-user editing functions.</td>
@ -190,7 +191,7 @@
echo ' <a class="stored-edit '.$storeFile->documentType.'" href="doceditor.php?fileID='.urlencode($storeFile->name).'&user='.$user.'" target="_blank">';
echo ' <span title="'.$storeFile->name.'">'.$storeFile->name.'</span>';
echo ' </a>';
echo ' <a href="'.FileUri($storeFile->name).'">';
echo ' <a href="webeditor-ajax.php?type=download&name='.urlencode($storeFile->name).'">';
echo ' <img class="icon-download" src="css/images/download-24.png" alt="Download" title="Download" /></a>';
echo ' </a>';
echo ' <a class="delete-file" data="'.$storeFile->name.'">';

View File

@ -0,0 +1,234 @@
<?php
/**
*
* (c) Copyright Ascensio System SIA 2020
*
* 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.
*
*/
require_once( dirname(__FILE__) . '/jwtmanager.php' );
require_once( dirname(__FILE__) . '/common.php' );
require_once( dirname(__FILE__) . '/config.php' );
function readBody() {
$result["error"] = 0;
if (($body_stream = file_get_contents('php://input')) === FALSE) {
$result["error"] = "Bad Request";
return $result;
}
$data = json_decode($body_stream, TRUE); //json_decode - PHP 5 >= 5.2.0
if ($data === NULL) {
$result["error"] = "Bad Response";
return $result;
}
sendlog(" InputStream data: " . serialize($data), "webedior-ajax.log");
if (isJwtEnabled()) {
sendlog(" jwt enabled, checking tokens", "webedior-ajax.log");
$inHeader = false;
$token = "";
$jwtHeader = $GLOBALS['DOC_SERV_JWT_HEADER'] == "" ? "Authorization" : $GLOBALS['DOC_SERV_JWT_HEADER'];
if (!empty($data["token"])) {
$token = jwtDecode($data["token"]);
} elseif (!empty(apache_request_headers()[$jwtHeader])) {
$token = jwtDecode(substr(apache_request_headers()[$jwtHeader], strlen("Bearer ")));
$inHeader = true;
} else {
sendlog(" jwt token wasn't found in body or headers", "webedior-ajax.log");
$result["error"] = "Expected JWT";
return $result;
}
if (empty($token)) {
sendlog(" token was found but signature is invalid", "webedior-ajax.log");
$result["error"] = "Invalid JWT signature";
return $result;
}
$data = json_decode($token, true);
if ($inHeader) $data = $data["payload"];
}
return $data;
}
function processSave($data, $fileName, $userAddress) {
$downloadUri = $data["url"];
$curExt = strtolower('.' . pathinfo($fileName, PATHINFO_EXTENSION));
$downloadExt = strtolower('.' . pathinfo($downloadUri, PATHINFO_EXTENSION));
$newFileName = $fileName;
if ($downloadExt != $curExt) {
$key = GenerateRevisionId($downloadUri);
try {
sendlog(" Convert " . $downloadUri . " from " . $downloadExt . " to " . $curExt, "webedior-ajax.log");
$convertedUri;
$percent = GetConvertedUri($downloadUri, $downloadExt, $curExt, $key, FALSE, $convertedUri);
if (!empty($convertedUri)) {
$downloadUri = $convertedUri;
} else {
sendlog(" Convert after save convertedUri is empty", "webedior-ajax.log");
$baseNameWithoutExt = substr($fileName, 0, strlen($fileName) - strlen($curExt));
$newFileName = GetCorrectName($baseNameWithoutExt . $downloadExt, $userAddress);
}
} catch (Exception $e) {
sendlog(" Convert after save ".$e->getMessage(), "webedior-ajax.log");
$baseNameWithoutExt = substr($fileName, 0, strlen($fileName) - strlen($curExt));
$newFileName = GetCorrectName($baseNameWithoutExt . $downloadExt, $userAddress);
}
}
$saved = 1;
if (!(($new_data = file_get_contents($downloadUri)) === FALSE)) {
$storagePath = getStoragePath($newFileName, $userAddress);
$histDir = getHistoryDir($storagePath);
$verDir = getVersionDir($histDir, getFileVersion($histDir));
mkdir($verDir);
rename(getStoragePath($fileName, $userAddress), $verDir . DIRECTORY_SEPARATOR . "prev" . $curExt);
file_put_contents($storagePath, $new_data, LOCK_EX);
if ($changesData = file_get_contents($data["changesurl"])) {
file_put_contents($verDir . DIRECTORY_SEPARATOR . "diff.zip", $changesData, LOCK_EX);
}
$histData = $data["changeshistory"];
if (empty($histData)) {
$histData = json_encode($data["history"], JSON_PRETTY_PRINT);
}
if (!empty($histData)) {
file_put_contents($verDir . DIRECTORY_SEPARATOR . "changes.json", $histData, LOCK_EX);
}
file_put_contents($verDir . DIRECTORY_SEPARATOR . "key.txt", $data["key"], LOCK_EX);
$forcesavePath = getForcesavePath($newFileName, $userAddress, false);
if ($forcesavePath != "") {
unlink($forcesavePath);
}
$saved = 0;
}
$result["error"] = $saved;
return $result;
}
function processForceSave($data, $fileName, $userAddress) {
$downloadUri = $data["url"];
$curExt = strtolower('.' . pathinfo($fileName, PATHINFO_EXTENSION));
$downloadExt = strtolower('.' . pathinfo($downloadUri, PATHINFO_EXTENSION));
$newFileName = $fileName;
if ($downloadExt != $curExt) {
$key = GenerateRevisionId($downloadUri);
try {
sendlog(" Convert " . $downloadUri . " from " . $downloadExt . " to " . $curExt, "webedior-ajax.log");
$convertedUri;
$percent = GetConvertedUri($downloadUri, $downloadExt, $curExt, $key, FALSE, $convertedUri);
if (!empty($convertedUri)) {
$downloadUri = $convertedUri;
} else {
sendlog(" Convert after save convertedUri is empty", "webedior-ajax.log");
$baseNameWithoutExt = substr($fileName, 0, strlen($fileName) - strlen($curExt));
$newFileName = GetCorrectName($baseNameWithoutExt . $downloadExt, $userAddress);
}
} catch (Exception $e) {
sendlog(" Convert after save ".$e->getMessage(), "webedior-ajax.log");
$baseNameWithoutExt = substr($fileName, 0, strlen($fileName) - strlen($curExt));
$newFileName = GetCorrectName($baseNameWithoutExt . $downloadExt, $userAddress);
}
}
$saved = 1;
if (!(($new_data = file_get_contents($downloadUri)) === FALSE)) {
$isSubmitForm = $data["forcesavetype"] == 3;
if ($isSubmitForm) {
if ($newFileName == $fileName){
$newFileName = GetCorrectName($fileName, $userAddress);
}
$forcesavePath = getStoragePath($newFileName, $userAddress);
} else {
$forcesavePath = getForcesavePath($newFileName, $userAddress, false);
if ($forcesavePath == "") {
$forcesavePath = getForcesavePath($newFileName, $userAddress, true);
}
}
file_put_contents($forcesavePath, $new_data, LOCK_EX);
if ($isSubmitForm) {
$user = $data["actions"][0]["userid"];
createMeta($newFileName, $user, $userAddress);
}
$saved = 0;
}
$result["error"] = $saved;
return $result;
}
function commandRequest($method, $key){
$documentCommandUrl = $GLOBALS['DOC_SERV_SITE_URL'].$GLOBALS['DOC_SERV_COMMAND_URL'];
$arr = [
"c" => $method,
"key" => $key
];
$headerToken = "";
$jwtHeader = $GLOBALS['DOC_SERV_JWT_HEADER'] == "" ? "Authorization" : $GLOBALS['DOC_SERV_JWT_HEADER'];
if (isJwtEnabled()) {
$headerToken = jwtEncode([ "payload" => $arr ]);
$arr["token"] = jwtEncode($arr);
}
$data = json_encode($arr);
$opts = array('http' => array(
'method' => 'POST',
'header'=> "Content-type: application/json\r\n" .
(empty($headerToken) ? "" : $jwtHeader.": Bearer $headerToken\r\n"),
'content' => $data
));
if (substr($documentCommandUrl, 0, strlen("https")) === "https") {
$opts['ssl'] = array( 'verify_peer' => FALSE );
}
$context = stream_context_create($opts);
$response_data = file_get_contents($documentCommandUrl, FALSE, $context);
return $response_data;
}
?>

View File

@ -25,16 +25,18 @@ require_once( dirname(__FILE__) . '/ajax.php' );
require_once( dirname(__FILE__) . '/common.php' );
require_once( dirname(__FILE__) . '/functions.php' );
require_once( dirname(__FILE__) . '/jwtmanager.php' );
require_once( dirname(__FILE__) . '/trackmanager.php' );
$_trackerStatus = array(
0 => 'NotFound',
1 => 'Editing',
2 => 'MustSave',
3 => 'Corrupted',
4 => 'Closed'
4 => 'Closed',
6 => 'MustForceSave',
7 => 'CorruptedForceSave'
);
if (isset($_GET["type"]) && !empty($_GET["type"])) { //Checks if type value exists
$response_array;
@header( 'Content-Type: application/json; charset==utf-8');
@ -52,6 +54,10 @@ if (isset($_GET["type"]) && !empty($_GET["type"])) { //Checks if type value exis
$response_array = upload();
$response_array['status'] = isset($response_array['error']) ? 'error' : 'success';
die (json_encode($response_array));
case "download":
$response_array = download();
$response_array['status'] = 'success';
die (json_encode($response_array));
case "convert":
$response_array = convert();
$response_array['status'] = 'success';
@ -64,8 +70,8 @@ if (isset($_GET["type"]) && !empty($_GET["type"])) { //Checks if type value exis
$response_array = delete();
$response_array['status'] = 'success';
die (json_encode($response_array));
case "download":
$response_array = download();
case "assets":
$response_array = assets();
$response_array['status'] = 'success';
die (json_encode($response_array));
case "csv":
@ -130,116 +136,42 @@ function upload() {
function track() {
sendlog("Track START", "webedior-ajax.log");
sendlog("_GET params: " . serialize( $_GET ), "webedior-ajax.log");
sendlog(" _GET params: " . serialize( $_GET ), "webedior-ajax.log");
global $_trackerStatus;
$data;
$result["error"] = 0;
if (($body_stream = file_get_contents('php://input'))===FALSE) {
$result["error"] = "Bad Request";
return $result;
}
$data = json_decode($body_stream, TRUE); //json_decode - PHP 5 >= 5.2.0
if ($data === NULL) {
$result["error"] = "Bad Response";
return $result;
}
sendlog("InputStream data: " . serialize($data), "webedior-ajax.log");
if (isJwtEnabled()) {
sendlog("jwt enabled, checking tokens", "webedior-ajax.log");
$inHeader = false;
$token = "";
$jwtHeader = $GLOBALS['DOC_SERV_JWT_HEADER'] == "" ? "Authorization" : $GLOBALS['DOC_SERV_JWT_HEADER'];
if (!empty($data["token"])) {
$token = jwtDecode($data["token"]);
} elseif (!empty(apache_request_headers()[$jwtHeader])) {
$token = jwtDecode(substr(apache_request_headers()[$jwtHeader], strlen("Bearer ")));
$inHeader = true;
} else {
sendlog("jwt token wasn't found in body or headers", "webedior-ajax.log");
$result["error"] = "Expected JWT";
return $result;
}
if (empty($token)) {
sendlog("token was found but signature is invalid", "webedior-ajax.log");
$result["error"] = "Invalid JWT signature";
return $result;
}
$data = json_decode($token, true);
if ($inHeader) $data = $data["payload"];
$data = readBody();
if ($data["error"]){
return $data;
}
global $_trackerStatus;
$status = $_trackerStatus[$data["status"]];
$userAddress = $_GET["userAddress"];
$fileName = basename($_GET["fileName"]);
switch ($status) {
case "Editing":
if ($data["actions"] && $data["actions"][0]["type"] == 0) {
$user = $data["actions"][0]["userid"];
if (array_search($user, $data["users"]) === FALSE) {
$commandRequest = commandRequest("forcesave", $data["key"]);
sendlog(" CommandRequest forcesave: " . serialize($commandRequest), "webedior-ajax.log");
}
}
break;
case "MustSave":
case "Corrupted":
$userAddress = $_GET["userAddress"];
$fileName = basename($_GET["fileName"]);
$downloadUri = $data["url"];
$curExt = strtolower('.' . pathinfo($fileName, PATHINFO_EXTENSION));
$downloadExt = strtolower('.' . pathinfo($downloadUri, PATHINFO_EXTENSION));
if ($downloadExt != $curExt) {
$key = getDocEditorKey(downloadUri);
try {
sendlog("Convert " . $downloadUri . " from " . $downloadExt . " to " . $curExt, "webedior-ajax.log");
$convertedUri;
$percent = GetConvertedUri($downloadUri, $downloadExt, $curExt, $key, FALSE, $convertedUri);
$downloadUri = $convertedUri;
} catch (Exception $e) {
sendlog("Convert after save ".$e->getMessage(), "webedior-ajax.log");
$result["error"] = "error: " . $e->getMessage();
return $result;
}
}
$saved = 1;
if (($new_data = file_get_contents($downloadUri)) === FALSE) {
$saved = 0;
} else {
$storagePath = getStoragePath($fileName, $userAddress);
$histDir = getHistoryDir($storagePath);
$verDir = getVersionDir($histDir, getFileVersion($histDir));
mkdir($verDir);
copy($storagePath, $verDir . DIRECTORY_SEPARATOR . "prev" . $downloadExt);
file_put_contents($storagePath, $new_data, LOCK_EX);
if ($changesData = file_get_contents($data["changesurl"])) {
file_put_contents($verDir . DIRECTORY_SEPARATOR . "diff.zip", $changesData, LOCK_EX);
}
$histData = $data["changeshistory"];
if (empty($histData)) {
$histData = json_encode($data["history"], JSON_PRETTY_PRINT);
}
if (!empty($histData)) {
file_put_contents($verDir . DIRECTORY_SEPARATOR . "changes.json", $histData, LOCK_EX);
}
file_put_contents($verDir . DIRECTORY_SEPARATOR . "key.txt", $data["key"], LOCK_EX);
}
$result["c"] = "saved";
$result["status"] = $saved;
$result = processSave($data, $fileName, $userAddress);
break;
case "MustForceSave":
case "CorruptedForceSave":
$result = processForceSave($data, $fileName, $userAddress);
break;
}
sendlog("track result: " . serialize($result), "webedior-ajax.log");
sendlog("Track RESULT: " . serialize($result), "webedior-ajax.log");
return $result;
}
@ -331,28 +263,44 @@ function files() {
}
}
function download() {
$fileName = "sample" . DIRECTORY_SEPARATOR . basename($_GET["name"]);
downloadFile($fileName);
function assets() {
$fileName = basename($_GET["name"]);
$filePath = dirname(__FILE__) . DIRECTORY_SEPARATOR . "assets" . DIRECTORY_SEPARATOR . "sample" . DIRECTORY_SEPARATOR . $fileName;
downloadFile($filePath);
}
function csv() {
$fileName = "sample" . DIRECTORY_SEPARATOR . "csv.csv";
downloadFile($fileName);
$fileName = "csv.csv";
$filePath = dirname(__FILE__) . DIRECTORY_SEPARATOR . "assets" . DIRECTORY_SEPARATOR . "sample" . DIRECTORY_SEPARATOR . $fileName;
downloadFile($filePath);
}
function downloadFile($fileName) {
$file = dirname(__FILE__) . DIRECTORY_SEPARATOR . "assets" . DIRECTORY_SEPARATOR . $fileName;
if (file_exists($file)) {
function download() {
try {
$fileName = basename($_GET["name"]);
$filePath = getForcesavePath($fileName, null, false);
if ($filePath == "") {
$filePath = getStoragePath($fileName, null);
}
downloadFile($filePath);
} catch (Exception $e) {
sendlog("Download ".$e->getMessage(), "webedior-ajax.log");
$result["error"] = "error: File not found";
return $result;
}
}
function downloadFile($filePath) {
if (file_exists($filePath)) {
if (ob_get_level()) {
ob_end_clean();
}
@header('Content-Length: ' . filesize($file));
@header('Content-Disposition: attachment; filename*=UTF-8\'\'' . urldecode(basename($file)));
@header('Content-Type: ' . mime_content_type($file));
@header('Content-Length: ' . filesize($filePath));
@header('Content-Disposition: attachment; filename*=UTF-8\'\'' . urldecode(basename($filePath)));
@header('Content-Type: ' . mime_content_type($filePath));
if ($fd = fopen($file, 'rb')) {
if ($fd = fopen($filePath, 'rb')) {
while (!feof($fd)) {
print fread($fd, 1024);
}

View File

@ -10,7 +10,7 @@ DOC_SERV_CONVERT = [
".fodt", ".ott", ".xlsm", ".xls", ".xltx", ".xltm",
".xlt", ".ods", ".fods", ".ots", ".pptm", ".ppt",
".ppsx", ".ppsm", ".pps", ".potx", ".potm", ".pot",
".odp", ".fodp", ".otp", ".rtf", ".mht", ".html", ".htm", ".epub", ".fb2"
".odp", ".fodp", ".otp", ".rtf", ".mht", ".html", ".htm", ".xml", ".epub", ".fb2"
]
DOC_SERV_TIMEOUT = 120000
@ -20,6 +20,7 @@ DOC_SERV_SITE_URL = 'https://documentserver/'
DOC_SERV_CONVERTER_URL = 'ConvertService.ashx'
DOC_SERV_API_URL = 'web-apps/apps/api/documents/api.js'
DOC_SERV_PRELOADER_URL = 'web-apps/apps/api/documents/cache-scripts.html'
DOC_SERV_COMMAND_URL='coauthoring/CommandService.ashx'
EXAMPLE_DOMAIN = None
@ -43,7 +44,7 @@ EXT_DOCUMENT = [
".doc", ".docx", ".docm",
".dot", ".dotx", ".dotm",
".odt", ".fodt", ".ott", ".rtf", ".txt",
".html", ".htm", ".mht",
".html", ".htm", ".mht", ".xml",
".pdf", ".djvu", ".fb2", ".epub", ".xps"
]

View File

@ -6,7 +6,7 @@ You should also install following dependencies:
```
pip install Django==3.1.6
pip install requests==2.25.1
pip install pyjwt==2.0.1
pip install pyjwt==1.7.1
```
## Configuration

View File

@ -32,6 +32,7 @@ from django.contrib.staticfiles.urls import staticfiles_urlpatterns
urlpatterns = [
path('', index.default),
path('upload', actions.upload),
path('download', actions.download),
path('convert', actions.convert),
path('create', actions.createNew),
path('edit', actions.edit),

View File

@ -32,7 +32,10 @@ import io
import re
import requests
import time
import urllib.parse
import magic
from django.http import HttpResponse, HttpResponseRedirect, FileResponse
from src import settings
from . import fileUtils, historyManager
@ -137,6 +140,29 @@ def getStoragePath(filename, req):
return os.path.join(directory, fileUtils.getFileName(filename))
def getForcesavePath(filename, req, create):
if isinstance(req, str):
curAdr = req
else:
curAdr = req.META['REMOTE_ADDR']
directory = os.path.join(config.STORAGE_PATH, curAdr)
if not os.path.exists(directory):
return ""
directory = os.path.join(directory, f'{filename}-hist')
if (not os.path.exists(directory)):
if create:
os.makedirs(directory)
else:
return ""
directory = os.path.join(directory, filename)
if (not os.path.exists(directory) and not create):
return ""
return directory
def getStoredFiles(req):
directory = getRootFolder(req)
@ -152,21 +178,26 @@ def getStoredFiles(req):
return fileInfos
def createFile(stream, path, req = None, meta = False):
bufSize = 8196
bufSize = 8192
with io.open(path, 'wb') as out:
read = stream.read(bufSize)
while len(read) > 0:
out.write(read)
read = stream.read(bufSize)
if meta:
historyManager.createMeta(path, req)
return
def createFileResponse(response, path, req, meta):
response.raise_for_status()
with open(path, 'wb') as file:
for chunk in response.iter_content(chunk_size=8192):
file.write(chunk)
return
def saveFileFromUri(uri, path, req = None, meta = False):
resp = requests.get(uri, stream=True)
createFile(resp.raw, path, req, meta)
createFileResponse(resp, path, req, meta)
return
def createSample(fileType, sample, req):
@ -201,6 +232,13 @@ def generateFileKey(filename, req):
replaced = re.sub(r'[^0-9-.a-zA-Z_=]', '_', h)
return replaced[:20]
def generateRevisionId(expectedKey):
if (len(expectedKey) > 20):
expectedKey = str(hash(expectedKey))
key = re.sub(r'[^0-9-.a-zA-Z_=]', '_', expectedKey)
return key[:20]
def getFilesInfo(req):
fileId = req.GET.get('fileId') if req.GET.get('fileId') else None
@ -224,4 +262,11 @@ def getFilesInfo(req):
if len(resultID) > 0 : return resultID
else : return "File not found"
else :
return result
return result
def download(filePath):
response = FileResponse(open(filePath, 'rb'), True)
response['Content-Length'] = os.path.getsize(filePath)
response['Content-Disposition'] = "attachment;filename*=UTF-8\'\'" + urllib.parse.unquote(os.path.basename(filePath))
response['Content-Type'] = magic.from_file(filePath, mime=True)
return response

View File

@ -95,6 +95,23 @@ def createMeta(storagePath, req):
return
def createMetaData(filename, uid, uname, usAddr):
histDir = getHistoryDir(docManager.getStoragePath(filename, usAddr))
path = getMetaPath(histDir)
if not os.path.exists(histDir):
os.makedirs(histDir)
obj = {
'created': datetime.today().strftime('%Y-%m-%d %H:%M:%S'),
'uid': uid,
'uname': uname
}
writeFile(path, json.dumps(obj))
return
def writeFile(path, content):
with io.open(path, 'w') as out:
out.write(content)

View File

@ -0,0 +1,153 @@
"""
(c) Copyright Ascensio System SIA 2020
*
The MIT License (MIT)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
"""
import config
import requests
import os
import json
from . import jwtManager, docManager, historyManager, fileUtils, serviceConverter
def readBody(request):
body = json.loads(request.body)
if (jwtManager.isEnabled()):
token = body.get('token')
if (not token):
jwtHeader = 'Authorization' if config.DOC_SERV_JWT_HEADER is None or config.DOC_SERV_JWT_HEADER == '' else config.DOC_SERV_JWT_HEADER
token = request.headers.get(jwtHeader)
if token:
token = token[len('Bearer '):]
if (not token):
raise Exception('Expected JWT')
body = jwtManager.decode(token)
if (body.get('payload')):
body = body['payload']
return body
def processSave(body, filename, usAddr):
download = body.get('url')
changesUri = body.get('changesurl')
newFilename = filename
curExt = fileUtils.getFileExt(filename)
downloadExt = fileUtils.getFileExt(download)
if (curExt != downloadExt):
try:
newUri = serviceConverter.getConverterUri(download, downloadExt, curExt, docManager.generateRevisionId(download), False)
if not newUri:
newFilename = docManager.getCorrectName(fileUtils.getFileNameWithoutExt(filename) + downloadExt, usAddr)
else:
download = newUri
except Exception:
newFilename = docManager.getCorrectName(fileUtils.getFileNameWithoutExt(filename) + downloadExt, usAddr)
path = docManager.getStoragePath(newFilename, usAddr)
histDir = historyManager.getHistoryDir(path)
if not os.path.exists(histDir):
os.makedirs(histDir)
versionDir = historyManager.getNextVersionDir(histDir)
os.rename(docManager.getStoragePath(filename, usAddr), historyManager.getPrevFilePath(versionDir, curExt))
docManager.saveFileFromUri(download, path)
docManager.saveFileFromUri(changesUri, historyManager.getChangesZipPath(versionDir))
hist = None
hist = body.get('changeshistory')
if (not hist) & ('history' in body):
hist = json.dumps(body.get('history'))
if hist:
historyManager.writeFile(historyManager.getChangesHistoryPath(versionDir), hist)
historyManager.writeFile(historyManager.getKeyPath(versionDir), body.get('key'))
forcesavePath = docManager.getForcesavePath(newFilename, usAddr, False)
if (forcesavePath != ""):
os.remove(forcesavePath)
return
def processForceSave(body, filename, usAddr):
download = body.get('url')
curExt = fileUtils.getFileExt(filename)
downloadExt = fileUtils.getFileExt(download)
newFilename = filename
if (curExt != downloadExt):
try:
newUri = serviceConverter.getConverterUri(download, downloadExt, curExt, docManager.generateRevisionId(download), False)
if not newUri:
newFilename = docManager.getCorrectName(fileUtils.getFileNameWithoutExt(filename) + downloadExt, usAddr)
else:
download = newUri
except Exception:
newFilename = docManager.getCorrectName(fileUtils.getFileNameWithoutExt(filename) + downloadExt, usAddr)
isSubmitForm = body.get('forcesavetype') == 3
if(isSubmitForm):
if (newFilename == filename):
newFilename = docManager.getCorrectName(filename, usAddr)
forcesavePath = docManager.getStoragePath(newFilename, usAddr)
else:
forcesavePath = docManager.getForcesavePath(newFilename, usAddr, False)
if (forcesavePath == ""):
forcesavePath = docManager.getForcesavePath(newFilename, usAddr, True)
docManager.saveFileFromUri(download, forcesavePath)
if(isSubmitForm):
uid = body['actions'][0]['userid']
historyManager.createMetaData(newFilename, uid, "Filling Form", usAddr)
return
def commandRequest(method, key):
documentCommandUrl = config.DOC_SERV_SITE_URL + config.DOC_SERV_COMMAND_URL
payload = {
'c': method,
'key': key
}
headers={'accept': 'application/json'}
if jwtManager.isEnabled():
jwtHeader = 'Authorization' if config.DOC_SERV_JWT_HEADER is None or config.DOC_SERV_JWT_HEADER == '' else config.DOC_SERV_JWT_HEADER
headerToken = jwtManager.encode({'payload': payload})
headers[jwtHeader] = f'Bearer {headerToken}'
payload['token'] = jwtManager.encode(payload)
response = requests.post(documentCommandUrl, json=payload, headers=headers)
return

View File

@ -38,6 +38,10 @@ USERS = [
{
'uid': 'uid-3',
'uname': 'Hamish Mitchell'
},
{
'uid': 'uid-0',
'uname': 'anonymous'
}
]

View File

@ -33,7 +33,7 @@ import magic
from datetime import datetime
from django.http import HttpResponse, HttpResponseRedirect, FileResponse
from django.shortcuts import render
from src.utils import docManager, fileUtils, serviceConverter, users, jwtManager, historyManager
from src.utils import docManager, fileUtils, serviceConverter, users, jwtManager, historyManager, trackManager
def upload(request):
@ -119,9 +119,18 @@ def edit(request):
docKey = docManager.generateFileKey(filename, request)
fileType = fileUtils.getFileType(filename)
user = users.getUserFromReq(request)
userGroup = None
reviewGroups = None
if (user['uid'] == 'uid-2'):
userGroup = 'group-2'
reviewGroups = ['group-2', '']
if (user['uid'] == 'uid-3'):
userGroup = 'group-3'
reviewGroups = ['group-2']
edMode = request.GET.get('mode') if request.GET.get('mode') else 'edit'
canEdit = docManager.isCanEdit(ext)
submitForm = canEdit & ((edMode == 'edit') | (edMode == 'fillForms'))
mode = 'edit' if canEdit & (edMode != 'view') else 'view'
edType = request.GET.get('type') if request.GET.get('type') else 'desktop'
@ -161,7 +170,8 @@ def edit(request):
'fillForms': (edMode != 'view') & (edMode != 'comment') & (edMode != 'embedded') & (edMode != "blockcontent"),
'modifyFilter': edMode != 'filter',
'modifyContentControl': edMode != "blockcontent",
'review': (edMode == 'edit') | (edMode == 'review')
'review': (edMode == 'edit') | (edMode == 'review'),
'reviewGroups': reviewGroups
}
},
'editorConfig': {
@ -171,7 +181,8 @@ def edit(request):
'callbackUrl': docManager.getCallbackUrl(filename, request),
'user': {
'id': user['uid'],
'name': user['uname']
'name': None if user['uid'] == 'uid-0' else user['uname'],
'group': userGroup
},
'embedded': {
'saveUrl': fileUriUser,
@ -182,6 +193,8 @@ def edit(request):
'customization': {
'about': True,
'feedback': True,
'forcesave': False,
'submitForm': submitForm,
'goback': {
'url': docManager.getServerUrl(False, request)
}
@ -225,51 +238,25 @@ def edit(request):
return render(request, 'editor.html', context)
def track(request):
filename = fileUtils.getFileName(request.GET['filename'])
usAddr = request.GET['userAddress']
response = {}
try:
body = json.loads(request.body)
if jwtManager.isEnabled():
token = body.get('token')
if (not token):
jwtHeader = 'Authorization' if config.DOC_SERV_JWT_HEADER is None or config.DOC_SERV_JWT_HEADER == '' else config.DOC_SERV_JWT_HEADER
token = request.headers.get(jwtHeader)
if token:
token = token[len('Bearer '):]
if (not token):
raise Exception('Expected JWT')
body = jwtManager.decode(token)
if (body.get('payload')):
body = body['payload']
body = trackManager.readBody(request)
status = body['status']
download = body.get('url')
if (status == 1): # Editing
if (body['actions'] and body['actions'][0]['type'] == 0):# finished edit
user = body['actions'][0]['userid']
if (not user in body['users']):
trackManager.commandRequest('forcesave', body['key'])
filename = fileUtils.getFileName(request.GET['filename'])
usAddr = request.GET['userAddress']
if (status == 2) | (status == 3): # mustsave, corrupted
path = docManager.getStoragePath(filename, usAddr)
histDir = historyManager.getHistoryDir(path)
versionDir = historyManager.getNextVersionDir(histDir)
changesUri = body.get('changesurl')
os.rename(path, historyManager.getPrevFilePath(versionDir, fileUtils.getFileExt(filename)))
docManager.saveFileFromUri(download, path)
docManager.saveFileFromUri(changesUri, historyManager.getChangesZipPath(versionDir))
hist = None
hist = body.get('changeshistory')
if (not hist) & ('history' in body):
hist = json.dumps(body.get('history'))
if hist:
historyManager.writeFile(historyManager.getChangesHistoryPath(versionDir), hist)
historyManager.writeFile(historyManager.getKeyPath(versionDir), body.get('key'))
trackManager.processSave(body, filename, usAddr)
if (status == 6) | (status == 7): # mustforcesave, corruptedforcesave
trackManager.processForceSave(body, filename, usAddr)
except Exception as e:
response.setdefault('error', 1)
@ -298,8 +285,18 @@ def files(request):
def csv(request):
filePath = os.path.join('assets', 'sample', "csv.csv")
response = FileResponse(open(filePath, 'rb'), True)
response['Content-Length'] = os.path.getsize(filePath)
response['Content-Disposition'] = "attachment;filename*=UTF-8\'\'" + urllib.parse.unquote(os.path.basename(filePath))
response['Content-Type'] = magic.from_file(filePath, mime=True)
return response
response = docManager.download(filePath)
return response
def download(request):
try:
fileName = fileUtils.getFileName(request.GET['filename'])
filePath = docManager.getForcesavePath(fileName, request, False)
if (filePath == ""):
filePath = docManager.getStoragePath(fileName, request)
response = docManager.download(filePath)
return response
except Exception:
response = {}
response.setdefault('error', 'File not found')
return HttpResponse(json.dumps(response), content_type='application/json')

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.2 KiB

View File

@ -137,7 +137,7 @@
<a class="stored-edit {{ file.type }}" href="edit?filename={{ file.title }}" target="_blank">
<span title="{{ file.title }}">{{ file.title }}</span>
</a>
<a href="{{ file.url }}">
<a href="download?filename={{ file.title }}">
<img class="icon-download" src="{% static "images/download-24.png" %}" alt="Download" title="Download" />
</a>
<a class="delete-file" data-filename="{{ file.title }}">

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.2 KiB

View File

@ -57,13 +57,13 @@ class HomeController < ApplicationController
raise 'File type is not supported'
end
file_name = DocumentHelper.get_correct_name(file_name)
file_name = DocumentHelper.get_correct_name(file_name, nil)
File.open(DocumentHelper.storage_path(file_name, nil), 'wb') do |file|
file.write(http_posted_file.read)
end
DocumentHelper.create_meta(file_name, cookies[:uid], cookies[:uname])
DocumentHelper.create_meta(file_name, cookies[:uid], cookies[:uname], nil)
render plain: '{ "filename": "' + file_name + '"}'
rescue => ex
@ -89,7 +89,7 @@ class HomeController < ApplicationController
return
end
correct_name = DocumentHelper.get_correct_name(File.basename(file_name, extension) + internal_extension)
correct_name = DocumentHelper.get_correct_name(File.basename(file_name, extension) + internal_extension, nil)
uri = URI.parse(new_file_uri)
http = Net::HTTP.new(uri.host, uri.port)
@ -113,7 +113,7 @@ class HomeController < ApplicationController
file_name = correct_name
DocumentHelper.create_meta(file_name, cookies[:uid], cookies[:uname])
DocumentHelper.create_meta(file_name, cookies[:uid], cookies[:uname], nil)
end
render plain: '{ "filename" : "' + file_name + '"}'
@ -124,110 +124,40 @@ class HomeController < ApplicationController
end
def track
user_address = params[:userAddress]
file_name = File.basename(params[:fileName])
storage_path = DocumentHelper.storage_path(file_name, user_address)
body = request.body.read
if body == nil || body.empty?
file_data = TrackHelper.read_body(request)
if file_data == nil || file_data.empty?
render plain: '{"error":1}'
return
end
file_data = JSON.parse(body)
if JwtHelper.is_enabled
inHeader = false
token = nil
jwtHeader = Rails.configuration.header.empty? ? "Authorization" : Rails.configuration.header;
if file_data["token"]
token = JwtHelper.decode(file_data["token"])
elsif request.headers[jwtHeader]
hdr = request.headers[jwtHeader]
hdr.slice!(0, "Bearer ".length)
token = JwtHelper.decode(hdr)
inHeader = true
else
raise "Expected JWT"
end
if !token
raise "Invalid JWT signature"
end
file_data = JSON.parse(token)
if inHeader
file_data = file_data["payload"]
end
end
status = file_data['status'].to_i
if status == 2 || status == 3 #MustSave, Corrupted
user_address = params[:userAddress]
file_name = File.basename(params[:fileName])
saved = 0
begin
def save_from_uri(path, uristr)
uri = URI.parse(uristr)
http = Net::HTTP.new(uri.host, uri.port)
if uristr.start_with?('https')
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
end
req = Net::HTTP::Get.new(uri)
res = http.request(req)
data = res.body
if data == nil
raise 'stream is null'
end
File.open(path, 'wb') do |file|
file.write(data)
end
end
hist_dir = DocumentHelper.history_dir(storage_path)
ver_dir = DocumentHelper.version_dir(hist_dir, DocumentHelper.get_file_version(hist_dir))
FileUtils.mkdir_p(ver_dir)
FileUtils.move(storage_path, File.join(ver_dir, "prev#{File.extname(file_name)}"))
save_from_uri(storage_path, file_data['url'])
if (file_data["changesurl"])
save_from_uri(File.join(ver_dir, "diff.zip"), file_data["changesurl"])
end
hist_data = file_data["changeshistory"]
if (!hist_data)
hist_data = file_data["history"].to_json
end
if (hist_data)
File.open(File.join(ver_dir, "changes.json"), 'wb') do |file|
file.write(hist_data)
end
end
File.open(File.join(ver_dir, "key.txt"), 'wb') do |file|
file.write(file_data["key"])
end
rescue StandardError => msg
saved = 1
if status == 1 #Editing
if file_data['actions'][0]['type'] == 0 #Finished edit
user = file_data['actions'][0]['userid']
if !file_data['users'].index(user)
json_data = TrackHelper.command_request("forcesave", file_data['key'])
end
end
end
if status == 2 || status == 3 #MustSave, Corrupted
saved = TrackHelper.process_save(file_data, file_name, user_address)
render plain: '{"error":' + saved.to_s + '}'
return
end
if status == 6 || status == 7 # MustForceave, CorruptedForcesave
saved = TrackHelper.process_force_save(file_data, file_name, user_address)
render plain: '{"error":' + saved.to_s + '}'
return
end
render plain: '{"error":0}'
return
end
def remove
@ -269,4 +199,22 @@ class HomeController < ApplicationController
send_file csvPath, :x_sendfile => true
end
def download
begin
file_name = File.basename(params[:filename])
file_path = DocumentHelper.forcesave_path(file_name, nil, false)
if file_path.eql?("")
file_path = DocumentHelper.storage_path(file_name, nil)
end
response.headers['Content-Length'] = File.size(file_path).to_s
response.headers['Content-Type'] = MimeMagic.by_path(file_path).type
response.headers['Content-Disposition'] = "attachment;filename*=UTF-8\'\'" + URI.escape(file_name, Regexp.new("[^#{URI::PATTERN::UNRESERVED}]"))
send_file file_path, :x_sendfile => true
rescue => ex
render plain: '{ "error": "File not found"}'
end
end
end

View File

@ -77,6 +77,32 @@ class DocumentHelper
directory.join(File.basename(file_name)).to_s
end
def forcesave_path(file_name, user_address, create)
directory = Rails.root.join('public', Rails.configuration.storagePath, cur_user_host_address(user_address))
unless File.directory?(directory)
return ""
end
directory = directory.join("#{File.basename(file_name)}-hist")
unless File.directory?(directory)
if create
FileUtils.mkdir_p(directory)
else
return ""
end
end
directory = directory.join(File.basename(file_name))
unless File.file?(directory)
if !create
return ""
end
end
return directory.to_s
end
def history_dir(storage_path)
directory = "#{storage_path}-hist"
@ -108,13 +134,13 @@ class DocumentHelper
return ver
end
def get_correct_name(file_name)
def get_correct_name(file_name, user_address)
ext = File.extname(file_name)
base_name = File.basename(file_name, ext)
name = base_name + ext
index = 1
while File.exist?(storage_path(name, nil))
while File.exist?(storage_path(name, user_address))
name = base_name + ' (' + index.to_s + ')' + ext
index = index + 1
end
@ -140,8 +166,8 @@ class DocumentHelper
return arr
end
def create_meta(file_name, uid, uname)
hist_dir = history_dir(storage_path(file_name, nil))
def create_meta(file_name, uid, uname, user_address)
hist_dir = history_dir(storage_path(file_name, user_address))
json = {
:created => Time.now.to_formatted_s(:db),
@ -156,14 +182,14 @@ class DocumentHelper
def create_demo(file_ext, sample, uid, uname)
demo_name = (sample == 'true' ? 'sample.' : 'new.') + file_ext
file_name = get_correct_name demo_name
file_name = get_correct_name(demo_name, nil)
src = Rails.root.join('public', 'assets', sample == 'true' ? 'sample' : 'new', demo_name)
dest = storage_path file_name, nil
FileUtils.cp src, dest
create_meta(file_name, uid, uname)
create_meta(file_name, uid, uname, nil)
file_name
end

View File

@ -66,7 +66,20 @@ class FileModel
def get_config
editorsmode = @mode ? @mode : "edit"
canEdit = DocumentHelper.edited_exts.include?(file_ext)
submitForm = canEdit && (editorsmode.eql?("edit") || editorsmode.eql?("fillForms"))
mode = canEdit && editorsmode.eql?("view") ? "view" : "edit"
userId = @user_id ? @user_id : "uid-1"
user_name = (userId.eql?("uid-0") ? nil : (@user_name ? @user_name : "John Smith"))
userGroup = nil
reviewGroups = nil
if (userId == "uid-2")
userGroup = "group-2"
reviewGroups = ["group-2", ""]
end
if (userId == "uid-3")
userGroup = "group-3"
reviewGroups = ["group-2"]
end
config = {
:type => type(),
@ -88,7 +101,8 @@ class FileModel
:fillForms => !editorsmode.eql?("view") && !editorsmode.eql?("comment") && !editorsmode.eql?("embedded") && !editorsmode.eql?("blockcontent"),
:modifyFilter => !editorsmode.eql?("filter"),
:modifyContentControl => !editorsmode.eql?("blockcontent"),
:review => editorsmode.eql?("edit") || editorsmode.eql?("review")
:review => editorsmode.eql?("edit") || editorsmode.eql?("review"),
:reviewGroups => reviewGroups
}
},
:editorConfig => {
@ -97,8 +111,9 @@ class FileModel
:lang => @lang ? @lang : "en",
:callbackUrl => callback_url,
:user => {
:id => @user_id ? @user_id : "uid-0",
:name => @user_name ? @user_name : "John Smith"
:id => userId,
:name => user_name,
:group => userGroup
},
:embedded => {
:saveUrl => file_uri_user,
@ -106,6 +121,10 @@ class FileModel
:shareUrl => file_uri_user,
:toolbarDocked => "top"
},
:customization => {
:forcesave => false,
:submitForm => submitForm
}
}
}
@ -144,14 +163,16 @@ class FileModel
obj["version"] = i
if (i == 1)
File.open(File.join(hist_dir, "createdInfo.json"), 'r') do |file|
cr_info = JSON.parse(file.read())
if File.file?(File.join(hist_dir, "createdInfo.json"))
File.open(File.join(hist_dir, "createdInfo.json"), 'r') do |file|
cr_info = JSON.parse(file.read())
obj["created"] = cr_info["created"]
obj["user"] = {
:id => cr_info["created"],
:name => cr_info["name"]
}
obj["created"] = cr_info["created"]
obj["user"] = {
:id => cr_info["created"],
:name => cr_info["name"]
}
end
end
end

View File

@ -16,7 +16,7 @@
class FileUtility
@@exts_document = %w(.doc .docx .docm .dot .dotx .dotm .odt .fodt .ott .rtf .txt .html .htm .mht .pdf .djvu .fb2 .epub .xps)
@@exts_document = %w(.doc .docx .docm .dot .dotx .dotm .odt .fodt .ott .rtf .txt .html .htm .mht .xml .pdf .djvu .fb2 .epub .xps)
@@exts_spreadsheet = %w(.xls .xlsx .xlsm .xlt .xltx .xltm .ods .fods .ots .csv)

View File

@ -0,0 +1,238 @@
#
# (c) Copyright Ascensio System SIA 2020
#
# 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.
#
require 'net/http'
class TrackHelper
class << self
def read_body(request)
body = request.body.read
if body == nil || body.empty?
return ""
end
file_data = JSON.parse(body)
if JwtHelper.is_enabled
inHeader = false
token = nil
jwtHeader = Rails.configuration.header.empty? ? "Authorization" : Rails.configuration.header;
if file_data["token"]
token = JwtHelper.decode(file_data["token"])
elsif request.headers[jwtHeader]
hdr = request.headers[jwtHeader]
hdr.slice!(0, "Bearer ".length)
token = JwtHelper.decode(hdr)
inHeader = true
else
raise "Expected JWT"
end
if !token
raise "Invalid JWT signature"
end
file_data = JSON.parse(token)
if inHeader
file_data = file_data["payload"]
end
end
return file_data
end
def process_save(file_data, file_name, user_address)
download_uri = file_data['url']
new_file_name = file_name
cur_ext = File.extname(file_name)
download_ext = File.extname(download_uri)
if (!cur_ext.eql?(download_ext))
key = ServiceConverter.generate_revision_id(download_uri)
begin
percent, new_file_uri = ServiceConverter.get_converted_uri(download_uri, download_ext.delete('.'), cur_ext.delete('.'), key, false)
if (new_file_uri == nil || new_file_uri.empty?)
new_file_name = DocumentHelper.get_correct_name(File.basename(file_name, cur_ext) + download_ext, user_address)
else
download_uri = new_file_uri
end
rescue StandardError => msg
new_file_name = DocumentHelper.get_correct_name(File.basename(file_name, cur_ext) + download_ext, user_address)
end
end
saved = 1
begin
storage_path = DocumentHelper.storage_path(new_file_name, user_address)
hist_dir = DocumentHelper.history_dir(storage_path)
ver_dir = DocumentHelper.version_dir(hist_dir, DocumentHelper.get_file_version(hist_dir))
FileUtils.mkdir_p(ver_dir)
FileUtils.move(DocumentHelper.storage_path(file_name, user_address), File.join(ver_dir, "prev#{cur_ext}"))
save_from_uri(storage_path, download_uri)
if (file_data["changesurl"])
save_from_uri(File.join(ver_dir, "diff.zip"), file_data["changesurl"])
end
hist_data = file_data["changeshistory"]
if (!hist_data)
hist_data = file_data["history"].to_json
end
if (hist_data)
File.open(File.join(ver_dir, "changes.json"), 'wb') do |file|
file.write(hist_data)
end
end
File.open(File.join(ver_dir, "key.txt"), 'wb') do |file|
file.write(file_data["key"])
end
forcesave_path = DocumentHelper.forcesave_path(new_file_name, user_address, false)
if (!forcesave_path.eql?(""))
File.delete(forcesave_path)
end
saved = 0
rescue StandardError => msg
saved = 1
end
return saved
end
def process_force_save(file_data, file_name, user_address)
download_uri = file_data['url']
cur_ext = File.extname(file_name)
download_ext = File.extname(download_uri)
new_file_name = file_name
if (!cur_ext.eql?(download_ext))
key = ServiceConverter.generate_revision_id(download_uri)
begin
percent, new_file_uri = ServiceConverter.get_converted_uri(download_uri, download_ext.delete('.'), cur_ext.delete('.'), key, false)
if (new_file_uri == nil || new_file_uri.empty?)
new_file_name = DocumentHelper.get_correct_name(File.basename(file_name, cur_ext) + download_ext, user_address)
else
download_uri = new_file_uri
end
rescue StandardError => msg
new_file_name = DocumentHelper.get_correct_name(File.basename(file_name, cur_ext) + download_ext, user_address)
end
end
saved = 1
begin
is_submit_form = file_data["forcesavetype"].to_i == 3
if (is_submit_form)
if (new_file_name.eql?(file_name))
new_file_name = DocumentHelper.get_correct_name(file_name, user_address)
end
forcesave_path = DocumentHelper.storage_path(new_file_name, user_address)
else
forcesave_path = DocumentHelper.forcesave_path(new_file_name, user_address, false)
if (forcesave_path.eql?(""))
forcesave_path = DocumentHelper.forcesave_path(new_file_name, user_address, true)
end
end
save_from_uri(forcesave_path, download_uri)
if (is_submit_form)
uid = file_data['actions'][0]['userid']
DocumentHelper.create_meta(new_file_name, uid, "Filling Form", user_address)
end
saved = 0
rescue StandardError => msg
saved = 1
end
return saved
end
def command_request(method, key)
document_command_url = Rails.configuration.urlSite + Rails.configuration.commandUrl
payload = {
:c => method,
:key => key
}
data = nil
begin
uri = URI.parse(document_command_url)
http = Net::HTTP.new(uri.host, uri.port)
if document_command_url.start_with?('https')
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
end
req = Net::HTTP::Post.new(uri.request_uri)
req.add_field("Content-Type", "application/json")
if JwtHelper.is_enabled
payload["token"] = JwtHelper.encode(payload)
jwtHeader = Rails.configuration.header.empty? ? "Authorization" : Rails.configuration.header;
req.add_field(jwtHeader, "Bearer #{JwtHelper.encode({ :payload => payload })}")
end
req.body = payload.to_json
res = http.request(req)
data = res.body
rescue => ex
raise ex.message
end
json_data = JSON.parse(data)
return json_data
end
def save_from_uri(path, uristr)
uri = URI.parse(uristr)
http = Net::HTTP.new(uri.host, uri.port)
if uristr.start_with?('https')
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
end
req = Net::HTTP::Get.new(uri)
res = http.request(req)
data = res.body
if data == nil
raise 'stream is null'
end
File.open(path, 'wb') do |file|
file.write(data)
end
end
end
end

View File

@ -34,6 +34,7 @@
<option value="uid-1">John Smith</option>
<option value="uid-2">Mark Pottato</option>
<option value="uid-3">Hamish Mitchell</option>
<option value="uid-0">anonymous</option>
</select>
</td>
<td width="70%" valign="middle">Select user name before opening the document; you can open the same document using different users in different Web browser sessions, so you can check out multi-user editing functions.</td>
@ -136,7 +137,7 @@
<a class="stored-edit <%= docType %>" href="<%= editUrl %>" target="_blank">
<span title="<%= d %>"><%= d %></span>
</a>
<a href="<%= DocumentHelper.get_file_uri(d, false) %>">
<a href="<%= "download?filename=#{URI::encode(d)}" %>">
<img class="icon-download" src="assets/download-24.png" alt="Download" title="Download" />
</a>
<a class="delete-file" data-filename="<%= d %>">

View File

@ -18,7 +18,14 @@
* limitations under the License.
*
-->
<%= favicon_link_tag "favicon.ico" %>
<%
favicon = "favicon.ico"
if (@file)
favicon = @file.document_type + ".ico"
end
%>
<%= favicon_link_tag favicon %>
<title>ONLYOFFICE</title>
<link rel="stylesheet" type="text/css" href="https://fonts.googleapis.com/css?family=Open+Sans:900,800,700,600,500,400,300&subset=latin,cyrillic-ext,cyrillic,latin-ext" />
<%= stylesheet_link_tag "stylesheet" %>

View File

@ -34,12 +34,14 @@ module OnlineEditorsExampleRuby
Rails.configuration.viewedDocs=".pdf|.djvu|.xps"
Rails.configuration.editedDocs=".docx|.xlsx|.csv|.pptx|.txt"
Rails.configuration.convertDocs=".docm|.dotx|.dotm|.dot|.doc|.odt|.fodt|.ott|.xlsm|.xltx|.xltm|.xlt|.xls|.ods|.fods|.ots|.pptm|.ppt|.ppsx|.ppsm|.pps|.potx|.potm|.pot|.odp|.fodp|.otp|.rtf|.mht|.html|.htm|.epub|.fb2"
Rails.configuration.convertDocs=".docm|.dotx|.dotm|.dot|.doc|.odt|.fodt|.ott|.xlsm|.xltx|.xltm|.xlt|.xls|.ods|.fods|.ots|.pptm|.ppt|.ppsx|.ppsm|.pps|.potx|.potm|.pot|.odp|.fodp|.otp|.rtf|.mht|.html|.htm|.xml|.epub|.fb2"
Rails.configuration.urlSite="https://documentserver/"
Rails.configuration.urlConverter="ConvertService.ashx"
Rails.configuration.urlApi="web-apps/apps/api/documents/api.js"
Rails.configuration.urlPreloader="web-apps/apps/api/documents/cache-scripts.html"
Rails.configuration.commandUrl="coauthoring/CommandService.ashx"
Rails.configuration.urlExample=""
Rails.configuration.jwtSecret = ""

View File

@ -6,6 +6,7 @@ Rails.application.routes.draw do
match '/remove', to: 'home#remove', via: 'get'
match '/upload', to: 'home#upload', via: 'post'
match '/download', to: 'home#download', via: 'get'
match '/convert', to: 'home#convert', via: 'get'
match '/track', to: 'home#track', via: 'post'
match '/csv', to: 'home#csv', via: 'get'