Compare commits

..

57 Commits

Author SHA1 Message Date
dbaa7c5113 Merge pull request #310 from ONLYOFFICE/bugfix/file-request-status
Bugfix/file request status
2022-11-21 13:25:47 +03:00
d6ad145111 nodejs: init type argument (fix ab03bb5490) 2022-11-18 13:51:11 +03:00
44fb3a089c php: added request timeout for download 2022-11-11 14:58:36 +03:00
513bf99adb csharp-mvc: added request timeout for download 2022-11-11 12:23:39 +03:00
6f92633ef8 csharp: added request timeout for download 2022-11-11 12:23:28 +03:00
b67e768dce python: added request status check for file 2022-11-10 19:07:17 +03:00
751a886bfa ruby: added request status check for file 2022-11-10 19:06:29 +03:00
66ea4b144b java: added request status check for file 2022-11-10 19:05:32 +03:00
7a73422231 java-spring: added request status check for file 2022-11-10 19:04:49 +03:00
93accdac7c nodejs: do not send key in referenceData 2022-11-08 16:33:19 +03:00
def268f5f2 Merge remote-tracking branch 'remotes/origin/release/1.4.0' into develop 2022-11-08 10:42:00 +03:00
6054bffb3f Merge pull request #305 from ONLYOFFICE/dependabot/maven/web/documentserver-example/java-spring/com.fasterxml.jackson.core-jackson-databind-2.13.4.1
build(deps): bump jackson-databind from 2.12.6.1 to 2.13.4.1 in /web/documentserver-example/java-spring
2022-11-08 10:31:57 +03:00
a7c917db3f Merge remote-tracking branch 'remotes/origin/release/1.4.0' into develop 2022-11-08 09:18:02 +03:00
30481005a1 removed enum Language (Fix Bug 59624) 2022-11-08 09:17:30 +03:00
5544768500 set language from cookies (Fix Bug 59352) 2022-11-08 09:17:22 +03:00
14e53970c8 update pyjwt=2.6.0 (Fix Bug 59369) 2022-11-08 09:16:37 +03:00
82efd0f18a fix 848cfb20bc 2022-11-07 14:23:01 +03:00
8ce90d89ed removed enum Language (Fix Bug 59624) 2022-11-07 13:07:34 +03:00
2b184972dc Merge pull request #306 from ONLYOFFICE/dependabot/bundler/web/documentserver-example/ruby/nokogiri-1.13.9
build(deps): bump nokogiri from 1.13.8 to 1.13.9 in /web/documentserver-example/ruby
2022-11-03 14:46:55 +03:00
0fb9da4d89 update pom.xml 2022-11-03 14:11:05 +03:00
9277d3de58 Merge branch 'feature/optionDirectUrl' into develop 2022-11-03 13:34:47 +03:00
baf7a1e5dd fix changelog about directUrl task 2022-11-03 13:34:15 +03:00
e2a14a74db Merge pull request #308 from ONLYOFFICE/feature/optionDirectUrl
Feature/option direct url
2022-11-03 13:33:20 +03:00
848cfb20bc set language from cookies (Fix Bug 59352) 2022-11-03 12:05:53 +03:00
ddd3ec82a8 update pyjwt=2.6.0 (Fix Bug 59369) 2022-11-03 10:47:39 +03:00
0ed08fd7b2 Change CHANGELOG.md 2022-11-02 14:58:12 +03:00
e1c5907003 csharp: option to send directUrl 2022-11-02 14:54:33 +03:00
9dd2d7c0db csharp-mvc: fix label for aspx 2022-11-02 14:49:40 +03:00
8f0cbb78af Change CHANGELOG.md 2022-11-02 13:10:39 +03:00
72e48914aa Merge branch 'feature/optionDirectUrl' of https://github.com/ONLYOFFICE/document-server-integration into feature/optionDirectUrl 2022-11-02 13:05:45 +03:00
82a282029a csharp-mvc: option to send directUrl 2022-11-02 13:05:08 +03:00
9b7c12b5c0 Change CHANGELOG.md 2022-11-01 23:10:46 +03:00
6ea5546099 python: option to send directUrl 2022-11-01 23:09:36 +03:00
92fbd1e293 Change CHANGELOG.md 2022-10-28 16:48:05 +03:00
855c1ed9f9 php: option to send directUrl 2022-10-28 16:47:08 +03:00
7e60ec15fd Change CHANGELOG.md 2022-10-28 13:56:28 +03:00
3697a4a888 ruby: option to send directUrl 2022-10-28 13:55:48 +03:00
0b8107d167 Change CHANGELOG.md 2022-10-28 13:52:11 +03:00
885850ee33 java: option to send directUrl 2022-10-27 14:32:21 +03:00
98c61250a6 Change CHANGELOG.md 2022-10-26 16:54:16 +03:00
457487844c java-spring: fix option to send directUrl 2022-10-26 16:47:43 +03:00
ff72956b68 java-spring: option to send directUrl 2022-10-26 16:41:59 +03:00
1593df6aec build(deps): bump nokogiri in /web/documentserver-example/ruby
Bumps [nokogiri](https://github.com/sparklemotion/nokogiri) from 1.13.8 to 1.13.9.
- [Release notes](https://github.com/sparklemotion/nokogiri/releases)
- [Changelog](https://github.com/sparklemotion/nokogiri/blob/main/CHANGELOG.md)
- [Commits](https://github.com/sparklemotion/nokogiri/compare/v1.13.8...v1.13.9)

---
updated-dependencies:
- dependency-name: nokogiri
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-10-26 10:46:51 +00:00
cda8a86c2a Merge remote-tracking branch 'remotes/origin/release/1.4.0' into develop 2022-10-26 13:40:30 +03:00
16584c0abb Merge remote-tracking branch 'remotes/origin/hotfix/1.3.1' into release/1.4.0
# Conflicts:
#	CHANGELOG.md
#	web/documentserver-example/csharp/settings.config
#	web/documentserver-example/ruby/config/application.rb
2022-10-26 13:39:29 +03:00
1ddda89001 Merge pull request #307 from ONLYOFFICE/hotfix/1.3.1
Hotfix/1.3.1
2022-10-26 13:37:19 +03:00
5b76d798fb 1.3.1 2022-10-26 13:28:18 +03:00
e96200df85 java-spring: tooltip fix 2022-10-26 11:53:50 +03:00
de75b11e18 java-spring: option to send directUrl 2022-10-26 11:48:11 +03:00
f27afe1535 java-spring: option to send directUrl 2022-10-25 19:44:39 +03:00
59e17079ff build(deps): bump jackson-databind
Bumps [jackson-databind](https://github.com/FasterXML/jackson) from 2.12.6.1 to 2.13.4.1.
- [Release notes](https://github.com/FasterXML/jackson/releases)
- [Commits](https://github.com/FasterXML/jackson/commits)

---
updated-dependencies:
- dependency-name: com.fasterxml.jackson.core:jackson-databind
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-10-19 07:08:15 +00:00
1bdb3c03bc Merge remote-tracking branch 'remotes/origin/feature/referenceData' into develop 2022-10-14 10:22:24 +03:00
111dc14f2b nodejs: referenceData 2022-10-14 10:20:45 +03:00
4a656c025f 1.4.0 2022-10-14 10:12:48 +03:00
ce9930e5bc java-spring: fixed footer positioning 2022-10-12 11:12:59 +03:00
9da22d7803 java-spring: fixed sorting of the list of languages 2022-10-12 11:00:01 +03:00
d78c677c99 java: fixed sorting of the list of languages 2022-10-12 10:59:41 +03:00
70 changed files with 808 additions and 278 deletions

View File

@ -1,10 +1,18 @@
# Change Log
- nodejs: referenceData
- option to send directUrl
## 1.4.0
- nodejs: option to send directUrl
- opening file on client by directUrl
- offline viewer for anonymous
- added hy, eu, zh-TW, ms, pt-PT
## 1.3.1
- charp: fix references
- ruby: update rails
## 1.3.0
- update empty files
- anonymous without chat
@ -29,6 +37,5 @@
- creating docxf
- opening docxf, oform
## 1.0.0
- added java spring

View File

@ -167,7 +167,7 @@ label .checkbox {
background-image: url("images/file_docxf.svg");
}
.create-sample {
.side-option {
color: #666666;
line-height: 24px;
}

View File

@ -16,6 +16,7 @@
*
*/
using System;
using System.IO;
using System.Web.Mvc;
using OnlineEditorsExampleMVC.Helpers;
@ -31,13 +32,14 @@ namespace OnlineEditorsExampleMVC.Controllers
}
// viewing file in the editor
public ActionResult Editor(string fileName, string editorsMode, string editorsType)
public ActionResult Editor(string fileName, string editorsMode, string editorsType, string directUrl)
{
var file = new FileModel
{
Mode = editorsMode, // editor mode: edit or view
Type = editorsType, // editor type: desktop, mobile, embedded
FileName = Path.GetFileName(fileName) // file name
FileName = Path.GetFileName(fileName), // file name
IsEnabledDirectUrl = directUrl != null ? Convert.ToBoolean(directUrl) : false
};
return View("Editor", file);

View File

@ -442,5 +442,11 @@ namespace OnlineEditorsExampleMVC.Helpers
}
return languages;
}
public static string GetDirectUrl()
{
string isEnabledDirectUrl = HttpUtility.ParseQueryString(HttpContext.Current.Request.Url.Query).Get("directUrl");
return isEnabledDirectUrl != null ? isEnabledDirectUrl : "false";
}
}
}

View File

@ -321,6 +321,7 @@ namespace OnlineEditorsExampleMVC.Helpers
if (string.IsNullOrEmpty(path)) throw new ArgumentException("path"); // file isn't specified
var req = (HttpWebRequest)WebRequest.Create(url);
req.Timeout = 5000;
using (var stream = req.GetResponse().GetResponseStream()) // get input stream of the file information from the url
{
if (stream == null) throw new Exception("stream is null");

View File

@ -33,6 +33,7 @@ namespace OnlineEditorsExampleMVC.Models
{
public string Mode { get; set; } // editor mode
public string Type { get; set; } // editor type
public bool IsEnabledDirectUrl { get; set; } // is enabled direct url
// get file url for Document Server
public string FileUri
@ -126,7 +127,7 @@ namespace OnlineEditorsExampleMVC.Models
{
{ "title", FileName },
{ "url", DownloadUrl },
{ "directUrl", directUrl },
{ "directUrl", IsEnabledDirectUrl ? directUrl : "" },
{ "fileType", ext.Trim('.') },
{ "key", Key },
{
@ -286,7 +287,10 @@ namespace OnlineEditorsExampleMVC.Models
}
dataObj.Add("url", prevFileUrl);
dataObj.Add("directUrl", directPrevFileUrl);
if (IsEnabledDirectUrl)
{
dataObj.Add("directUrl", directPrevFileUrl);
}
dataObj.Add("version", i);
if (i > 1) // check if the version number is greater than 1 (the file was modified)
{
@ -304,11 +308,15 @@ namespace OnlineEditorsExampleMVC.Models
obj.Add("user", change.Count > 0 ? change["user"] : null);
var prev = (Dictionary<string, object>)histData[(i - 2).ToString()]; // get the history data from the previous file version
dataObj.Add("previous", new Dictionary<string, object>() { // write information about previous file version to the data object
dataObj.Add("previous", IsEnabledDirectUrl ? new Dictionary<string, object>() { // write information about previous file version to the data object with direct url
{ "fileType", prev["fileType"] },
{ "key", prev["key"] }, // write key and url information about previous file version
{ "url", prev["url"] },
{ "directUrl", prev["directUrl"] },
} : new Dictionary<string, object>() { // write information about previous file version to the data object without direct url
{ "fileType", prev["fileType"] },
{ "key", prev["key"] }, // write key and url information about previous file version
{ "url", prev["url"] },
});
// write the path to the diff.zip archive with differences in this file version
var changesUrl = DocManagerHelper.GetHistoryDownloadUrl(FileName, (i - 1).ToString(), "diff.zip");
@ -359,10 +367,14 @@ namespace OnlineEditorsExampleMVC.Models
var dataCompareFile = new Dictionary<string, object>
{
{ "fileType", "docx" },
{ "url", compareFileUrl.ToString() },
{ "directUrl", directCompareFileUrl.ToString()}
{ "url", compareFileUrl.ToString() }
};
if (IsEnabledDirectUrl)
{
dataCompareFile.Add("directUrl", directCompareFileUrl.ToString());
}
if (JwtManager.Enabled) // if the secret key to generate token exists
{
var compareFileToken = JwtManager.Encode(dataCompareFile); // encode the dataCompareFile object into the token
@ -396,10 +408,14 @@ namespace OnlineEditorsExampleMVC.Models
var logoConfig = new Dictionary<string, object>
{
{ "fileType", "png"},
{ "url", mailMergeUrl.ToString()},
{ "directUrl", directMailMergeUrl.ToString()}
{ "url", mailMergeUrl.ToString()}
};
if (IsEnabledDirectUrl)
{
logoConfig.Add("directUrl", directMailMergeUrl.ToString());
}
if (JwtManager.Enabled) // if the secret key to generate token exists
{
var token = JwtManager.Encode(logoConfig); // encode logoConfig into the token
@ -437,10 +453,14 @@ namespace OnlineEditorsExampleMVC.Models
var mailMergeConfig = new Dictionary<string, object>
{
{ "fileType", "csv" },
{ "url", mailMergeUrl.ToString()},
{ "directUrl", directMailMergeUrl.ToString()}
{ "url", mailMergeUrl.ToString()}
};
if (IsEnabledDirectUrl)
{
mailMergeConfig.Add("directUrl", directMailMergeUrl.ToString());
}
if (JwtManager.Enabled) // if the secret key to generate token exists
{
var mailmergeToken = JwtManager.Encode(mailMergeConfig); // encode mailMergeConfig into the token

View File

@ -16,11 +16,24 @@
*
*/
var directUrl;
if (typeof jQuery != "undefined") {
jq = jQuery.noConflict();
directUrl = getUrlVars()["directUrl"] == "true";
mustReload = false;
if (directUrl)
jq("#directUrl").prop("checked", directUrl);
else
directUrl = jq("#directUrl").prop("checked");
jq("#directUrl").change(function () {
window.location = "?directUrl=" + jq(this).prop("checked");
});
jq(function () {
jq('#fileupload').fileupload({
dataType: 'json',
@ -219,7 +232,7 @@ if (typeof jQuery != "undefined") {
jq(document).on("click", "#beginEdit:not(.disable)", function () {
var fileId = encodeURIComponent(jq('#hiddenFileName').val());
var url = UrlEditor + "?fileName=" + fileId;
var url = UrlEditor + "?fileName=" + fileId + "&directUrl=" + directUrl;
window.open(url, "_blank");
jq('#hiddenFileName').val("");
jq.unblockUI();
@ -227,7 +240,7 @@ if (typeof jQuery != "undefined") {
jq(document).on("click", "#beginView:not(.disable)", function () {
var fileId = encodeURIComponent(jq('#hiddenFileName').val());
var url = UrlEditor + "?editorsMode=view&fileName=" + fileId;
var url = UrlEditor + "?editorsMode=view&fileName=" + fileId + "&directUrl=" + directUrl;
window.open(url, "_blank");
jq('#hiddenFileName').val("");
jq.unblockUI();
@ -235,7 +248,7 @@ if (typeof jQuery != "undefined") {
jq(document).on("click", "#beginEmbedded:not(.disable)", function () {
var fileId = encodeURIComponent(jq('#hiddenFileName').val());
var url = UrlEditor + "?editorsType=embedded&editorsMode=embedded&fileName=" + fileId;
var url = UrlEditor + "?editorsType=embedded&editorsMode=embedded&fileName=" + fileId + "&directUrl=" + directUrl;
jq("#mainProgress").addClass("embedded");
jq("#beginEmbedded").addClass("disable");
@ -289,6 +302,17 @@ if (typeof jQuery != "undefined") {
}
};
function getUrlVars() {
var vars = [], hash;
var hashes = window.location.href.slice(window.location.href.indexOf('?') + 1).split('&');
for (var i = 0; i < hashes.length; i++) {
hash = hashes[i].split('=');
vars.push(hash[0]);
vars[hash[0]] = hash[1];
}
return vars;
};
var fileList = jq("tr.tableRow");
var mouseIsOverTooltip = false;
@ -304,7 +328,7 @@ if (typeof jQuery != "undefined") {
});
}
} else {
jq(".info").mouseover(function (event) {
jq("#info").mouseover(function (event) {
if (fileList.length > 0) {
if (hideTooltipTimeout != null) {
clearTimeout(hideTooltipTimeout);

View File

@ -70,7 +70,7 @@
<a class="try-editor form" data-type="docxf">Form template</a>
</li>
</ul>
<label class="create-sample">
<label class="side-option">
<input id="createSample" class="checkbox" type="checkbox" />With sample content
</label>
</div>
@ -86,7 +86,7 @@
<tr>
<td valign="middle">
<span class="select-user">Username</span>
<img class="info" src="content/images/info.svg" />
<img id="info" src="content/images/info.svg" />
<select class="select-user" id="user">
<% foreach (User user in Users.getAllUsers())
{ %>
@ -107,6 +107,14 @@
</select>
</td>
</tr>
<tr>
<td valign="middle">
<label class="side-option">
<input id="directUrl" type="checkbox" class="checkbox" />Try opening on client
<img id="directUrlInfo" class="info info-tooltip" data-id="directUrlInfo" data-tooltip="Some files can be opened in the user's browser without connecting to the document server." src="content/images/info.svg" />
</label>
</td>
</tr>
</tbody>
</table>
</div>
@ -156,7 +164,8 @@
<tbody>
<% foreach (var storedFile in storedFiles)
{
var editUrl = "doceditor.aspx?fileID=" + HttpUtility.UrlEncode(storedFile.Name);
var isEnabledDirectUrl = DocManagerHelper.GetDirectUrl();
var editUrl = "doceditor.aspx?fileID=" + HttpUtility.UrlEncode(storedFile.Name);
var docType = FileUtility.GetFileType(storedFile.Name).ToString().ToLower();
var ext = Path.GetExtension(storedFile.Name).ToLower();
var canEdit = DocManagerHelper.EditedExts.Contains(ext);
@ -165,42 +174,42 @@
<tr class="tableRow" title="<%= storedFile.Name %> [<%= DocManagerHelper.GetFileVersion(storedFile.Name, HttpContext.Current.Request.UserHostAddress.Replace(':', '_')) %>]">
<td class="contentCells">
<a class="stored-edit <%= docType %>" href="<%= Url.Action("Editor", "Home", new { fileName = storedFile.Name }) %>" target="_blank">
<a class="stored-edit <%= docType %>" href="<%= Url.Action("Editor", "Home", new { fileName = storedFile.Name, directUrl = isEnabledDirectUrl }) %>" target="_blank">
<span><%= storedFile.Name %></span>
</a>
</td>
<% if (canEdit) { %>
<td class="contentCells contentCells-icon">
<a href="<%= Url.Action("Editor", "Home", new { fileName = storedFile.Name, editorsType = "desktop", editorsMode = "edit" }) %>" target="_blank">
<a href="<%= Url.Action("Editor", "Home", new { fileName = storedFile.Name, editorsType = "desktop", editorsMode = "edit", directUrl = isEnabledDirectUrl }) %>" target="_blank">
<img src="content/images/desktop.svg" alt="Open in editor for full size screens" title="Open in editor for full size screens"/>
</a>
</td>
<td class="contentCells contentCells-icon">
<a href="<%= Url.Action("Editor", "Home", new { fileName = storedFile.Name, editorsType = "mobile", editorsMode = "edit" }) %>" target="_blank">
<a href="<%= Url.Action("Editor", "Home", new { fileName = storedFile.Name, editorsType = "mobile", editorsMode = "edit", directUrl = isEnabledDirectUrl }) %>" target="_blank">
<img src="content/images/mobile.svg" alt="Open in editor for mobile devices" title="Open in editor for mobile devices"/>
</a>
</td>
<td class="contentCells contentCells-icon">
<a href="<%= Url.Action("Editor", "Home", new { fileName = storedFile.Name, editorsType = "desktop", editorsMode = "comment" }) %>" target="_blank">
<a href="<%= Url.Action("Editor", "Home", new { fileName = storedFile.Name, editorsType = "desktop", editorsMode = "comment", directUrl = isEnabledDirectUrl }) %>" target="_blank">
<img src="content/images/comment.svg" alt="Open in editor for comment" title="Open in editor for comment"/>
</a>
</td>
<% if (docType == "word") { %>
<td class="contentCells contentCells-icon">
<a href="<%= Url.Action("Editor", "Home", new { fileName = storedFile.Name, editorsType = "desktop", editorsMode = "review" }) %>" target="_blank">
<a href="<%= Url.Action("Editor", "Home", new { fileName = storedFile.Name, editorsType = "desktop", editorsMode = "review", directUrl = isEnabledDirectUrl }) %>" target="_blank">
<img src="content/images/review.svg" alt="Open in editor for review" title="Open in editor for review"/>
</a>
</td>
<% } else if (docType == "cell") { %>
<td class="contentCells contentCells-icon">
<a href="<%= Url.Action("Editor", "Home", new { fileName = storedFile.Name, editorsType = "desktop", editorsMode = "filter" }) %>" target="_blank">
<a href="<%= Url.Action("Editor", "Home", new { fileName = storedFile.Name, editorsType = "desktop", editorsMode = "filter", directUrl = isEnabledDirectUrl }) %>" target="_blank">
<img src="content/images/filter.svg" alt="Open in editor without access to change the filter" title="Open in editor without access to change the filter" />
</a>
</td>
<% } %>
<% if (docType == "word") { %>
<td class="contentCells contentCells-icon">
<a href="<%= Url.Action("Editor", "Home", new { fileName = storedFile.Name, editorsType = "desktop", editorsMode = "blockcontent" }) %>" target="_blank">
<a href="<%= Url.Action("Editor", "Home", new { fileName = storedFile.Name, editorsType = "desktop", editorsMode = "blockcontent", directUrl = isEnabledDirectUrl }) %>" target="_blank">
<img src="content/images/block-content.svg" alt="Open in editor without content control modification" title="Open in editor without content control modification"/>
</a>
</td>
@ -212,7 +221,7 @@
<% } %>
<% if (isFillFormDoc) { %>
<td class="contentCells contentCells-shift contentCells-icon firstContentCellShift">
<a href="<%= Url.Action("Editor", "Home", new { fileName = storedFile.Name, editorsType = "desktop", editorsMode = "fillForms" }) %>" target="_blank">
<a href="<%= Url.Action("Editor", "Home", new { fileName = storedFile.Name, editorsType = "desktop", editorsMode = "fillForms", directUrl = isEnabledDirectUrl }) %>" target="_blank">
<img src="content/images/fill-forms.svg" alt="Open in editor for filling in forms" title="Open in editor for filling in forms"/>
</a>
</td>
@ -222,7 +231,7 @@
<% } else if (isFillFormDoc) { %>
<td class="contentCells contentCells-icon "></td>
<td class="contentCells contentCells-icon">
<a href="<%= Url.Action("Editor", "Home", new { fileName = storedFile.Name, editorsType = "mobile", editorsMode = "fillForms" }) %>" target="_blank">
<a href="<%= Url.Action("Editor", "Home", new { fileName = storedFile.Name, editorsType = "mobile", editorsMode = "fillForms", directUrl = isEnabledDirectUrl }) %>" target="_blank">
<img src="content/images/mobile-fill-forms.svg" alt="Open in editor for filling in forms for mobile devices" title="Open in editor for filling in forms for mobile devices"/>
</a>
</td>
@ -230,7 +239,7 @@
<td class="contentCells contentCells-icon "></td>
<td class="contentCells contentCells-icon "></td>
<td class="contentCells contentCells-shift contentCells-icon firstContentCellShift">
<a href="<%= Url.Action("Editor", "Home", new { fileName = storedFile.Name, editorsType = "desktop", editorsMode = "fillForms" }) %>" target="_blank">
<a href="<%= Url.Action("Editor", "Home", new { fileName = storedFile.Name, editorsType = "desktop", editorsMode = "fillForms", directUrl = isEnabledDirectUrl }) %>" target="_blank">
<img src="content/images/fill-forms.svg" alt="Open in editor for filling in forms" title="Open in editor for filling in forms"/>
</a>
</td>
@ -238,17 +247,17 @@
<td class="contentCells contentCells-shift contentCells-icon contentCellsEmpty" colspan="6"></td>
<% } %>
<td class="contentCells contentCells-icon firstContentCellViewers">
<a href="<%= Url.Action("Editor", "Home", new { fileName = storedFile.Name, editorsType = "desktop", editorsMode = "view" }) %>" target="_blank">
<a href="<%= Url.Action("Editor", "Home", new { fileName = storedFile.Name, editorsType = "desktop", editorsMode = "view", directUrl = isEnabledDirectUrl }) %>" target="_blank">
<img src="content/images/desktop.svg" alt="Open in viewer for full size screens" title="Open in viewer for full size screens"/>
</a>
</td>
<td class="contentCells contentCells-icon">
<a href="<%= Url.Action("Editor", "Home", new { fileName = storedFile.Name, editorsType = "mobile", editorsMode = "view" }) %>" target="_blank">
<a href="<%= Url.Action("Editor", "Home", new { fileName = storedFile.Name, editorsType = "mobile", editorsMode = "view", directUrl = isEnabledDirectUrl }) %>" target="_blank">
<img src="content/images/mobile.svg" alt="Open in viewer for mobile devices" title="Open in viewer for mobile devices"/>
</a>
</td>
<td class="contentCells contentCells-icon contentCells-shift">
<a href="<%= Url.Action("Editor", "Home", new { fileName = storedFile.Name, editorsType = "embedded", editorsMode = "embedded" }) %>" target="_blank">
<a href="<%= Url.Action("Editor", "Home", new { fileName = storedFile.Name, editorsType = "embedded", editorsMode = "embedded", directUrl = isEnabledDirectUrl }) %>" target="_blank">
<img src="content/images/embeded.svg" alt="Open in embedded mode" title="Open in embedded mode"/>
</a>
</td>

View File

@ -1,7 +1,7 @@
<?xml version="1.0"?>
<appSettings>
<clear />
<add key="version" value="1.3.0"/>
<add key="version" value="1.4.0"/>
<add key="filesize-max" value="52428800"/>
<add key="storage-path" value=""/>

View File

@ -167,7 +167,7 @@ label .checkbox {
background-image: url("images/file_docxf.svg");
}
.create-sample {
.side-option {
color: #666666;
line-height: 24px;
}

View File

@ -73,7 +73,7 @@
<a class="try-editor form" data-type="docxf">Form template</a>
</li>
</ul>
<label class="create-sample">
<label class="side-option">
<input id="createSample" class="checkbox" type="checkbox" />With sample content
</label>
</div>
@ -109,6 +109,14 @@
</select>
</td>
</tr>
<tr>
<td valign="middle">
<label class="side-option">
<input id="directUrl" type="checkbox" class="checkbox" />Try opening on client
<img id="directUrlInfo" class="info info-tooltip" data-id="directUrlInfo" data-tooltip="Some files can be opened in the user's browser without connecting to the document server." src="app_themes/images/info.svg" />
</label>
</td>
</tr>
</tbody>
</table>
</div>
@ -158,7 +166,8 @@
<tbody>
<% foreach (var storedFile in storedFiles)
{
var editUrl = "doceditor.aspx?fileID=" + HttpUtility.UrlEncode(storedFile.Name);
var directUrlParam = GetDirectUrlParam();
var editUrl = "doceditor.aspx?fileID=" + HttpUtility.UrlEncode(storedFile.Name) + directUrlParam;
var ext = Path.GetExtension(storedFile.Name).ToLower();
var docType = DocumentType(storedFile.Name);
var canEdit = EditedExts.Contains(ext);

View File

@ -626,5 +626,11 @@ namespace OnlineEditorsExample
}
return languages;
}
public static string GetDirectUrlParam()
{
string isEnabledDirectUrl = HttpUtility.ParseQueryString(HttpContext.Current.Request.Url.Query).Get("directUrl");
return "&directUrl=" + (isEnabledDirectUrl != null ? isEnabledDirectUrl : "false");
}
}
}

View File

@ -195,7 +195,7 @@ namespace OnlineEditorsExample
{
{ "title", FileName },
{ "url", getDownloadUrl(FileName) },
{ "directUrl", directUrl },
{ "directUrl", IsEnabledDirectUrl() ? directUrl : "" },
{ "fileType", ext.Trim('.') },
{ "key", Key },
{
@ -377,7 +377,12 @@ namespace OnlineEditorsExample
}
dataObj.Add("url", prevFileUrl); // write file url to the data object
dataObj.Add("directUrl", directPrevFileUrl); // write direct url to the data object
if (IsEnabledDirectUrl())
{
dataObj.Add("directUrl", directPrevFileUrl); // write direct url to the data object
}
dataObj.Add("version", i);
if (i > 1) // check if the version number is greater than 1 (the file was modified)
{
@ -395,12 +400,19 @@ namespace OnlineEditorsExample
obj.Add("user", change.Count > 0 ? change["user"] : null);
var prev = (Dictionary<string, object>)histData[(i - 2).ToString()]; // get the history data from the previous file version
dataObj.Add("previous", new Dictionary<string, object>() { // write information about previous file version to the data object
Dictionary<string, object> dataPrev = new Dictionary<string, object>() { // write information about previous file version to the data object
{ "fileType", prev["fileType"] },
{ "key", prev["key"] }, // write key and url information about previous file version
{ "url", prev["url"] },
{ "directUrl", prev["directUrl"] },
});
{ "url", prev["url"] }
};
if (IsEnabledDirectUrl())
{
dataPrev.Add("directUrl", prev["directUrl"]);
}
dataObj.Add("previous", dataPrev);
// write the path to the diff.zip archive with differences in this file version
var changesUrl = MakePublicHistoryUrl(FileName, (i - 1).ToString(), "diff.zip");
dataObj.Add("changesUrl", changesUrl);
@ -442,10 +454,14 @@ namespace OnlineEditorsExample
Dictionary<string, object> logoConfig = new Dictionary<string, object>
{
{ "fileType", "png"},
{ "url", InsertImageUrl.ToString()},
{ "directUrl", DirectImageUrl.ToString()}
{ "url", InsertImageUrl.ToString()}
};
if (IsEnabledDirectUrl())
{
logoConfig.Add("directUrl", DirectImageUrl.ToString());
}
if (JwtManager.Enabled) // if the secret key to generate token exists
{
var insImageToken = JwtManager.Encode(logoConfig); // encode logoConfig into the token
@ -475,10 +491,14 @@ namespace OnlineEditorsExample
Dictionary<string, object> dataCompareFile = new Dictionary<string, object>
{
{ "fileType", "docx" },
{ "url", compareFileUrl.ToString() },
{ "directUrl", DirectFileUrl.ToString() }
{ "url", compareFileUrl.ToString() }
};
if (IsEnabledDirectUrl())
{
dataCompareFile.Add("directUrl", DirectFileUrl.ToString());
}
if (JwtManager.Enabled) // if the secret key to generate token exists
{
var compareFileToken = JwtManager.Encode(dataCompareFile); // encode the dataCompareFile object into the token
@ -510,10 +530,14 @@ namespace OnlineEditorsExample
Dictionary<string, object> mailMergeConfig = new Dictionary<string, object>
{
{ "fileType", "csv" },
{ "url", mailmergeUrl.ToString() },
{ "directUrl", DirectMailMergeUrl.ToString() }
{ "url", mailmergeUrl.ToString() }
};
if (IsEnabledDirectUrl())
{
mailMergeConfig.Add("directUrl", DirectMailMergeUrl.ToString());
}
if (JwtManager.Enabled) // if the secret key to generate token exists
{
var mailmergeToken = JwtManager.Encode(mailMergeConfig); // encode mailMergeConfig into the token
@ -615,5 +639,12 @@ namespace OnlineEditorsExample
{ "name", uname }
}));
}
// get direct url flag
private static bool IsEnabledDirectUrl()
{
string isEnabledDirectUrl = HttpUtility.ParseQueryString(HttpContext.Current.Request.Url.Query).Get("directUrl");
return isEnabledDirectUrl != null ? Convert.ToBoolean(isEnabledDirectUrl) : false;
}
}
}

View File

@ -324,6 +324,7 @@ namespace OnlineEditorsExample
if (string.IsNullOrEmpty(path)) throw new ArgumentException("path"); // file isn't specified
var req = (HttpWebRequest)WebRequest.Create(url);
req.Timeout = 5000;
using (var stream = req.GetResponse().GetResponseStream()) // get input stream of the file information from the url
{
if (stream == null) throw new Exception("stream is null");

View File

@ -16,11 +16,24 @@
*
*/
var directUrl;
if (typeof jQuery != "undefined") {
jq = jQuery.noConflict();
directUrl = getUrlVars()["directUrl"] == "true";
mustReload = false;
if (directUrl)
jq("#directUrl").prop("checked", directUrl);
else
directUrl = jq("#directUrl").prop("checked");
jq("#directUrl").change(function () {
window.location = "?directUrl=" + jq(this).prop("checked");
});
jq(function () {
jq('#fileupload').fileupload({
dataType: 'json',
@ -219,7 +232,7 @@ if (typeof jQuery != "undefined") {
jq(document).on("click", "#beginEdit:not(.disable)", function () {
var fileId = encodeURIComponent(jq('#hiddenFileName').val());
var url = "doceditor.aspx?fileID=" + fileId;
var url = "doceditor.aspx?fileID=" + fileId + "&directUrl=" + directUrl;
window.open(url, "_blank");
jq('#hiddenFileName').val("");
jq.unblockUI();
@ -227,7 +240,7 @@ if (typeof jQuery != "undefined") {
jq(document).on("click", "#beginView:not(.disable)", function () {
var fileId = encodeURIComponent(jq('#hiddenFileName').val());
var url = "doceditor.aspx?editorsMode=view&fileID=" + fileId;
var url = "doceditor.aspx?editorsMode=view&fileID=" + fileId + "&directUrl=" + directUrl;
window.open(url, "_blank");
jq('#hiddenFileName').val("");
jq.unblockUI();
@ -235,7 +248,7 @@ if (typeof jQuery != "undefined") {
jq(document).on("click", "#beginEmbedded:not(.disable)", function () {
var fileId = encodeURIComponent(jq('#hiddenFileName').val());
var url = "doceditor.aspx?editorsType=embedded&editorsMode=embedded&fileID=" + fileId;
var url = "doceditor.aspx?editorsType=embedded&editorsMode=embedded&fileID=" + fileId + "&directUrl=" + directUrl;
jq("#mainProgress").addClass("embedded");
jq("#beginEmbedded").addClass("disable");
@ -288,6 +301,17 @@ if (typeof jQuery != "undefined") {
}
};
function getUrlVars() {
var vars = [], hash;
var hashes = window.location.href.slice(window.location.href.indexOf('?') + 1).split('&');
for (var i = 0; i < hashes.length; i++) {
hash = hashes[i].split('=');
vars.push(hash[0]);
vars[hash[0]] = hash[1];
}
return vars;
};
var fileList = jq("tr.tableRow");
var mouseIsOverTooltip = false;
@ -303,7 +327,7 @@ if (typeof jQuery != "undefined") {
});
}
} else {
jq(".info").mouseover(function (event) {
jq("#info").mouseover(function (event) {
if (fileList.length > 0) {
if (hideTooltipTimeout != null) {
clearTimeout(hideTooltipTimeout);

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8" ?>
<appSettings>
<clear />
<add key="version" value="1.3.0"/>
<add key="version" value="1.4.0"/>
<add key="filesize-max" value="52428800"/>
<add key="storage-path" value=""/>

View File

@ -61,10 +61,15 @@
<version>1.18.20</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.13.4</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.12.6.1</version>
<version>2.13.4.2</version>
</dependency>
<dependency>
<groupId>org.modelmapper</groupId>

View File

@ -26,7 +26,6 @@ import com.onlyoffice.integration.documentserver.models.enums.Action;
import com.onlyoffice.integration.documentserver.storage.FileStoragePathBuilder;
import com.onlyoffice.integration.entities.User;
import com.onlyoffice.integration.dto.Mentions;
import com.onlyoffice.integration.documentserver.models.enums.Language;
import com.onlyoffice.integration.documentserver.models.enums.Type;
import com.onlyoffice.integration.documentserver.models.filemodel.FileModel;
import com.onlyoffice.integration.services.UserServices;
@ -53,6 +52,9 @@ public class EditorController {
@Value("${files.docservice.url.api}")
private String docserviceApiUrl;
@Value("${files.docservice.languages}")
private String langs;
@Autowired
private FileStoragePathBuilder storagePathBuilder;
@ -77,16 +79,25 @@ public class EditorController {
@RequestParam(value = "action", required = false) String actionParam,
@RequestParam(value = "type", required = false) String typeParam,
@RequestParam(value = "actionLink", required = false) String actionLink,
@RequestParam(value = "directUrl", required = false, defaultValue = "false") Boolean directUrl,
@CookieValue(value = "uid") String uid,
@CookieValue(value = "ulang") String lang,
Model model) throws JsonProcessingException {
Action action = Action.edit;
Type type = Type.desktop;
Language language = Language.en;
Locale locale = new Locale("en");
if(actionParam != null) action = Action.valueOf(actionParam);
if(typeParam != null) type = Type.valueOf(typeParam);
if(lang != null) language = Language.valueOf(lang);
List<String> langsAndKeys = Arrays.asList(langs.split("\\|"));
for (String langAndKey : langsAndKeys) {
String[] couple = langAndKey.split(":");
if (couple[0].equals(lang)) {
String[] langAndCountry = couple[0].split("-");
locale = new Locale(langAndCountry[0], langAndCountry.length > 1 ? langAndCountry[1] : "");
}
}
Optional<User> optionalUser = userService.findUserById(Integer.parseInt(uid));
@ -101,10 +112,11 @@ public class EditorController {
.builder()
.fileName(fileName)
.type(type)
.lang(language)
.lang(locale.toLanguageTag())
.action(action)
.user(user)
.actionData(actionLink)
.isEnableDirectUrl(directUrl)
.build()
);
@ -112,9 +124,9 @@ public class EditorController {
model.addAttribute("model", fileModel); // add file model with the default parameters to the original model
model.addAttribute("fileHistory", historyManager.getHistory(fileModel.getDocument())); // get file history and add it to the model
model.addAttribute("docserviceApiUrl",docserviceSite + docserviceApiUrl); // create the document service api URL and add it to the model
model.addAttribute("dataInsertImage", getInsertImage()); // get an image and add it to the model
model.addAttribute("dataCompareFile", getCompareFile()); // get a document for comparison and add it to the model
model.addAttribute("dataMailMergeRecipients", getMailMerge()); // get recipients data for mail merging and add it to the model
model.addAttribute("dataInsertImage", getInsertImage(directUrl)); // get an image and add it to the model
model.addAttribute("dataCompareFile", getCompareFile(directUrl)); // get a document for comparison and add it to the model
model.addAttribute("dataMailMergeRecipients", getMailMerge(directUrl)); // get recipients data for mail merging and add it to the model
model.addAttribute("usersForMentions", getUserMentions(uid)); // get user data for mentions and add it to the model
return "editor.html";
}
@ -134,11 +146,13 @@ public class EditorController {
}
@SneakyThrows
private String getInsertImage() { // get an image that will be inserted into the document
private String getInsertImage(Boolean directUrl) { // get an image that will be inserted into the document
Map<String, Object> dataInsertImage = new HashMap<>();
dataInsertImage.put("fileType", "png");
dataInsertImage.put("url", storagePathBuilder.getServerUrl(true) + "/css/img/logo.png");
dataInsertImage.put("directUrl", storagePathBuilder.getServerUrl(false) + "/css/img/logo.png");
if (directUrl) {
dataInsertImage.put("directUrl", storagePathBuilder.getServerUrl(false) + "/css/img/logo.png");
}
// check if the document token is enabled
if(jwtManager.tokenEnabled()){
@ -149,11 +163,13 @@ public class EditorController {
}
@SneakyThrows
private String getCompareFile(){ // get a document that will be compared with the current document
private String getCompareFile(Boolean directUrl) { // get a document that will be compared with the current document
Map<String, Object> dataCompareFile = new HashMap<>();
dataCompareFile.put("fileType", "docx");
dataCompareFile.put("url", storagePathBuilder.getServerUrl(true) + "/assets?name=sample.docx");
dataCompareFile.put("directUrl", storagePathBuilder.getServerUrl(false) + "/assets?name=sample.docx");
if (directUrl) {
dataCompareFile.put("directUrl", storagePathBuilder.getServerUrl(false) + "/assets?name=sample.docx");
}
// check if the document token is enabled
if(jwtManager.tokenEnabled()){
@ -164,11 +180,13 @@ public class EditorController {
}
@SneakyThrows
private String getMailMerge(){
private String getMailMerge(Boolean directUrl) {
Map<String, Object> dataMailMergeRecipients = new HashMap<>(); // get recipients data for mail merging
dataMailMergeRecipients.put("fileType", "csv");
dataMailMergeRecipients.put("url", storagePathBuilder.getServerUrl(true) + "/csv");
dataMailMergeRecipients.put("directUrl", storagePathBuilder.getServerUrl(false) + "/csv");
if (directUrl) {
dataMailMergeRecipients.put("directUrl", storagePathBuilder.getServerUrl(false) + "/csv");
}
// check if the document token is enabled
if(jwtManager.tokenEnabled()){

View File

@ -68,7 +68,8 @@ public class IndexController {
private String langs;
@GetMapping("${url.index}")
public String index(Model model){
public String index(@RequestParam(value = "directUrl", required = false) Boolean directUrl,
Model model){
java.io.File[] files = storageMutator.getStoredFiles(); // get all the stored files from the storage
List<String> docTypes = new ArrayList<>();
List<Boolean> filesEditable = new ArrayList<>();
@ -76,7 +77,7 @@ public class IndexController {
List<Boolean> isFillFormDoc = new ArrayList<>();
List<String> langsAndKeys = Arrays.asList(langs.split("\\|"));
Map<String, String> languages = new HashMap<>();
Map<String, String> languages = new LinkedHashMap<>();
langsAndKeys.forEach((str) -> {
String[] couple = str.split(":");
@ -107,6 +108,7 @@ public class IndexController {
model.addAttribute("tooltip", tooltip);
model.addAttribute("users", users);
model.addAttribute("languages", languages);
model.addAttribute("directUrl", directUrl);
return "index.html";
}

View File

@ -76,8 +76,15 @@ public class DefaultCallbackManager implements CallbackManager {
URL uri = new URL(url);
java.net.HttpURLConnection connection = (java.net.HttpURLConnection) uri.openConnection();
connection.setConnectTimeout(5000);
InputStream stream = connection.getInputStream(); // get input stream of the file information from the URL
int statusCode = connection.getResponseCode();
if (statusCode != 200) { // checking status code
connection.disconnect();
throw new RuntimeException("Document editing service returned status: " + statusCode);
}
if (stream == null) {
connection.disconnect();
throw new RuntimeException("Input stream is null");

View File

@ -91,8 +91,10 @@ public class DefaultHistoryManager implements HistoryManager {
dataObj.put("key", key);
dataObj.put("url", i == curVer ? document.getUrl() :
documentManager.getHistoryFileUrl(document.getTitle(), i, "prev" + fileUtility.getFileExtension(document.getTitle()), true));
dataObj.put("directUrl", i == curVer ? document.getDirectUrl() :
documentManager.getHistoryFileUrl(document.getTitle(), i, "prev" + fileUtility.getFileExtension(document.getTitle()), false));
if (!document.getDirectUrl().equals("")) {
dataObj.put("directUrl", i == curVer ? document.getDirectUrl() :
documentManager.getHistoryFileUrl(document.getTitle(), i, "prev" + fileUtility.getFileExtension(document.getTitle()), false));
}
dataObj.put("version", i);
if (i > 1) { //check if the version number is greater than 1
@ -111,7 +113,9 @@ public class DefaultHistoryManager implements HistoryManager {
prevInfo.put("fileType", prev.get("fileType"));
prevInfo.put("key", prev.get("key")); // write key and URL information about previous file version
prevInfo.put("url", prev.get("url"));
prevInfo.put("directUrl", prev.get("directUrl"));
if (!document.getDirectUrl().equals("")) {
prevInfo.put("directUrl", prev.get("directUrl"));
}
dataObj.put("previous", prevInfo); // write information about previous file version to the data object
// write the path to the diff.zip archive with differences in this file version
Integer verdiff = i - 1;

View File

@ -1,55 +0,0 @@
/**
*
* (c) Copyright Ascensio System SIA 2021
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package com.onlyoffice.integration.documentserver.models.enums;
public enum Language {
en,
de,
ru,
pl,
be,
bg,
ca,
zh,
cs,
da,
nl,
fi,
fr,
el,
hu,
id,
it,
ja,
ko,
lv,
lo,
nb,
pt,
ro,
sk,
sl,
sv,
es,
tr,
uk,
vi,
gl,
az
}

View File

@ -20,7 +20,6 @@ package com.onlyoffice.integration.documentserver.models.filemodel;
import com.onlyoffice.integration.documentserver.models.configurations.Customization;
import com.onlyoffice.integration.documentserver.models.configurations.Embedded;
import com.onlyoffice.integration.documentserver.models.enums.Language;
import com.onlyoffice.integration.documentserver.models.enums.Mode;
import lombok.*;
import org.springframework.beans.factory.annotation.Autowired;
@ -44,7 +43,7 @@ public class EditorConfig { // the parameters pertaining to the editor interfac
private Customization customization; // the parameters which allow to customize the editor interface so that it looked like your other products (if there are any) and change the presence or absence of the additional buttons, links, change logos and editor owner details
@Autowired
private Embedded embedded; // the parameters which allow to change the settings which define the behavior of the buttons in the embedded mode
private Language lang; // the editor interface language
private String lang; // the editor interface language
private Mode mode; // the editor opening mode
@Autowired
private User user; // the user currently viewing or editing the document

View File

@ -95,6 +95,13 @@ public class DefaultServiceConverter implements ServiceConverter
}
connection.connect();
int statusCode = connection.getResponseCode();
if (statusCode != 200) { // checking status code
connection.disconnect();
throw new RuntimeException("Convertation service returned status: " + statusCode);
}
try (OutputStream os = connection.getOutputStream()) {
os.write(bodyByte); // write bytes to the output stream
os.flush(); // force write data to the output stream that can be cached in the current thread

View File

@ -55,7 +55,7 @@ public class DefaultDocumentConfigurer implements DocumentConfigurer<DefaultDocu
document.setTitle(fileName); // set the title to the document config
document.setUrl(documentManager.getDownloadUrl(fileName, true)); // set the URL to download a file to the document config
document.setUrlUser(documentManager.getFileUri(fileName, false)); // set the file URL to the document config
document.setDirectUrl(documentManager.getDownloadUrl(fileName, false));
document.setDirectUrl(wrapper.getIsEnableDirectUrl() ? documentManager.getDownloadUrl(fileName, false) : "");
document.setFileType(fileUtility.getFileExtension(fileName).replace(".","")); // set the file type to the document config
document.getInfo().setFavorite(wrapper.getFavorite()); // set the favorite parameter to the document config

View File

@ -80,6 +80,7 @@ public class DefaultFileConfigurer implements FileConfigurer<DefaultFileWrapper>
.fileName(fileName)
.permission(updatePermissions(userPermissions, action, canEdit))
.favorite(wrapper.getUser().getFavorite())
.isEnableDirectUrl(wrapper.getIsEnableDirectUrl())
.build();
defaultDocumentConfigurer.configure(fileModel.getDocument(), documentWrapper); // define the document configurer

View File

@ -28,4 +28,5 @@ public class DefaultDocumentWrapper {
private Permission permission;
private String fileName;
private Boolean favorite;
private Boolean isEnableDirectUrl;
}

View File

@ -20,7 +20,6 @@ package com.onlyoffice.integration.services.configurers.wrappers;
import com.onlyoffice.integration.documentserver.models.enums.Action;
import com.onlyoffice.integration.entities.User;
import com.onlyoffice.integration.documentserver.models.enums.Language;
import com.onlyoffice.integration.documentserver.models.enums.Type;
import lombok.Builder;
import lombok.Getter;
@ -33,8 +32,9 @@ public class DefaultFileWrapper {
private String fileName;
private Type type;
private User user;
private Language lang;
private String lang;
private Action action;
private String actionData;
private Boolean canEdit;
private Boolean isEnableDirectUrl;
}

View File

@ -1,4 +1,4 @@
server.version=1.3.0
server.version=1.4.0
server.address=
server.port=4000

View File

@ -72,6 +72,7 @@ header img {
}
.main{
display: table;
height: calc(100% - 112px);
min-height: 536px;
}
@ -166,7 +167,7 @@ label .checkbox {
background-image: url("img/file_docxf.svg");
}
.create-sample {
.side-option {
color: #666666;
line-height: 24px;
}

View File

@ -16,11 +16,24 @@
*
*/
var directUrl;
if (typeof jQuery !== "undefined") {
jq = jQuery.noConflict();
directUrl = getUrlVars()["directUrl"] == "true";
mustReload = false;
if (directUrl)
jq("#directUrl").prop("checked", directUrl);
else
directUrl = jq("#directUrl").prop("checked");
jq("#directUrl").change(function() {
window.location = "?directUrl=" + jq(this).prop("checked");
});
jq(function () {
jq("#fileupload").fileupload({
dataType: "json",
@ -228,7 +241,7 @@ if (typeof jQuery !== "undefined") {
jq(document).on("click", "#beginEdit:not(.disable)", function () {
var fileId = encodeURIComponent(jq("#hiddenFileName").val());
var url = UrlEditor + "?action=edit&fileName=" + fileId;
var url = UrlEditor + "?action=edit&fileName=" + fileId + "&directUrl=" + directUrl;
window.open(url, "_blank");
jq("#hiddenFileName").val("");
jq.unblockUI();
@ -236,7 +249,7 @@ if (typeof jQuery !== "undefined") {
jq(document).on("click", "#beginView:not(.disable)", function () {
var fileId = encodeURIComponent(jq("#hiddenFileName").val());
var url = UrlEditor + "?action=view&fileName=" + fileId;
var url = UrlEditor + "?action=view&fileName=" + fileId + "&directUrl=" + directUrl;
window.open(url, "_blank");
jq("#hiddenFileName").val("");
jq.unblockUI();
@ -244,7 +257,7 @@ if (typeof jQuery !== "undefined") {
jq(document).on("click", "#beginEmbedded:not(.disable)", function () {
var fileId = encodeURIComponent(jq("#hiddenFileName").val());
var url = UrlEditor + "?type=embedded&action=embedded&fileName=" + fileId;
var url = UrlEditor + "?type=embedded&action=embedded&fileName=" + fileId + "&directUrl=" + directUrl;
jq("#mainProgress").addClass("embedded");
jq("#beginEmbedded").addClass("disable");
@ -300,6 +313,17 @@ if (typeof jQuery !== "undefined") {
}
};
function getUrlVars() {
var vars = [], hash;
var hashes = window.location.href.slice(window.location.href.indexOf('?') + 1).split('&');
for (var i = 0; i < hashes.length; i++) {
hash = hashes[i].split('=');
vars.push(hash[0]);
vars[hash[0]] = hash[1];
}
return vars;
};
jq("#portal-info")[0].innerHTML += jq("#portal-info")[0].attributes.tooltip.value;
var fileList = jq("tr.tableRow");
@ -317,7 +341,7 @@ if (typeof jQuery !== "undefined") {
});
}
} else {
jq(".info").mouseover(function (event) {
jq("#info").mouseover(function (event) {
if (fileList.length > 0) {
if (hideTooltipTimeout != null) {
clearTimeout(hideTooltipTimeout);

View File

@ -59,7 +59,7 @@
<a class="try-editor form" data-type="docxf">Form template</a>
</li>
</ul>
<label class="create-sample">
<label class="side-option">
<input id="createSample" class="checkbox" type="checkbox" />With sample content
</label>
</div>
@ -75,7 +75,7 @@
<tr>
<td valign="middle">
<span class="select-user">Username</span>
<img class="info" src="css/img/info.svg"/>
<img id="info" class="info" src="css/img/info.svg"/>
<select class="select-user" id="user">
<option th:each="user : ${users}"
th:value="${user.id}"
@ -93,6 +93,14 @@
</select>
</td>
</tr>
<tr>
<td valign="middle">
<label class="side-option">
<input id="directUrl" type="checkbox" class="checkbox" />Try opening on client
<img id="directUrlInfo" class="info info-tooltip" data-id="directUrlInfo" data-tooltip="Some files can be opened in the user's browser without connecting to the document server." src="css/img/info.svg" />
</label>
</td>
</tr>
</tbody>
</table>
</div>
@ -129,43 +137,50 @@
<tr th:each="file,iState : ${files}" class="tableRow" th:title="${files[iState.index].getName() + versions[iState.index]}">
<td class="contentCells">
<a class="stored-edit" th:classappend="${docTypes[iState.index]}"
th:href="@{/editor(fileName=${files[iState.index].getName()})}" target="_blank">
th:with="directUrl=${directUrl}"
th:href="@{/editor(fileName=${files[iState.index].getName()}, __(${#strings.isEmpty(directUrl)} ? '' : ('directUrl=' + ${directUrl}))__)}" target="_blank">
<span th:text="${files[iState.index].getName()}"></span>
</a>
</td>
<th:block th:if="${filesEditable[iState.index]}">
<td class="contentCells contentCells-icon">
<a th:href="@{/editor(fileName=${files[iState.index].getName()},type='desktop',action='edit')}" target="_blank">
<a th:with="directUrl=${directUrl}"
th:href="@{/editor(fileName=${files[iState.index].getName()},type='desktop',action='edit', __(${#strings.isEmpty(directUrl)} ? '' : ('directUrl=' + ${directUrl}))__)}" target="_blank">
<img src="css/img/desktop.svg" alt="Open in editor for full size screens" title="Open in editor for full size screens"/>
</a>
</td>
<td class="contentCells contentCells-icon">
<a th:href="@{/editor(fileName=${files[iState.index].getName()},type='mobile',action='edit')}" target="_blank">
<a th:with="directUrl=${directUrl}"
th:href="@{/editor(fileName=${files[iState.index].getName()},type='mobile',action='edit', __(${#strings.isEmpty(directUrl)} ? '' : ('directUrl=' + ${directUrl}))__)}" target="_blank">
<img src="css/img/mobile.svg" alt="Open in editor for mobile devices" title="Open in editor for mobile devices"/>
</a>
</td>
<td class="contentCells contentCells-icon">
<a th:href="@{/editor(fileName=${files[iState.index].getName()},type='desktop',action='comment')}" target="_blank">
<a th:with="directUrl=${directUrl}"
th:href="@{/editor(fileName=${files[iState.index].getName()},type='desktop',action='comment', __(${#strings.isEmpty(directUrl)} ? '' : ('directUrl=' + ${directUrl}))__)}" target="_blank">
<img src="css/img/comment.svg" alt="Open in editor for comment" title="Open in editor for comment"/>
</a>
</td>
<div th:if="${docTypes[iState.index]} eq 'word'">
<td class="contentCells contentCells-icon">
<a th:href="@{/editor(fileName=${files[iState.index].getName()},type='desktop',action='review')}" target="_blank">
<a th:with="directUrl=${directUrl}"
th:href="@{/editor(fileName=${files[iState.index].getName()},type='desktop',action='review', __(${#strings.isEmpty(directUrl)} ? '' : ('directUrl=' + ${directUrl}))__)}" target="_blank">
<img src="css/img/review.svg" alt="Open in editor for review" title="Open in editor for review"/>
</a>
</td>
</div>
<div th:if="${docTypes[iState.index]} eq 'cell'">
<td class="contentCells contentCells-icon">
<a th:href="@{/editor(fileName=${files[iState.index].getName()},type='desktop',action='filter')}" target="_blank">
<a th:with="directUrl=${directUrl}"
th:href="@{/editor(fileName=${files[iState.index].getName()},type='desktop',action='filter', __(${#strings.isEmpty(directUrl)} ? '' : ('directUrl=' + ${directUrl}))__)}" target="_blank">
<img src="css/img/filter.svg" alt="Open in editor without access to change the filter" title="Open in editor without access to change the filter" />
</a>
</td>
</div>
<div th:if="${docTypes[iState.index]} eq 'word'">
<td class="contentCells contentCells-icon">
<a th:href="@{/editor(fileName=${files[iState.index].getName()},type='desktop',action='blockcontent')}" target="_blank">
<a th:with="directUrl=${directUrl}"
th:href="@{/editor(fileName=${files[iState.index].getName()},type='desktop',action='blockcontent', __(${#strings.isEmpty(directUrl)} ? '' : ('directUrl=' + ${directUrl}))__)}" target="_blank">
<img src="css/img/block-content.svg" alt="Open in editor without content control modification" title="Open in editor without content control modification"/>
</a>
</td>
@ -178,7 +193,8 @@
</div>
<div th:if="${isFillFormDoc[iState.index]}">
<td class="contentCells contentCells-shift contentCells-icon firstContentCellShift">
<a th:href="@{/editor(fileName=${files[iState.index].getName()},type='desktop',action='fillForms')}" target="_blank">
<a th:with="directUrl=${directUrl}"
th:href="@{/editor(fileName=${files[iState.index].getName()},type='desktop',action='fillForms', __(${#strings.isEmpty(directUrl)} ? '' : ('directUrl=' + ${directUrl}))__)}" target="_blank">
<img src="css/img/fill-forms.svg" alt="Open in editor for filling in forms" title="Open in editor for filling in forms"/>
</a>
</td>
@ -190,7 +206,8 @@
<th:block th:if="${isFillFormDoc[iState.index] and not filesEditable[iState.index]}">
<td class="contentCells contentCells-icon "></td>
<td class="contentCells contentCells-icon">
<a th:href="@{/editor(fileName=${files[iState.index].getName()},type='mobile',action='fillForms')}" target="_blank">
<a th:with="directUrl=${directUrl}"
th:href="@{/editor(fileName=${files[iState.index].getName()},type='mobile',action='fillForms', __(${#strings.isEmpty(directUrl)} ? '' : ('directUrl=' + ${directUrl}))__)}" target="_blank">
<img src="css/img/mobile-fill-forms.svg" alt="Open in editor for filling in forms for mobile devices" title="Open in editor for filling in forms for mobile devices" />
</a>
</td>
@ -198,7 +215,8 @@
<td class="contentCells contentCells-icon "></td>
<td class="contentCells contentCells-icon "></td>
<td class="contentCells contentCells-shift contentCells-icon firstContentCellShift">
<a th:href="@{/editor(fileName=${files[iState.index].getName()},type='desktop',action='fillForms')}" target="_blank">
<a th:with="directUrl=${directUrl}"
th:href="@{/editor(fileName=${files[iState.index].getName()},type='desktop',action='fillForms', __(${#strings.isEmpty(directUrl)} ? '' : ('directUrl=' + ${directUrl}))__)}" target="_blank">
<img src="css/img/fill-forms.svg" alt="Open in editor for filling in forms" title="Open in editor for filling in forms"/>
</a>
</td>
@ -207,17 +225,20 @@
<td class="contentCells contentCells-shift contentCells-icon contentCellsEmpty" colspan="6"></td>
</th:block>
<td class="contentCells contentCells-icon firstContentCellViewers">
<a th:href="@{/editor(fileName=${files[iState.index].getName()},type='desktop',action='view')}" target="_blank">
<a th:with="directUrl=${directUrl}"
th:href="@{/editor(fileName=${files[iState.index].getName()},type='desktop',action='view', __(${#strings.isEmpty(directUrl)} ? '' : ('directUrl=' + ${directUrl}))__)}" target="_blank">
<img src="css/img/desktop.svg" alt="Open in viewer for full size screens" title="Open in viewer for full size screens"/>
</a>
</td>
<td class="contentCells contentCells-icon">
<a th:href="@{/editor(fileName=${files[iState.index].getName()},type='mobile',action='view')}" target="_blank">
<a th:with="directUrl=${directUrl}"
th:href="@{/editor(fileName=${files[iState.index].getName()},type='mobile',action='view', __(${#strings.isEmpty(directUrl)} ? '' : ('directUrl=' + ${directUrl}))__)}" target="_blank">
<img src="css/img/mobile.svg" alt="Open in viewer for mobile devices" title="Open in viewer for mobile devices"/>
</a>
</td>
<td class="contentCells contentCells-icon contentCells-shift">
<a th:href="@{/editor(fileName=${files[iState.index].getName()},type='embedded',action='embedded')}" target="_blank">
<a th:with="directUrl=${directUrl}"
th:href="@{/editor(fileName=${files[iState.index].getName()},type='embedded',action='embedded', __(${#strings.isEmpty(directUrl)} ? '' : ('directUrl=' + ${directUrl}))__)}" target="_blank">
<img src="css/img/embeded.svg" alt="Open in embedded mode" title="Open in embedded mode"/>
</a>
</td>
@ -318,8 +339,19 @@
<script type="text/javascript" src="scripts/jscript.js"></script>
<script type="text/javascript" src="scripts/converter.js"></script>
<script type="text/javascript">
document.addEventListener('DOMContentLoaded', function(){
document.getElementById("language").value="en";
document.addEventListener('DOMContentLoaded', function() {
var lang = document.cookie
.split('; ')
.find((row) => row.startsWith('ulang='))
?.split('=')[1];
var languages = Array.from(document.getElementById("language").options).map(e => e.value)
if (!languages.includes(lang)) {
lang = "en";
}
document.getElementById("language").value=lang;
});
</script>
</body>

View File

@ -47,6 +47,7 @@ public class EditorServlet extends HttpServlet
String fileName = FileUtility.GetFileName(request.getParameter("fileName"));
String fileExt = request.getParameter("fileExt");
String sample = request.getParameter("sample");
Boolean isEnableDirectUrl = Boolean.valueOf(request.getParameter("directUrl"));
// check if there is sample data in the request
Boolean sampleData = (sample == null || sample.isEmpty()) ? false : sample.toLowerCase().equals("true");
@ -70,7 +71,7 @@ public class EditorServlet extends HttpServlet
}
// create file model (get all the necessary parameters from cookies)
FileModel file = new FileModel(fileName, cm.getCookie("ulang"), request.getParameter("actionLink"), user);
FileModel file = new FileModel(fileName, cm.getCookie("ulang"), request.getParameter("actionLink"), user, isEnableDirectUrl);
// change type parameter if needed
file.changeType(request.getParameter("mode"), request.getParameter("type"), user, fileName);
@ -78,19 +79,25 @@ public class EditorServlet extends HttpServlet
Map<String, Object> dataInsertImage = new HashMap<>();
dataInsertImage.put("fileType", "png");
dataInsertImage.put("url", DocumentManager.GetServerUrl(true) + "/css/img/logo.png");
dataInsertImage.put("directUrl", DocumentManager.GetServerUrl(false) + "/css/img/logo.png");
if (isEnableDirectUrl) {
dataInsertImage.put("directUrl", DocumentManager.GetServerUrl(false) + "/css/img/logo.png");
}
// a document that will be compared with the current document
Map<String, Object> dataCompareFile = new HashMap<>();
dataCompareFile.put("fileType", "docx");
dataCompareFile.put("url", DocumentManager.GetServerUrl(true) + "/IndexServlet?type=assets&name=sample.docx");
dataCompareFile.put("directUrl", DocumentManager.GetServerUrl(false) + "/IndexServlet?type=assets&name=sample.docx");
if (isEnableDirectUrl) {
dataCompareFile.put("directUrl", DocumentManager.GetServerUrl(false) + "/IndexServlet?type=assets&name=sample.docx");
}
// recipients data for mail merging
Map<String, Object> dataMailMergeRecipients = new HashMap<>();
dataMailMergeRecipients.put("fileType", "csv");
dataMailMergeRecipients.put("url", DocumentManager.GetServerUrl(true) + "/IndexServlet?type=csv");
dataMailMergeRecipients.put("directUrl", DocumentManager.GetServerUrl(false) + "/IndexServlet?type=csv");
if (isEnableDirectUrl) {
dataMailMergeRecipients.put("directUrl", DocumentManager.GetServerUrl(false) + "/IndexServlet?type=csv");
}
// users data for mentions
List<Map<String, Object>> usersForMentions = Users.getUsersForMentions(user.id);

View File

@ -40,7 +40,7 @@ public class FileModel
public String token;
// create file model
public FileModel(String fileName, String lang, String actionData, User user)
public FileModel(String fileName, String lang, String actionData, User user, Boolean isEnableDirectUrl)
{
if (fileName == null) fileName = "";
fileName = fileName.trim(); // remove extra spaces in the file name
@ -52,7 +52,7 @@ public class FileModel
document = new Document();
document.title = fileName;
document.url = DocumentManager.GetDownloadUrl(fileName, true); // get file url
document.directUrl = DocumentManager.GetDownloadUrl(fileName, false); // get direct url
document.directUrl = isEnableDirectUrl ? DocumentManager.GetDownloadUrl(fileName, false) : ""; // get direct url
document.fileType = FileUtility.GetFileExtension(fileName).replace(".", ""); // get file extension from the file name
// generate document key
document.key = ServiceConverter.GenerateRevisionId(DocumentManager.CurUserHostAddress(null) + "/" + fileName + "/" + Long.toString(new File(DocumentManager.StoragePath(fileName, null)).lastModified()));
@ -185,7 +185,9 @@ public class FileModel
dataObj.put("fileType", FileUtility.GetFileExtension(document.title).substring(1));
dataObj.put("key", key);
dataObj.put("url", i == curVer ? document.url : DocumentManager.GetDownloadHistoryUrl(document.title, i, "prev" + FileUtility.GetFileExtension(document.title), true));
dataObj.put("directUrl", i == curVer ? document.url : DocumentManager.GetDownloadHistoryUrl(document.title, i, "prev" + FileUtility.GetFileExtension(document.title), false));
if (!document.directUrl.equals("")) {
dataObj.put("directUrl", i == curVer ? document.url : DocumentManager.GetDownloadHistoryUrl(document.title, i, "prev" + FileUtility.GetFileExtension(document.title), false));
}
dataObj.put("version", i);
if (i > 1) { //check if the version number is greater than 1

View File

@ -577,7 +577,7 @@ public class DocumentManager
String langs = ConfigManager.GetProperty("files.docservice.languages");
List<String> langsAndKeys = Arrays.asList(langs.split("\\|"));
Map<String, String> languages = new HashMap<>();
Map<String, String> languages = new LinkedHashMap<>();
langsAndKeys.forEach((str) -> {
String[] couple = str.split(":");

View File

@ -143,6 +143,12 @@ public class ServiceConverter
}
connection.connect();
int statusCode = connection.getResponseCode();
if (statusCode != 200) { // checking status code
connection.disconnect();
throw new Exception("Conversion service returned status: " + statusCode);
}
try (OutputStream os = connection.getOutputStream()) {
os.write(bodyByte);
}

View File

@ -253,6 +253,14 @@ public class TrackManager {
URL uri = new URL(url);
java.net.HttpURLConnection connection = (java.net.HttpURLConnection) uri.openConnection();
connection.setConnectTimeout(5000);
int statusCode = connection.getResponseCode();
if (statusCode != 200) { // checking status code
connection.disconnect();
throw new RuntimeException("Document editing service returned status: " + statusCode);
}
InputStream stream = connection.getInputStream(); // get input stream of the file information from the url
if (stream == null)

View File

@ -1,4 +1,4 @@
version=1.3.0
version=1.4.0
filesize-max=5242880
storage-folder=app_data

View File

@ -167,7 +167,7 @@ label .checkbox {
background-image: url("img/file_docxf.svg");
}
.create-sample {
.side-option {
color: #666666;
line-height: 24px;
}

View File

@ -87,7 +87,7 @@
<tr>
<td valign="middle">
<span class="select-user">Username</span>
<img class="info" src="css/img/info.svg" />
<img id="info" src="css/img/info.svg" />
<select class="select-user" id="user">
<% for (User user : Users.getAllUsers()) { %>
<option value="<%= user.id %>"><%= user.name == null ? "Anonymous" : user.name %></option>
@ -106,6 +106,12 @@
</select>
</td>
</tr>
<td valign="middle">
<label class="side-option">
<input id="directUrl" type="checkbox" class="checkbox" />Try opening on client
<img id="directUrlInfo" class="info info-tooltip" data-id="directUrlInfo" data-tooltip="Some files can be opened in the user's browser without connecting to the document server." src="css/img/info.svg" />
</label>
</td>
</tbody>
</table>
</div>
@ -159,42 +165,44 @@
%>
<tr class="tableRow" title="<%= files[i].getName() %><%= version %>">
<td class="contentCells">
<a class="stored-edit <%= docType %>" href="EditorServlet?fileName=<%= URLEncoder.encode(files[i].getName(), "UTF-8") %>" target="_blank">
<a class="stored-edit <%= docType %>" href="EditorServlet?fileName=<%= URLEncoder.encode(files[i].getName(), "UTF-8").concat(request.getParameter("directUrl") != null ? "&directUrl=".concat(request.getParameter("directUrl")) : "") %>" target="_blank">
<span><%= files[i].getName() %></span>
</a>
</td>
<% if (canEdit) { %>
<td class="contentCells contentCells-icon">
<a href="EditorServlet?fileName=<%= URLEncoder.encode(files[i].getName(), "UTF-8") %>&type=desktop&mode=edit" target="_blank">
<a href="EditorServlet?fileName=<%= URLEncoder.encode(files[i].getName(), "UTF-8").concat(request.getParameter("directUrl") != null ? "&directUrl=".concat(request.getParameter("directUrl")) : "") %>&type=desktop&mode=edit" target="_blank">
<img src="css/img/desktop.svg" alt="Open in editor for full size screens" title="Open in editor for full size screens"/>
</a>
</td>
<td class="contentCells contentCells-icon">
<a href="EditorServlet?fileName=<%= URLEncoder.encode(files[i].getName(), "UTF-8") %>&type=mobile&mode=edit" target="_blank">
<a href="EditorServlet?fileName=<%= URLEncoder.encode(files[i].getName(), "UTF-8").concat(request.getParameter("directUrl") != null ? "&directUrl=".concat(request.getParameter("directUrl")) : "") %>&type=mobile&mode=edit" target="_blank">
<img src="css/img/mobile.svg" alt="Open in editor for mobile devices" title="Open in editor for mobile devices"/>
</a>
</td>
<td class="contentCells contentCells-icon">
<a href="EditorServlet?fileName=<%= URLEncoder.encode(files[i].getName(), "UTF-8") %>&type=desktop&mode=comment" target="_blank">
<a href="EditorServlet?fileName=<%= URLEncoder.encode(files[i].getName(), "UTF-8").concat(request.getParameter("directUrl") != null ? "&directUrl=".concat(request.getParameter("directUrl")) : "") %>&type=desktop&mode=comment" target="_blank">
<img src="css/img/comment.svg" alt="Open in editor for comment" title="Open in editor for comment"/>
</a>
</td>
<% if (docType.equals("word")) { %>
<td class="contentCells contentCells-icon">
<a href="EditorServlet?fileName=<%= URLEncoder.encode(files[i].getName(), "UTF-8") %>&type=desktop&mode=review" target="_blank">
<a href="EditorServlet?fileName=<%= URLEncoder.encode(files[i].getName(), "UTF-8").concat(request.getParameter("directUrl") != null ? "&directUrl=".concat(request.getParameter("directUrl")) : "") %>&type=desktop&mode=review" target="_blank">
<img src="css/img/review.svg" alt="Open in editor for review" title="Open in editor for review"/>
</a>
</td>
<% } else if (docType.equals("cell")) { %>
<td class="contentCells contentCells-icon">
<a href="EditorServlet?fileName=<%= URLEncoder.encode(files[i].getName(), "UTF-8") %>&type=desktop&mode=filter" target="_blank">
<a href="EditorServlet?fileName=<%= URLEncoder.encode(files[i].getName(), "UTF-8").concat(request.getParameter("directUrl") != null ? "&directUrl=".concat(request.getParameter("directUrl")) : "") %>&type=desktop&mode=filter" target="_blank">
<img src="css/img/filter.svg" alt="Open in editor without access to change the filter" title="Open in editor without access to change the filter"/>
</a>
</td>
<% } %>
<% if (docType.equals("word")) { %>
<td class="contentCells contentCells-icon">
<a href="EditorServlet?fileName=<%= URLEncoder.encode(files[i].getName(), "UTF-8") %>&type=desktop&mode=blockcontent" target="_blank">
<a href="EditorServlet?fileName=<%= URLEncoder.encode(files[i].getName(), "UTF-8")
.concat(request.getParameter("directUrl") != null ?
"&directUrl=".concat(request.getParameter("directUrl")) : "") %>&type=desktop&mode=blockcontent" target="_blank">
<img src="css/img/block-content.svg" alt="Open in editor without content control modification" title="Open in editor without content control modification"/>
</a>
</td>
@ -206,7 +214,9 @@
<% } %>
<% if (isFillFormDoc) { %>
<td class="contentCells contentCells-shift contentCells-icon firstContentCellShift">
<a href="EditorServlet?fileName=<%= URLEncoder.encode(files[i].getName(), "UTF-8") %>&type=desktop&mode=fillForms" target="_blank">
<a href="EditorServlet?fileName=<%= URLEncoder.encode(files[i].getName(), "UTF-8")
.concat(request.getParameter("directUrl") != null ?
"&directUrl=".concat(request.getParameter("directUrl")) : "") %>&type=desktop&mode=fillForms" target="_blank">
<img src="css/img/fill-forms.svg" alt="Open in editor for filling in forms" title="Open in editor for filling in forms"/>
</a>
</td>
@ -216,7 +226,9 @@
<% } else if (isFillFormDoc) {%>
<td class="contentCells contentCells-icon "></td>
<td class="contentCells contentCells-icon">
<a href="EditorServlet?fileName=<%= URLEncoder.encode(files[i].getName(), "UTF-8") %>&type=mobile&mode=fillForms" target="_blank">
<a href="EditorServlet?fileName=<%= URLEncoder.encode(files[i].getName(), "UTF-8")
.concat(request.getParameter("directUrl") != null ?
"&directUrl=".concat(request.getParameter("directUrl")) : "") %>&type=mobile&mode=fillForms" target="_blank">
<img src="css/img/mobile-fill-forms.svg" alt="Open in editor for filling in forms for mobile devices" title="Open in editor for filling in forms for mobile devices" />
</a>
</td>
@ -224,24 +236,32 @@
<td class="contentCells contentCells-icon "></td>
<td class="contentCells contentCells-icon "></td>
<td class="contentCells contentCells-shift contentCells-icon firstContentCellShift">
<a href="EditorServlet?fileName=<%= URLEncoder.encode(files[i].getName(), "UTF-8") %>&type=desktop&mode=fillForms" target="_blank">
<a href="EditorServlet?fileName=<%= URLEncoder.encode(files[i].getName(), "UTF-8")
.concat(request.getParameter("directUrl") != null ?
"&directUrl=".concat(request.getParameter("directUrl")) : "") %>&type=desktop&mode=fillForms" target="_blank">
<img src="css/img/fill-forms.svg" alt="Open in editor for filling in forms" title="Open in editor for filling in forms"/>
</a>
<% } else { %>
<td class="contentCells contentCells-shift contentCells-icon contentCellsEmpty" colspan="6"></td>
<% } %>
<td class="contentCells contentCells-icon firstContentCellViewers">
<a href="EditorServlet?fileName=<%= URLEncoder.encode(files[i].getName(), "UTF-8") %>&type=desktop&mode=view" target="_blank">
<a href="EditorServlet?fileName=<%= URLEncoder.encode(files[i].getName(), "UTF-8")
.concat(request.getParameter("directUrl") != null ?
"&directUrl=".concat(request.getParameter("directUrl")) : "") %>&type=desktop&mode=view" target="_blank">
<img src="css/img/desktop.svg" alt="Open in viewer for full size screens" title="Open in viewer for full size screens"/>
</a>
</td>
<td class="contentCells contentCells-icon">
<a href="EditorServlet?fileName=<%= URLEncoder.encode(files[i].getName(), "UTF-8") %>&type=mobile&mode=view" target="_blank">
<a href="EditorServlet?fileName=<%= URLEncoder.encode(files[i].getName(), "UTF-8")
.concat(request.getParameter("directUrl") != null ?
"&directUrl=".concat(request.getParameter("directUrl")) : "") %>&type=mobile&mode=view" target="_blank">
<img src="css/img/mobile.svg" alt="Open in viewer for mobile devices" title="Open in viewer for mobile devices"/>
</a>
</td>
<td class="contentCells contentCells-icon contentCells-shift">
<a href="EditorServlet?fileName=<%= URLEncoder.encode(files[i].getName(), "UTF-8") %>&type=embedded&mode=embedded" target="_blank">
<a href="EditorServlet?fileName=<%= URLEncoder.encode(files[i].getName(), "UTF-8")
.concat(request.getParameter("directUrl") != null ?
"&directUrl=".concat(request.getParameter("directUrl")) : "") %>&type=embedded&mode=embedded" target="_blank">
<img src="css/img/embeded.svg" alt="Open in embedded mode" title="Open in embedded mode"/>
</a>
</td>
@ -349,8 +369,19 @@
var UrlConverter = "IndexServlet?type=convert";
var UrlEditor = "EditorServlet";
document.addEventListener('DOMContentLoaded', function(){
document.getElementById("language").value="en";
document.addEventListener('DOMContentLoaded', function() {
var lang = document.cookie
.split('; ')
.find((row) => row.startsWith('ulang='))
?.split('=')[1];
var languages = Array.from(document.getElementById("language").options).map(e => e.value)
if (!languages.includes(lang)) {
lang = "en";
}
document.getElementById("language").value=lang;
});
</script>
</body>

View File

@ -16,11 +16,24 @@
*
*/
var directUrl;
if (typeof jQuery !== "undefined") {
jq = jQuery.noConflict();
directUrl = getUrlVars()["directUrl"] == "true";
mustReload = false;
if (directUrl)
jq("#directUrl").prop("checked", directUrl);
else
directUrl = jq("#directUrl").prop("checked");
jq("#directUrl").change(function() {
window.location = "?directUrl=" + jq(this).prop("checked");
});
jq(function () {
jq("#fileupload").fileupload({
dataType: "json",
@ -218,7 +231,7 @@ if (typeof jQuery !== "undefined") {
jq(document).on("click", "#beginEdit:not(.disable)", function () {
var fileId = encodeURIComponent(jq("#hiddenFileName").val());
var url = UrlEditor + "?mode=edit&fileName=" + fileId;
var url = UrlEditor + "?mode=edit&fileName=" + fileId + "&directUrl=" + directUrl;
window.open(url, "_blank");
jq("#hiddenFileName").val("");
jq.unblockUI();
@ -226,7 +239,7 @@ if (typeof jQuery !== "undefined") {
jq(document).on("click", "#beginView:not(.disable)", function () {
var fileId = encodeURIComponent(jq("#hiddenFileName").val());
var url = UrlEditor + "?mode=view&fileName=" + fileId;
var url = UrlEditor + "?mode=view&fileName=" + fileId + "&directUrl=" + directUrl;
window.open(url, "_blank");
jq("#hiddenFileName").val("");
jq.unblockUI();
@ -234,7 +247,7 @@ if (typeof jQuery !== "undefined") {
jq(document).on("click", "#beginEmbedded:not(.disable)", function () {
var fileId = encodeURIComponent(jq("#hiddenFileName").val());
var url = UrlEditor + "?type=embedded&mode=embedded&fileName=" + fileId;
var url = UrlEditor + "?type=embedded&mode=embedded&fileName=" + fileId + "&directUrl=" + directUrl;
jq("#mainProgress").addClass("embedded");
jq("#beginEmbedded").addClass("disable");
@ -287,6 +300,17 @@ if (typeof jQuery !== "undefined") {
}
};
function getUrlVars() {
var vars = [], hash;
var hashes = window.location.href.slice(window.location.href.indexOf('?') + 1).split('&');
for (var i = 0; i < hashes.length; i++) {
hash = hashes[i].split('=');
vars.push(hash[0]);
vars[hash[0]] = hash[1];
}
return vars;
};
var fileList = jq("tr.tableRow");
var mouseIsOverTooltip = false;
@ -302,7 +326,7 @@ if (typeof jQuery !== "undefined") {
});
}
} else {
jq(".info").mouseover(function (event) {
jq("#info").mouseover(function (event) {
if (fileList.length > 0) {
if (hideTooltipTimeout != null) {
clearTimeout(hideTooltipTimeout);

View File

@ -29,6 +29,7 @@ const config = require('config');
const configServer = config.get('server');
const storageFolder = configServer.get("storageFolder");
const mime = require("mime");
const urlModule = require("url");
const docManager = require("./helpers/docManager");
const documentService = require("./helpers/documentService");
const fileUtility = require("./helpers/fileUtility");
@ -469,6 +470,74 @@ app.get("/csv", function (req, res) { // define a handler for downloading csv f
filestream.pipe(res); // send file information to the response by streams
})
app.post("/reference", function (req, res) { //define a handler for renaming file
req.docManager = new docManager(req, res);
var result = function(data) {
res.writeHead(200, {"Content-Type": "application/json" });
res.write(JSON.stringify(data));
res.end();
};
var referenceData = req.body.referenceData;
if (!!referenceData) {
var portalName = referenceData.portalName;
if (portalName != req.docManager.getServerUrl()) {
result({ "error": "You do not have access to this site" });
return;
}
var fileId = JSON.parse(referenceData.fileId);
var userAddress = fileId.userAddress;
if (userAddress != req.docManager.curUserHostAddress()) {
result({ "error": "You do not have access to this file" });
return;
}
var fileName = fileId.fileName;
if (!req.docManager.existsSync(req.docManager.storagePath(fileName, userAddress))) {
result({ "error": "File is not exist" });
return;
}
} else if (!!req.body.link) {
if (req.body.link.indexOf(req.docManager.curUserHostAddress()) != -1) {
result({ "error": "You do not have access to this site" });
return;
}
var urlObj = urlModule.parse(req.body.link, true);
var fileName = urlObj.query.fileName;
if (!req.docManager.existsSync(req.docManager.storagePath(fileName, userAddress))) {
result({ "error": "File is not exist" });
return;
}
} else if (!!req.body.path) {
var fileName = fileUtility.getFileName(req.body.path);
if (!req.docManager.existsSync(req.docManager.storagePath(fileName, userAddress))) {
result({ "error": "File is not exist" });
return;
}
}
if (!fileName) {
result({ "error": "File is not found" });
return;
}
result({
url: req.docManager.getDownloadUrl(fileName, true),
directUrl: req.docManager.getDownloadUrl(fileName),
referenceData: {
fileId: JSON.stringify({ fileName: fileName, userAddress: req.docManager.curUserHostAddress()}),
portalName: req.docManager.getServerUrl()
},
link: req.docManager.getServerUrl() + "/editor?fileName=" + encodeURIComponent(fileName),
path: fileName,
});
});
app.post("/track", async function (req, res) { // define a handler for tracking file changes
req.docManager = new docManager(req, res);
@ -779,6 +848,19 @@ app.get("/editor", function (req, res) { // define a handler for editing docume
}
}
var referenceData = {
fileId: JSON.stringify({ fileName: fileName, userAddress: req.docManager.curUserHostAddress()}),
portalName: req.docManager.getServerUrl()
};
var type = req.query.type || ""; // type: embedded/mobile/desktop
if (type == "") {
type = new RegExp(configServer.get("mobileRegEx"), "i").test(req.get('User-Agent')) ? "mobile" : "desktop";
} else if (type != "mobile"
&& type != "embedded") {
type = "desktop";
}
var templatesImageUrl = req.docManager.getTemplateImageUrl(fileUtility.getFileType(fileName));
var createUrl = req.docManager.getCreateUrl(fileUtility.getFileType(fileName), userid, type, lang);
var templates = [
@ -820,14 +902,6 @@ app.get("/editor", function (req, res) { // define a handler for editing docume
var directUrl = req.docManager.getDownloadUrl(fileName);
var mode = req.query.mode || "edit"; // mode: view/edit/review/comment/fillForms/embedded
var type = req.query.type || ""; // type: embedded/mobile/desktop
if (type == "") {
type = new RegExp(configServer.get("mobileRegEx"), "i").test(req.get('User-Agent')) ? "mobile" : "desktop";
} else if (type != "mobile"
&& type != "embedded") {
type = "desktop";
}
var canEdit = configServer.get('editedDocs').indexOf(fileExt) != -1; // check if this file can be edited
if ((!canEdit && mode == "edit" || mode == "fillForms") && configServer.get('fillDocs').indexOf(fileExt) != -1) {
mode = "fillForms";
@ -945,7 +1019,8 @@ app.get("/editor", function (req, res) { // define a handler for editing docume
fileChoiceUrl: fileChoiceUrl,
submitForm: submitForm,
plugins: JSON.stringify(plugins),
actionData: actionData
actionData: actionData,
referenceData: userid != "uid-0" ? referenceData : null
},
history: history,
historyData: historyData,

View File

@ -1,5 +1,5 @@
{
"version": "1.3.0",
"version": "1.4.0",
"log": {
"appenders": [
{

View File

@ -22,6 +22,7 @@
"commentGroups": <%- editor.commentGroups %>,
"userInfoGroups": <%- editor.userInfoGroups %>
},
"referenceData": <%- JSON.stringify(editor.referenceData) %>,
"title": "<%- file.name %>",
"url": "<%- file.uri %>"
},

View File

@ -151,6 +151,20 @@
innerAlert("onRequestSendNotify: " + data);
};
var onRequestReferenceData = function(event) { // user refresh external data source
innerAlert("onRequestReferenceData");
innerAlert(event.data);
let xhr = new XMLHttpRequest();
xhr.open("POST", "reference");
xhr.setRequestHeader("Content-Type", "application/json");
xhr.send(JSON.stringify(event.data));
xhr.onload = function () {
innerAlert(xhr.responseText);
docEditor.setReferenceData(JSON.parse(xhr.responseText));
}
};
var onRequestSaveAs = function (event) { // the user is trying to save file by clicking Save Copy as... button
var title = event.data.title;
var url = event.data.url;
@ -209,6 +223,7 @@
config.events.onRequestRename = onRequestRename;
config.events.onRequestUsers = onRequestUsers;
config.events.onRequestSendNotify = onRequestSendNotify;
config.events.onRequestReferenceData = onRequestReferenceData;
}
if (config.editorConfig.createUrl) {

View File

@ -1,6 +1,6 @@
<?php
$GLOBALS['version'] = "1.3.0";
$GLOBALS['version'] = "1.4.0";
$GLOBALS['FILE_SIZE_MAX'] = 5242880;
$GLOBALS['STORAGE_PATH'] = "";

View File

@ -166,7 +166,7 @@ label .checkbox {
background-image: url("images/file_docxf.svg");
}
.create-sample {
.side-option {
color: #666666;
line-height: 24px;
}

View File

@ -26,6 +26,7 @@
$filename;
$user = getUser($_GET["user"]);
$isEnableDirectUrl = $_GET["directUrl"] != null ? filter_var($_GET["directUrl"], FILTER_VALIDATE_BOOLEAN) : false;
// get the file url and upload it
$externalUrl = $_GET["fileUrl"];
@ -90,7 +91,7 @@
"document" => [
"title" => $filename,
"url" => getDownloadUrl($filename),
"directUrl" => $directUrl,
"directUrl" => $isEnableDirectUrl ? $directUrl : "",
"fileType" => $filetype,
"key" => $docKey,
"info" => [
@ -150,24 +151,33 @@
];
// an image for inserting
$dataInsertImage = [
$dataInsertImage = $isEnableDirectUrl ? [
"fileType" => "png",
"url" => serverPath(true) . "/css/images/logo.png",
"directUrl" => serverPath(false) . "/css/images/logo.png"
] : [
"fileType" => "png",
"url" => serverPath(true) . "/css/images/logo.png"
];
// a document for comparing
$dataCompareFile = [
$dataCompareFile = $isEnableDirectUrl ? [
"fileType" => "docx",
"url" => serverPath(true) . "/webeditor-ajax.php?type=assets&name=sample.docx",
"directUrl" => serverPath(false) . "/webeditor-ajax.php?type=assets&name=sample.docx"
] : [
"fileType" => "docx",
"url" => serverPath(true) . "/webeditor-ajax.php?type=assets&name=sample.docx"
];
// recipients data for mail merging
$dataMailMergeRecipients = [
$dataMailMergeRecipients = $isEnableDirectUrl ? [
"fileType" =>"csv",
"url" => serverPath(true) . "/webeditor-ajax.php?type=csv",
"directUrl" => serverPath(false) . "/webeditor-ajax.php?type=csv"
] : [
"fileType" =>"csv",
"url" => serverPath(true) . "/webeditor-ajax.php?type=csv"
];
// users data for mentions
@ -240,7 +250,7 @@
}
// get document history
function getHistory($filename, $filetype, $docKey, $fileuri) {
function getHistory($filename, $filetype, $docKey, $fileuri, $isEnableDirectUrl) {
$storagePath = $GLOBALS['STORAGE_PATH'];
$histDir = getHistoryDir(getStoragePath($filename)); // get the path to the file history
@ -282,11 +292,15 @@
$prevFileUrl = $i == $curVer ? $fileuri : getHistoryDownloadUrl($filename, $i, "prev.".$fileExe);
if (realpath($storagePath) === $storagePath) {
$prevFileUrl = $i == $curVer ? getDownloadUrl($filename) : getHistoryDownloadUrl($filename, $i, "prev.".$fileExe);
$directUrl = $i == $curVer ? getDownloadUrl($filename, FALSE) : getHistoryDownloadUrl($filename, $i, "prev.".$fileExe, FALSE);
if ($isEnableDirectUrl) {
$directUrl = $i == $curVer ? getDownloadUrl($filename, FALSE) : getHistoryDownloadUrl($filename, $i, "prev.".$fileExe, FALSE);
}
}
$dataObj["url"] = $prevFileUrl; // write file url to the data object
$dataObj["directUrl"] = $directUrl; // write direct url to the data object
if ($isEnableDirectUrl) {
$dataObj["directUrl"] = $directUrl; // write direct url to the data object
}
$dataObj["version"] = $i;
if ($i > 1) { // check if the version number is greater than 1 (the document was modified)
@ -299,11 +313,15 @@
$obj["user"] = $change ? $change["user"] : null;
$prev = $histData[$i - 2]; // get the history data from the previous file version
$dataObj["previous"] = [ // write information about previous file version to the data object
$dataObj["previous"] = $isEnableDirectUrl ? [ // write information about previous file version to the data object
"fileType" => $prev["fileType"],
"key" => $prev["key"],
"url" => $prev["url"],
"directUrl" => $prev["directUrl"]
] : [
"fileType" => $prev["fileType"],
"key" => $prev["key"],
"url" => $prev["url"]
];
// write the path to the diff.zip archive with differences in this file version
@ -529,7 +547,7 @@
};
<?php
$out = getHistory($filename, $filetype, $docKey, $fileuri);
$out = getHistory($filename, $filetype, $docKey, $fileuri, $isEnableDirectUrl);
$history = $out[0];
$historyData = $out[1];
?>

View File

@ -23,6 +23,7 @@
require_once( dirname(__FILE__) . '/users.php' );
$user = $_GET["user"];
$directUrlArg = $_GET["directUrl"] != null ? "&directUrl=" . $_GET["directUrl"] : "";
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
@ -73,7 +74,7 @@
<a class="try-editor form reload-page" target="_blank" href="doceditor.php?fileExt=docxf&user=<?php echo htmlentities($user); ?>">Form template</a>
</li>
</ul>
<label class="create-sample">
<label class="side-option">
<input type="checkbox" id="createSample" class="checkbox" />With sample content
</label>
</div>
@ -87,7 +88,7 @@
<tr>
<td valign="middle">
<span class="select-user">Username</span>
<img class="info" src="css/images/info.svg" />
<img id="info" src="css/images/info.svg" />
<select class="select-user" id="user">
<?php foreach(getAllUsers() as $user_l) {
$name = $user_l->name ? $user_l->name : "Anonymous";
@ -106,6 +107,14 @@
</select>
</td>
</tr>
<tr>
<td valign="middle">
<label class="side-option">
<input id="directUrl" type="checkbox" class="checkbox" />Try opening on client
<img id="directUrlInfo" class="info info-tooltip" data-id="directUrlInfo" data-tooltip="Some files can be opened in the user's browser without connecting to the document server." src="css/images/info.svg" />
</label>
</td>
</tr>
</table>
</div>
</div>
@ -159,37 +168,37 @@
<?php foreach ($storedFiles as &$storeFile) {
echo '<tr class="tableRow" title="'.$storeFile->name.' ['.getFileVersion(getHistoryDir(getStoragePath($storeFile->name))).']">';
echo ' <td class="contentCells">';
echo ' <a class="stored-edit '.$storeFile->documentType.'" href="doceditor.php?fileID='.urlencode($storeFile->name).'&user='.htmlentities($user).'" target="_blank">';
echo ' <a class="stored-edit '.$storeFile->documentType.'" href="doceditor.php?fileID='.urlencode($storeFile->name).'&user='.htmlentities($user) . $directUrlArg .'" target="_blank">';
echo ' <span>'.$storeFile->name.'</span>';
echo ' </a>';
echo ' </td>';
if ($storeFile->canEdit) {
echo ' <td class="contentCells contentCells-icon">';
echo ' <a href="doceditor.php?fileID=' . urlencode($storeFile->name) . '&user=' . htmlentities($user) . '&action=edit&type=desktop" target="_blank">';
echo ' <a href="doceditor.php?fileID=' . urlencode($storeFile->name) . '&user=' . htmlentities($user) . $directUrlArg . '&action=edit&type=desktop" target="_blank">';
echo ' <img src="css/images/desktop.svg" alt="Open in editor for full size screens" title="Open in editor for full size screens" /></a>';
echo ' </td>';
echo ' <td class="contentCells contentCells-icon">';
echo ' <a href="doceditor.php?fileID=' . urlencode($storeFile->name) . '&user=' . htmlentities($user) . '&action=edit&type=mobile" target="_blank">';
echo ' <a href="doceditor.php?fileID=' . urlencode($storeFile->name) . '&user=' . htmlentities($user) . $directUrlArg . '&action=edit&type=mobile" target="_blank">';
echo ' <img src="css/images/mobile.svg" alt="Open in editor for mobile devices" title="Open in editor for mobile devices" /></a>';
echo ' </td>';
echo ' <td class="contentCells contentCells-icon">';
echo ' <a href="doceditor.php?fileID=' . urlencode($storeFile->name) . '&user=' . htmlentities($user) . '&action=comment&type=desktop" target="_blank">';
echo ' <a href="doceditor.php?fileID=' . urlencode($storeFile->name) . '&user=' . htmlentities($user) . $directUrlArg . '&action=comment&type=desktop" target="_blank">';
echo ' <img src="css/images/comment.svg" alt="Open in editor for comment" title="Open in editor for comment" /></a>';
echo ' </td>';
if ($storeFile->documentType == "word") {
echo ' <td class="contentCells contentCells-icon">';
echo ' <a href="doceditor.php?fileID=' . urlencode($storeFile->name) . '&user=' . htmlentities($user) . '&action=review&type=desktop" target="_blank">';
echo ' <a href="doceditor.php?fileID=' . urlencode($storeFile->name) . '&user=' . htmlentities($user) . $directUrlArg . '&action=review&type=desktop" target="_blank">';
echo ' <img src="css/images/review.svg" alt="Open in editor for review" title="Open in editor for review" /></a>';
echo ' </td>';
} else if ($storeFile->documentType == "cell") {
echo ' <td class="contentCells contentCells-icon">';
echo ' <a href="doceditor.php?fileID=' . urlencode($storeFile->name) . '&user=' . htmlentities($user) . '&action=filter&type=desktop" target="_blank">';
echo ' <a href="doceditor.php?fileID=' . urlencode($storeFile->name) . '&user=' . htmlentities($user) . $directUrlArg . '&action=filter&type=desktop" target="_blank">';
echo ' <img src="css/images/filter.svg" alt="Open in editor without access to change the filter" title="Open in editor without access to change the filter" /></a>';
echo ' </td>';
}
if ($storeFile->documentType == "word") {
echo ' <td class="contentCells contentCells-icon ">';
echo ' <a href="doceditor.php?fileID=' . urlencode($storeFile->name) . '&user=' . htmlentities($user) . '&action=blockcontent&type=desktop" target="_blank">';
echo ' <a href="doceditor.php?fileID=' . urlencode($storeFile->name) . '&user=' . htmlentities($user) . $directUrlArg . '&action=blockcontent&type=desktop" target="_blank">';
echo ' <img src="css/images/block-content.svg" alt="Open in editor without content control modification" title="Open in editor without content control modification" /></a>';
echo ' </td>';
} else{
@ -200,7 +209,7 @@
}
if ($storeFile->isFillFormDoc) {
echo ' <td class="contentCells contentCells-shift contentCells-icon firstContentCellShift">';
echo ' <a href="doceditor.php?fileID=' . urlencode($storeFile->name) . '&user=' . htmlentities($user) . '&action=fillForms&type=desktop" target="_blank">';
echo ' <a href="doceditor.php?fileID=' . urlencode($storeFile->name) . '&user=' . htmlentities($user) . $directUrlArg . '&action=fillForms&type=desktop" target="_blank">';
echo ' <img src="css/images/fill-forms.svg" alt="Open in editor for filling in forms" title="Open in editor for filling in forms" /></a>';
echo ' </td>';
} else {
@ -209,29 +218,29 @@
} else if ($storeFile->isFillFormDoc) {
echo ' <td class="contentCells contentCells-icon"></td>';
echo ' <td class="contentCells contentCells-icon">';
echo ' <a href="doceditor.php?fileID=' . urlencode($storeFile->name) . '&user=' . htmlentities($user) . '&action=fillForms&type=desktop" target="_blank">';
echo ' <a href="doceditor.php?fileID=' . urlencode($storeFile->name) . '&user=' . htmlentities($user) . $directUrlArg . '&action=fillForms&type=desktop" target="_blank">';
echo ' <img src="css/images/mobile-fill-forms.svg" alt="Open in editor for filling in forms for mobile devices" title="Open in editor for filling in forms for mobile devices" /></a>';
echo ' </td>';
echo ' <td class="contentCells contentCells-icon"></td>';
echo ' <td class="contentCells contentCells-icon"></td>';
echo ' <td class="contentCells contentCells-icon"></td>';
echo ' <td class="contentCells contentCells-shift contentCells-icon firstContentCellShift">';
echo ' <a href="doceditor.php?fileID=' . urlencode($storeFile->name) . '&user=' . htmlentities($user) . '&action=fillForms&type=desktop" target="_blank">';
echo ' <a href="doceditor.php?fileID=' . urlencode($storeFile->name) . '&user=' . htmlentities($user) . $directUrlArg . '&action=fillForms&type=desktop" target="_blank">';
echo ' <img src="css/images/fill-forms.svg" alt="Open in editor for filling in forms" title="Open in editor for filling in forms" /></a>';
echo ' </td>';
} else {
echo '<td class="contentCells contentCells-shift contentCells-icon contentCellsEmpty" colspan="6"></td>';
}
echo ' <td class="contentCells contentCells-icon firstContentCellViewers">';
echo ' <a href="doceditor.php?fileID='.urlencode($storeFile->name).'&user='.htmlentities($user).'&action=view&type=desktop" target="_blank">';
echo ' <a href="doceditor.php?fileID='.urlencode($storeFile->name).'&user='.htmlentities($user) . $directUrlArg . '&action=view&type=desktop" target="_blank">';
echo ' <img src="css/images/desktop.svg" alt="Open in viewer for full size screens" title="Open in viewer for full size screens" /></a>';
echo ' </td>';
echo ' <td class="contentCells contentCells-icon">';
echo ' <a href="doceditor.php?fileID='.urlencode($storeFile->name).'&user='.htmlentities($user).'&action=view&type=mobile" target="_blank">';
echo ' <a href="doceditor.php?fileID='.urlencode($storeFile->name).'&user='.htmlentities($user) . $directUrlArg . '&action=view&type=mobile" target="_blank">';
echo ' <img src="css/images/mobile.svg" alt="Open in viewer for mobile devices" title="Open in viewer for mobile devices" /></a>';
echo ' </td>';
echo ' <td class="contentCells contentCells-icon contentCells-shift">';
echo ' <a href="doceditor.php?fileID='.urlencode($storeFile->name).'&user='.htmlentities($user).'&action=embedded&type=embedded" target="_blank">';
echo ' <a href="doceditor.php?fileID='.urlencode($storeFile->name).'&user='.htmlentities($user) . $directUrlArg . '&action=embedded&type=embedded" target="_blank">';
echo ' <img src="css/images/embeded.svg" alt="Open in embedded mode" title="Open in embedded mode" /></a>';
echo ' </td>';
echo ' <td class="contentCells contentCells-icon contentCells-shift downloadContentCellShift">';

View File

@ -16,11 +16,24 @@
*
*/
var directUrl;
if (typeof jQuery != "undefined") {
jq = jQuery.noConflict();
directUrl = getUrlVars()["directUrl"] == "true";
mustReload = false;
if (directUrl)
jq("#directUrl").prop("checked", directUrl);
else
directUrl = jq("#directUrl").prop("checked");
jq("#directUrl").change(function() {
window.location = "?directUrl=" + jq(this).prop("checked");
});
user = getUrlVars()["user"];
if ("" != user && undefined != user)
jq("#user").val(user);
@ -234,7 +247,7 @@ if (typeof jQuery != "undefined") {
jq(document).on("click", "#beginEdit:not(.disable)", function () {
var fileId = encodeURIComponent(jq('#hiddenFileName').val());
var url = "doceditor.php?fileID=" + fileId + "&user=" + user;
var url = "doceditor.php?fileID=" + fileId + "&user=" + user + "&directUrl=" + directUrl;
window.open(url, "_blank");
jq('#hiddenFileName').val("");
jq.unblockUI();
@ -243,7 +256,7 @@ if (typeof jQuery != "undefined") {
jq(document).on("click", "#beginView:not(.disable)", function () {
var fileId = encodeURIComponent(jq('#hiddenFileName').val());
var url = "doceditor.php?action=view&fileID=" + fileId + "&user=" + user;
var url = "doceditor.php?action=view&fileID=" + fileId + "&user=" + user + "&directUrl=" + directUrl;
window.open(url, "_blank");
jq('#hiddenFileName').val("");
jq.unblockUI();
@ -252,7 +265,7 @@ if (typeof jQuery != "undefined") {
jq(document).on("click", "#beginEmbedded:not(.disable)", function () {
var fileId = encodeURIComponent(jq('#hiddenFileName').val());
var url = "doceditor.php?type=embedded&fileID=" + fileId + "&user=" + user;
var url = "doceditor.php?type=embedded&fileID=" + fileId + "&user=" + user + "&directUrl=" + directUrl;
jq("#mainProgress").addClass("embedded");
jq("#beginEmbedded").addClass("disable");

View File

@ -115,7 +115,8 @@ function processSave($data, $fileName, $userAddress) {
$saved = 1;
if (!(($new_data = file_get_contents($downloadUri)) === FALSE)) {
if (!(($new_data = file_get_contents($downloadUri, false,
stream_context_create(["http"=>["timeout"=>5]]))) === FALSE)) {
$storagePath = getStoragePath($newFileName, $userAddress); // get the file path
$histDir = getHistoryDir($storagePath); // get the path to the history direction
$verDir = getVersionDir($histDir, getFileVersion($histDir)); // get the path to the file version
@ -125,7 +126,8 @@ function processSave($data, $fileName, $userAddress) {
rename(getStoragePath($fileName, $userAddress), $verDir . DIRECTORY_SEPARATOR . "prev" . $curExt); // get the path to the previous file version and rename the storage path with it
file_put_contents($storagePath, $new_data, LOCK_EX); // save file to the storage directory
if ($changesData = file_get_contents($data->changesurl)) {
if ($changesData = file_get_contents($data->changesurl, false,
stream_context_create(["http"=>["timeout"=>5]]))) {
file_put_contents($verDir . DIRECTORY_SEPARATOR . "diff.zip", $changesData, LOCK_EX); // save file changes to the diff.zip archive
}
@ -190,7 +192,8 @@ function processForceSave($data, $fileName, $userAddress) {
$saved = 1;
if (!(($new_data = file_get_contents($downloadUri)) === FALSE)) {
if (!(($new_data = file_get_contents($downloadUri, false,
stream_context_create(["http"=>["timeout"=>5]]))) === FALSE)) {
$baseNameWithoutExt = substr($fileName, 0, strlen($fileName) - strlen($curExt));
$isSubmitForm = $data->forcesavetype == 3; // SubmitForm

View File

@ -1,6 +1,6 @@
import os
VERSION = '1.3.0'
VERSION = '1.4.0'
FILE_SIZE_MAX = 5242880
STORAGE_PATH = 'app_data'

View File

@ -35,7 +35,7 @@ See the detailed guide to learn how to install Document Server [for Windows](htt
```
pip install Django==3.1.3
pip install requests==2.25.0
pip install pyjwt==2.3.0
pip install pyjwt==2.6.0
pip install python-magic
```

View File

@ -211,7 +211,9 @@ def createFile(stream, path, req = None, meta = False):
# create file response
def createFileResponse(response, path, req, meta):
response.raise_for_status()
status_code = response.status_code
if status_code != 200: # checking status code
raise RuntimeError('Document editing service returned status: %s' % status_code)
with open(path, 'wb') as file:
for chunk in response.iter_content(chunk_size=8192):
file.write(chunk)
@ -219,7 +221,7 @@ def createFileResponse(response, path, req, meta):
# save file from the given url
def saveFileFromUri(uri, path, req = None, meta = False):
resp = requests.get(uri, stream=True, verify = config.DOC_SERV_VERIFY_PEER)
resp = requests.get(uri, stream=True, verify = config.DOC_SERV_VERIFY_PEER, timeout=5)
createFileResponse(resp, path, req, meta)
return

View File

@ -152,7 +152,7 @@ def getMeta(storagePath):
return None
# get the document history of a given file
def getHistoryObject(storagePath, filename, docKey, docUrl, req):
def getHistoryObject(storagePath, filename, docKey, docUrl, isEnableDirectUrl, req):
histDir = getHistoryDir(storagePath)
version = getFileVersion(histDir)
if version > 0: # if the file was modified (the file version is greater than 0)
@ -184,7 +184,8 @@ def getHistoryObject(storagePath, filename, docKey, docUrl, req):
}
dataObj['url'] = docUrl if i == version else getPublicHistUri(filename, i, "prev" + fileUtils.getFileExt(filename), req) # write file url to the data object
dataObj['directUrl'] = docManager.getDownloadUrl(filename, req, False) if i == version else getPublicHistUri(filename, i, "prev" + fileUtils.getFileExt(filename), req, False) # write file direct url to the data object
if isEnableDirectUrl:
dataObj['directUrl'] = docManager.getDownloadUrl(filename, req, False) if i == version else getPublicHistUri(filename, i, "prev" + fileUtils.getFileExt(filename), req, False) # write file direct url to the data object
if i > 1: # check if the version number is greater than 1 (the file was modified)
changes = json.loads(readFile(getChangesHistoryPath(prevVerDir))) # get the path to the changes.json file
@ -201,6 +202,10 @@ def getHistoryObject(storagePath, filename, docKey, docUrl, req):
'key': prev['key'],
'url': prev['url'],
'directUrl': prev['directUrl']
} if isEnableDirectUrl else { # write key and url information about previous file version
'fileType': prev['fileType'],
'key': prev['key'],
'url': prev['url']
}
dataObj['previous'] = prevInfo # write information about previous file version to the data object
dataObj['changesUrl'] = getPublicHistUri(filename, i - 1, "diff.zip", req) # write the path to the diff.zip archive with differences in this file version

View File

@ -58,7 +58,10 @@ def getConverterUri(docUri, fromExt, toExt, docKey, isAsync, filePass = None, la
payload['token'] = jwtManager.encode(payload) # encode a payload object into a body token
headers[jwtHeader] = f'Bearer {headerToken}' # add a header Authorization with a header token with Authorization prefix in it
response = requests.post(config.DOC_SERV_SITE_URL + config.DOC_SERV_CONVERTER_URL, json=payload, headers=headers, verify = config.DOC_SERV_VERIFY_PEER) # send the headers and body values to the converter and write the result to the response
response = requests.post(config.DOC_SERV_SITE_URL + config.DOC_SERV_CONVERTER_URL, json=payload, headers=headers, verify = config.DOC_SERV_VERIFY_PEER, timeout=5) # send the headers and body values to the converter and write the result to the response
status_code = response.status_code
if status_code != 200: # checking status code
raise RuntimeError('Convertation service returned status: %s' % status_code)
json = response.json()
return getResponseUri(json)

View File

@ -171,6 +171,7 @@ def rename(request):
# edit a file
def edit(request):
filename = fileUtils.getFileName(request.GET['filename'])
isEnableDirectUrl = request.GET['directUrl'].lower() in ("true") if 'directUrl' in request.GET else False
ext = fileUtils.getFileExt(filename)
@ -234,7 +235,7 @@ def edit(request):
'document': {
'title': filename,
'url': docManager.getDownloadUrl(filename, request),
'directUrl': directUrl,
'directUrl': directUrl if isEnableDirectUrl else "",
'fileType': ext[1:],
'key': docKey,
'info': infObj,
@ -295,6 +296,9 @@ def edit(request):
'fileType': 'png',
'url': docManager.getServerUrl(True, request) + 'static/images/logo.png',
'directUrl': docManager.getServerUrl(False, request) + 'static/images/logo.png'
} if isEnableDirectUrl else {
'fileType': 'png',
'url': docManager.getServerUrl(True, request) + 'static/images/logo.png'
}
# a document which will be compared with the current document
@ -302,6 +306,9 @@ def edit(request):
'fileType': 'docx',
'url': docManager.getServerUrl(True, request) + 'static/sample.docx',
'directUrl': docManager.getServerUrl(False, request) + 'static/sample.docx'
} if isEnableDirectUrl else {
'fileType': 'docx',
'url': docManager.getServerUrl(True, request) + 'static/sample.docx'
}
# recipient data for mail merging
@ -309,6 +316,9 @@ def edit(request):
'fileType': 'csv',
'url': docManager.getServerUrl(True, request) + 'csv',
'directUrl': docManager.getServerUrl(False, request) + 'csv'
} if isEnableDirectUrl else {
'fileType': 'csv',
'url': docManager.getServerUrl(True, request) + 'csv'
}
# users data for mentions
@ -320,7 +330,7 @@ def edit(request):
dataCompareFile['token'] = jwtManager.encode(dataCompareFile) # encode the dataCompareFile object into a token
dataMailMergeRecipients['token'] = jwtManager.encode(dataMailMergeRecipients) # encode the dataMailMergeRecipients object into a token
hist = historyManager.getHistoryObject(storagePath, filename, docKey, fileUri, request) # get the document history
hist = historyManager.getHistoryObject(storagePath, filename, docKey, fileUri, isEnableDirectUrl, request) # get the document history
context = { # the data that will be passed to the template
'cfg': json.dumps(edConfig), # the document config in json format
@ -358,8 +368,8 @@ def track(request):
trackManager.processForceSave(body, filename, usAddr)
except Exception as e:
response.setdefault('error', 1) # set the default error value as 1 (document key is missing or no document with such key could be found)
response.setdefault('message', e.args[0])
response.setdefault("error", 1) # set the default error value as 1 (document key is missing or no document with such key could be found)
response.setdefault("message", str(e.args[0]))
response.setdefault('error', 0) # if no exceptions are raised, the default error value is 0 (no errors)
# the response status is 200 if the changes are saved successfully; otherwise, it is equal to 500

View File

@ -24,6 +24,8 @@
"""
import re
import sys
import config
import json
@ -32,6 +34,12 @@ from django.shortcuts import render
from src.utils import users
from src.utils import docManager
def getDirectUrlParam(request):
if ('directUrl' in request.GET):
return request.GET['directUrl'].lower() in ("true")
else:
return False;
def default(request): # default parameters that will be passed to the template
context = {
'users': users.USERS,
@ -40,6 +48,7 @@ def default(request): # default parameters that will be passed to the template
'editExt': json.dumps(config.DOC_SERV_EDITED), # file extensions that can be edited
'convExt': json.dumps(config.DOC_SERV_CONVERT), # file extensions that can be converted
'files': docManager.getStoredFiles(request), # information about stored files
'fillExt': json.dumps(config.DOC_SERV_FILLFORMS)
'fillExt': json.dumps(config.DOC_SERV_FILLFORMS),
'directUrl': str(getDirectUrlParam(request)).lower
}
return render(request, 'index.html', context) # execute the "index.html" template with context data and return http response in json format

View File

@ -175,7 +175,7 @@ label .checkbox {
background-image: url("../images/file_docxf.svg");
}
.create-sample {
.side-option {
color: #666666;
line-height: 24px;
}

View File

@ -24,11 +24,24 @@
*
*/
var directUrl;
if (typeof jQuery !== "undefined") {
jq = jQuery.noConflict();
directUrl = getUrlVars()["directUrl"] == "true";
mustReload = false;
if (directUrl)
jq("#directUrl").prop("checked", directUrl);
else
directUrl = jq("#directUrl").prop("checked");
jq("#directUrl").change(function() {
window.location = "?directUrl=" + jq(this).prop("checked");
});
jq(function () {
jq("#fileupload").fileupload({
dataType: "json",
@ -226,7 +239,7 @@ if (typeof jQuery !== "undefined") {
jq(document).on("click", "#beginEdit:not(.disable)", function () {
var fileId = encodeURIComponent(jq("#hiddenFileName").val());
var url = UrlEditor + "?mode=edit&filename=" + fileId;
var url = UrlEditor + "?mode=edit&filename=" + fileId+ "&directUrl=" + directUrl;
window.open(url, "_blank");
jq("#hiddenFileName").val("");
jq.unblockUI();
@ -234,7 +247,7 @@ if (typeof jQuery !== "undefined") {
jq(document).on("click", "#beginView:not(.disable)", function () {
var fileId = encodeURIComponent(jq("#hiddenFileName").val());
var url = UrlEditor + "?mode=view&filename=" + fileId;
var url = UrlEditor + "?mode=view&filename=" + fileId+ "&directUrl=" + directUrl;
window.open(url, "_blank");
jq("#hiddenFileName").val("");
jq.unblockUI();
@ -242,7 +255,7 @@ if (typeof jQuery !== "undefined") {
jq(document).on("click", "#beginEmbedded:not(.disable)", function () {
var fileId = encodeURIComponent(jq("#hiddenFileName").val());
var url = UrlEditor + "?type=embedded&mode=embedded&filename=" + fileId;
var url = UrlEditor + "?type=embedded&mode=embedded&filename=" + fileId + "&directUrl=" + directUrl;
jq("#mainProgress").addClass("embedded");
jq("#beginEmbedded").addClass("disable");
@ -309,7 +322,7 @@ if (typeof jQuery !== "undefined") {
});
}
} else {
jq(".info").mouseover(function (event) {
jq("#info").mouseover(function (event) {
if (fileList.length > 0) {
if (hideTooltipTimeout != null) {
clearTimeout(hideTooltipTimeout);
@ -333,4 +346,15 @@ if (typeof jQuery !== "undefined") {
}, 500);
});
}
function getUrlVars() {
var vars = [], hash;
var hashes = window.location.href.slice(window.location.href.indexOf('?') + 1).split('&');
for (var i = 0; i < hashes.length; i++) {
hash = hashes[i].split('=');
vars.push(hash[0]);
vars[hash[0]] = hash[1];
}
return vars;
};
}

View File

@ -71,7 +71,7 @@
<a class="try-editor form reload-page" target="_blank" data-type="docxf">Form template</a>
</li>
</ul>
<label class="create-sample">
<label class="side-option">
<input type="checkbox" id="createSample" class="checkbox" />With sample content
</label>
</div>
@ -86,7 +86,7 @@
<tr>
<td valign="middle">
<span class="select-user">Username</span>
<img class="info" src="{% static "images/info.svg" %}" />
<img id="info" src="{% static "images/info.svg" %}" />
<select class="select-user" id="user">
{% for user in users %}
<option value="{{ user.id }}">{% if user.name %} {{ user.name }} {% else %} Anonymous {% endif %} </option>
@ -104,6 +104,14 @@
</select>
</td>
</tr>
<tr>
<td valign="middle">
<label class="side-option">
<input id="directUrl" type="checkbox" class="checkbox" />Try opening on client
<img id="directUrlInfo" class="info info-tooltip" data-id="directUrlInfo" data-tooltip="Some files can be opened in the user's browser without connecting to the document server." src="{% static "images/info.svg" %}" />
</label>
</td>
</tr>
</table>
</div>
</div>
@ -153,42 +161,42 @@
{% for file in files %}
<tr class="tableRow" title="{{ file.title }} [{{file.version}}]">
<td class="contentCells">
<a class="stored-edit {{ file.type }}" href="edit?filename={{ file.title }}" target="_blank">
<a class="stored-edit {{ file.type }}" href="edit?filename={{ file.title }}&directUrl={{ directUrl }}" target="_blank">
<span>{{ file.title }}</span>
</a>
</td>
{% if file.canEdit %}
<td class="contentCells contentCells-icon">
<a href="edit?filename={{ file.title }}&type=desktop&mode=edit" target="_blank">
<a href="edit?filename={{ file.title }}&type=desktop&mode=edit&directUrl={{ directUrl }}" target="_blank">
<img src="{% static "images/desktop.svg" %}" alt="Open in editor for full size screens" title="Open in editor for full size screens"/>
</a>
</td>
<td class="contentCells contentCells-icon">
<a href="edit?filename={{ file.title }}&type=mobile&mode=edit" target="_blank">
<a href="edit?filename={{ file.title }}&type=mobile&mode=edit&directUrl={{ directUrl }}" target="_blank">
<img src="{% static "images/mobile.svg" %}" alt="Open in editor for mobile devices" title="Open in editor for mobile devices"/>
</a>
</td>
<td class="contentCells contentCells-icon">
<a href="edit?filename={{ file.title }}&type=desktop&mode=comment" target="_blank">
<a href="edit?filename={{ file.title }}&type=desktop&mode=comment&directUrl={{ directUrl }}" target="_blank">
<img src="{% static "images/comment.svg" %}" alt="Open in editor for comment" title="Open in editor for comment"/>
</a>
</td>
{% if file.type == 'word' %}
<td class="contentCells contentCells-icon">
<a href="edit?filename={{ file.title }}&type=desktop&mode=review" target="_blank">
<a href="edit?filename={{ file.title }}&type=desktop&mode=review&directUrl={{ directUrl }}" target="_blank">
<img src="{% static "images/review.svg" %}" alt="Open in editor for review" title="Open in editor for review"/>
</a>
</td>
{% elif file.type == 'cell' %}
<td class="contentCells contentCells-icon">
<a href="edit?filename={{ file.title }}&type=desktop&mode=filter" target="_blank">
<a href="edit?filename={{ file.title }}&type=desktop&mode=filter&directUrl={{ directUrl }}" target="_blank">
<img src="{% static "images/filter.svg" %}" alt="Open in editor without access to change the filter" title="Open in editor without access to change the filter" />
</a>
</td>
{% endif %}
{% if file.type == 'word' %}
<td class="contentCells contentCells-icon">
<a href="edit?filename={{ file.title }}&type=desktop&mode=blockcontent" target="_blank">
<a href="edit?filename={{ file.title }}&type=desktop&mode=blockcontent&directUrl={{ directUrl }}" target="_blank">
<img src="{% static "images/block-content.svg" %}" alt="Open in editor without content control modification" title="Open in editor without content control modification"/>
</a>
</td>
@ -200,7 +208,7 @@
{% endif %}
{% if file.isFillFormDoc %}
<td class="contentCells contentCells-shift contentCells-icon firstContentCellShift">
<a href="edit?filename={{ file.title }}&type=desktop&mode=fillForms" target="_blank">
<a href="edit?filename={{ file.title }}&type=desktop&mode=fillForms&directUrl={{ directUrl }}" target="_blank">
<img src="{% static "images/fill-forms.svg" %}" alt="Open in editor for filling in forms" title="Open in editor for filling in forms"/>
</a>
</td>
@ -210,7 +218,7 @@
{% elif file.isFillFormDoc %}
<td class="contentCells contentCells-icon"></td>
<td class="contentCells contentCells-icon">
<a href="edit?filename={{ file.title }}&type=mobile&mode=fillForms" target="_blank">
<a href="edit?filename={{ file.title }}&type=mobile&mode=fillForms&directUrl={{ directUrl }}" target="_blank">
<img src="{% static "images/mobile-fill-forms.svg" %}" alt="Open in editor for filling in forms for mobile devices" title="Open in editor for filling in forms for mobile devices"/>
</a>
</td>
@ -218,7 +226,7 @@
<td class="contentCells contentCells-icon"></td>
<td class="contentCells contentCells-icon"></td>
<td class="contentCells contentCells-icon">
<a href="edit?filename={{ file.title }}&type=desktop&mode=fillForms" target="_blank">
<a href="edit?filename={{ file.title }}&type=desktop&mode=fillForms&directUrl={{ directUrl }}" target="_blank">
<img src="{% static "images/fill-forms.svg" %}" alt="Open in editor for filling in forms" title="Open in editor for filling in forms"/>
</a>
</td>
@ -226,17 +234,17 @@
<td class="contentCells contentCells-shift contentCells-icon contentCellsEmpty" colspan="6"></td>
{% endif %}
<td class="contentCells contentCells-icon firstContentCellViewers">
<a href="edit?filename={{ file.title }}&type=desktop&mode=view" target="_blank">
<a href="edit?filename={{ file.title }}&type=desktop&mode=view&directUrl={{ directUrl }}" target="_blank">
<img src="{% static "images/desktop.svg" %}" alt="Open in viewer for full size screens" title="Open in viewer for full size screens"/>
</a>
</td>
<td class="contentCells contentCells-icon">
<a href="edit?filename={{ file.title }}&type=mobile&mode=view" target="_blank">
<a href="edit?filename={{ file.title }}&type=mobile&mode=view&directUrl={{ directUrl }}" target="_blank">
<img src="{% static "images/mobile.svg" %}" alt="Open in viewer for mobile devices" title="Open in viewer for mobile devices"/>
</a>
</td>
<td class="contentCells contentCells-icon contentCells-shift">
<a href="edit?filename={{ file.title }}&type=embedded&mode=embedded" target="_blank">
<a href="edit?filename={{ file.title }}&type=embedded&mode=embedded&directUrl={{ directUrl }}" target="_blank">
<img src="{% static "images/embeded.svg" %}" alt="Open in embedded mode" title="Open in embedded mode"/>
</a>
</td>

View File

@ -88,6 +88,7 @@ GEM
digest (3.1.0)
erubi (1.11.0)
execjs (2.8.1)
ffi (1.15.5)
ffi (1.15.5-x64-mingw-ucrt)
globalid (1.0.0)
activesupport (>= 5.0)
@ -127,7 +128,9 @@ GEM
net-protocol
timeout
nio4r (2.5.8)
nokogiri (1.13.8-x64-mingw-ucrt)
nokogiri (1.13.9-x64-mingw-ucrt)
racc (~> 1.4)
nokogiri (1.13.9-x86_64-linux)
racc (~> 1.4)
psych (4.0.5)
stringio
@ -216,6 +219,7 @@ GEM
PLATFORMS
x64-mingw-ucrt
x86_64-linux
DEPENDENCIES
byebug

View File

@ -16,11 +16,24 @@
*
*/
var directUrl;
if (typeof jQuery != "undefined") {
jq = jQuery.noConflict();
directUrl = getUrlVars()["directUrl"] == "true";
mustReload = false;
if (directUrl)
jq("#directUrl").prop("checked", directUrl);
else
directUrl = jq("#directUrl").prop("checked");
jq("#directUrl").change(function() {
window.location = "?directUrl=" + jq(this).prop("checked");
});
jq(function () {
jq('#fileupload').fileupload({
dataType: 'json',
@ -218,7 +231,7 @@ if (typeof jQuery != "undefined") {
jq(document).on("click", "#beginEdit:not(.disable)", function () {
var fileId = encodeURIComponent(jq('#hiddenFileName').val());
var url = UrlEditor + "?fileName=" + fileId;
var url = UrlEditor + "?fileName=" + fileId + "&directUrl=" + directUrl;
window.open(url, "_blank");
jq('#hiddenFileName').val("");
jq.unblockUI();
@ -226,7 +239,7 @@ if (typeof jQuery != "undefined") {
jq(document).on("click", "#beginView:not(.disable)", function () {
var fileId = encodeURIComponent(jq('#hiddenFileName').val());
var url = UrlEditor + "?editorsMode=view&fileName=" + fileId;
var url = UrlEditor + "?editorsMode=view&fileName=" + fileId + "&directUrl=" + directUrl;
window.open(url, "_blank");
jq('#hiddenFileName').val("");
jq.unblockUI();
@ -234,7 +247,7 @@ if (typeof jQuery != "undefined") {
jq(document).on("click", "#beginEmbedded:not(.disable)", function () {
var fileId = encodeURIComponent(jq('#hiddenFileName').val());
var url = UrlEditor + "?editorsType=embedded&editorsMode=embedded&fileName=" + fileId;
var url = UrlEditor + "?editorsType=embedded&editorsMode=embedded&fileName=" + fileId + "&directUrl=" + directUrl;
jq("#mainProgress").addClass("embedded");
jq("#beginEmbedded").addClass("disable");
@ -286,6 +299,17 @@ if (typeof jQuery != "undefined") {
}
};
function getUrlVars() {
var vars = [], hash;
var hashes = window.location.href.slice(window.location.href.indexOf('?') + 1).split('&');
for (var i = 0; i < hashes.length; i++) {
hash = hashes[i].split('=');
vars.push(hash[0]);
vars[hash[0]] = hash[1];
}
return vars;
};
var fileList = jq("tr.tableRow");
var mouseIsOverTooltip = false;

View File

@ -168,7 +168,7 @@ label .checkbox {
background-image: url("file_docxf.svg");
}
.create-sample {
.side-option {
color: #666666;
line-height: 24px;
}

View File

@ -26,7 +26,7 @@ class HomeController < ApplicationController
DocumentHelper.init(request.remote_ip, request.base_url)
user = Users.get_user(cookies[:uid])
@file = FileModel.new(:file_name => File.basename(params[:fileName]), :mode => params[:editorsMode], :type => params[:editorsType], :user_ip => request.remote_ip, :lang => cookies[:ulang], :user => user, :action_data => params[:actionLink])
@file = FileModel.new(:file_name => File.basename(params[:fileName]), :mode => params[:editorsMode], :type => params[:editorsType], :user_ip => request.remote_ip, :lang => cookies[:ulang], :user => user, :action_data => params[:actionLink], :direct_url => params[:directUrl])
end

View File

@ -16,7 +16,7 @@
class FileModel
attr_accessor :file_name, :mode, :type, :user_ip, :lang, :user, :action_data
attr_accessor :file_name, :mode, :type, :user_ip, :lang, :user, :action_data, :direct_url
# set file parameters
def initialize(attributes = {})
@ -27,6 +27,7 @@ class FileModel
@lang = attributes[:lang]
@user = attributes[:user]
@action_data = attributes[:action_data]
@direct_url = attributes[:direct_url]
end
def type
@ -110,7 +111,7 @@ class FileModel
:document => {
:title => @file_name,
:url => download_url,
:directUrl => download_url(false),
:directUrl => is_enable_direct_url ? download_url(false) : "",
:fileType => file_ext.delete("."),
:key => key,
:info => {
@ -224,7 +225,9 @@ class FileModel
dataObj["fileType"] = file_ext[1..file_ext.length]
dataObj["key"] = cur_key
dataObj["url"] = i == cur_ver ? doc_uri : DocumentHelper.get_historypath_uri(file_name, i, "prev#{file_ext}")
dataObj["directUrl"] = i == cur_ver ? download_url(false) : DocumentHelper.get_historypath_uri(file_name, i, "prev#{file_ext}", false)
if is_enable_direct_url == true
dataObj["directUrl"] = i == cur_ver ? download_url(false) : DocumentHelper.get_historypath_uri(file_name, i, "prev#{file_ext}", false)
end
dataObj["version"] = i
if (i > 1) # check if the version number is greater than 1
@ -243,11 +246,15 @@ class FileModel
obj["user"] = change ? change["user"] : nil
prev = histData[(i - 2).to_s] # get the history data from the previous file version
dataObj["previous"] = { # write key and url information about previous file version
dataObj["previous"] = is_enable_direct_url == true ? { # write key and url information about previous file version with optional direct url
:fileType => prev["fileType"],
:key => prev["key"],
:url => prev["url"],
:directUrl => prev["directUrl"]
} : {
:fileType => prev["fileType"],
:key => prev["key"],
:url => prev["url"]
}
# write the path to the diff.zip archive with differences in this file version
@ -276,11 +283,14 @@ class FileModel
end
# get image information
def get_insert_image
insert_image = {
def get_insert_image
insert_image = is_enable_direct_url == true ? {
:fileType => "png", # image file type
:url => DocumentHelper.get_server_url(true) + "/assets/logo.png", # server url to the image
:directUrl => DocumentHelper.get_server_url(false) + "/assets/logo.png" # direct url to the image
} : {
:fileType => "png", # image file type
:url => DocumentHelper.get_server_url(true) + "/assets/logo.png" # server url to the image
}
if JwtHelper.is_enabled # check if a secret key to generate token exists or not
@ -292,10 +302,13 @@ class FileModel
# get compared file information
def get_compare_file
compare_file = {
compare_file = is_enable_direct_url == true ? {
:fileType => "docx", # file type
:url => DocumentHelper.get_server_url(true) + "/assets/sample/sample.docx", # server url to the compared file
:directUrl => DocumentHelper.get_server_url(false) + "/assets/sample/sample.docx" # direct url to the compared file
} : {
:fileType => "docx", # file type
:url => DocumentHelper.get_server_url(true) + "/assets/sample/sample.docx" # server url to the compared file
}
if JwtHelper.is_enabled # check if a secret key to generate token exists or not
@ -307,10 +320,13 @@ class FileModel
# get mail merge recipients information
def dataMailMergeRecipients
dataMailMergeRecipients = {
dataMailMergeRecipients = is_enable_direct_url == true ? {
:fileType => "csv", # file type
:url => DocumentHelper.get_server_url(true) + "/csv", # server url to the mail merge recipients file
:directUrl => DocumentHelper.get_server_url(false) + "/csv" # direct url to the mail merge recipients file
} : {
:fileType => "csv", # file type
:url => DocumentHelper.get_server_url(true) + "/csv" # server url to the mail merge recipients file
}
if JwtHelper.is_enabled # check if a secret key to generate token exists or not
@ -325,4 +341,9 @@ class FileModel
return !@user.id.eql?("uid-0") ? Users.get_users_for_mentions(@user.id) : nil
end
# get direct url existence flag
def is_enable_direct_url
return @direct_url != nil && @direct_url == "true"
end
end

View File

@ -54,6 +54,7 @@ class ServiceConverter
DocumentHelper.verify_ssl(@@document_converter_url, http)
http.read_timeout = @@convert_timeout
http.open_timeout = 5
req = Net::HTTP::Post.new(uri.request_uri) # create the post request
req.add_field("Accept", "application/json") # set headers
req.add_field("Content-Type", "application/json")
@ -66,6 +67,12 @@ class ServiceConverter
req.body = payload.to_json
res = http.request(req) # get the response
status_code = res.code
if status_code != 200 # checking status code
raise "Conversion service returned status: #{status_code}"
end
data = res.body # and take its body
rescue TimeoutError
# try again

View File

@ -251,11 +251,17 @@ class TrackHelper
def save_from_uri(path, uristr)
uri = URI.parse(uristr) # parse the url string
http = Net::HTTP.new(uri.host, uri.port) # create a connection to the http server
http.open_timeout = 5
DocumentHelper.verify_ssl(uristr, http)
req = Net::HTTP::Get.new(uri)
res = http.request(req) # get the response
status_code = res.code
if status_code != 200 # checking status code
raise "Document editing service returned status: #{status_code}"
end
data = res.body # and take its body
if data == nil

View File

@ -44,7 +44,7 @@
<a class="try-editor form" data-type="docxf">Form template</a>
</li>
</ul>
<label class="create-sample">
<label class="side-option">
<input id="createSample" class="checkbox" type="checkbox" />With sample content
</label>
</div>
@ -60,7 +60,7 @@
<tr>
<td valign="middle">
<span class="select-user">Username</span>
<img class="info" data-id="user" src="assets/info.svg" />
<img id="info" data-id="user" src="assets/info.svg" />
<select class="select-user" id="user">
<% for user in Users.get_all_users() do %>
<option value="<%= user.id %>"><%= user.name ? user.name : "Anonymous" %></option>
@ -78,6 +78,14 @@
</select>
</td>
</tr>
<tr>
<td valign="middle">
<label class="side-option">
<input id="directUrl" type="checkbox" class="checkbox" />Try opening on client
<img id="directUrlInfo" class="info info-tooltip" data-id="directUrlInfo" data-tooltip="Some files can be opened in the user's browser without connecting to the document server." src="assets/info.svg" />
</label>
</td>
</tr>
</tbody>
</table>
</div>
@ -87,6 +95,7 @@
<%
DocumentHelper.init(request.remote_ip, request.base_url)
docs = DocumentHelper.get_stored_files(nil)
directUrl = request.params[:directUrl]
%>
<div class="main-panel">
<div id="portal-info" style="display: <%= docs.length > 0 ? "none" : "table-cell" %>">
@ -128,7 +137,7 @@
<%
docs.each { |d|
isFillFormDoc = DocumentHelper.fill_forms_exts.include?(File.extname(d).downcase)
editUrl = "editor?fileName=#{ERB::Util.url_encode(d)}"
editUrl = directUrl == nil ? "editor?fileName=#{ERB::Util.url_encode(d)}" : "editor?fileName=#{ERB::Util.url_encode(d)}&directUrl=#{directUrl}"
docType = FileUtility.get_file_type(d)
canEdit = DocumentHelper.edited_exts.include?(File.extname(d).downcase) %>
<tr class="tableRow" title="<%= d %> [<%= DocumentHelper.get_file_version(DocumentHelper.history_dir(DocumentHelper.storage_path(d, nil))) %>]">

View File

@ -26,7 +26,7 @@ module OnlineEditorsExampleRuby
end
end
Rails.configuration.version="1.3.0"
Rails.configuration.version="1.4.0"
Rails.configuration.fileSizeMax=5242880
Rails.configuration.storagePath="app_data"