Compare commits

...

112 Commits

Author SHA1 Message Date
05a3110c99 Remove workflow and disable build nodejs docker (#286)
* Remove workflow and disable build

* Remove Dockerfile
2022-05-27 15:34:59 +03:00
8bafa3ff3a Add submodule-init (#283) 2022-05-19 17:02:51 +03:00
56679a3b75 Change target repo (#282)
* Change target repo

* Add latest tag
2022-05-19 15:59:11 +03:00
d4d758770f Add docs-example multiarch build (#281)
* Add multiarch build

* Cosmetic changes

* Cosmetic changes
2022-05-19 14:17:28 +03:00
874ebff886 Fix the launch of the example container (#279)
* Fix the launch of the example container

* Change the user home directory

* Change the command for create a user
2022-05-16 17:26:24 +03:00
4f2f877f0e docxf update 2022-05-12 13:22:15 +03:00
5cc6b4cb15 Merge pull request #277 from ONLYOFFICE/develop
Release/1.2.0
2022-04-18 14:16:23 +03:00
7a70a44bcb 1.2.0 2022-04-18 13:59:07 +03:00
e42bd53664 Merge pull request #274 from ONLYOFFICE/feature/languages-fix
languages sort fix
2022-04-11 10:42:55 +03:00
23e616aade languages sort fix 2022-04-11 10:38:26 +03:00
f035da0db4 nodejs: disable X-Powered-By 2022-04-05 15:16:45 +03:00
3e12ec4ebe Merge pull request #272 from ONLYOFFICE/feature/ignore-self-signed-certificate
Feature/ignore self signed certificate
2022-03-30 14:34:02 +03:00
589ca9b601 Merge branch 'develop' into feature/ignore-self-signed-certificate 2022-03-28 16:00:59 +03:00
32f1ec82d1 Merge pull request #271 from ONLYOFFICE/feature/uid-0-fix
Feature/uid 0 fix
2022-03-28 13:26:38 +03:00
54bb5b0a24 format 2022-03-28 13:26:17 +03:00
8274c16f6d Merge pull request #273 from ONLYOFFICE/feature/update-readme
Update README.md
2022-03-28 13:09:24 +03:00
7a982fc785 format 2022-03-28 13:09:13 +03:00
6f5800fbde Updated Readme files in examples 2022-03-28 12:05:45 +03:00
8ec632eebd csharp-mvc: function created 2022-03-28 10:12:46 +03:00
b6ca4535ce csharp: function created 2022-03-28 09:58:59 +03:00
089fc8bfa0 ruby: function created 2022-03-28 09:31:01 +03:00
0b4c17ea0a Update README.md 2022-03-25 17:57:11 +03:00
405be2847b java-spring: ignoring self-signed certificate was added 2022-03-25 16:54:04 +03:00
f809c7e525 python: certificate ignore was added 2022-03-25 13:26:00 +03:00
44061c82a9 csharp-mvc: ignore certificate in config 2022-03-24 11:24:46 +03:00
ef4e283804 csharp: ignore certificate in config 2022-03-24 10:26:31 +03:00
4b0ad1a192 csharp + csharp-mvc 2022-03-23 16:56:41 +03:00
60469b0dba java: ignore certificate in config 2022-03-23 15:39:11 +03:00
f5ac95e1cc nodejs: ignore certificate in config 2022-03-23 15:11:30 +03:00
c4c2fbb945 ruby: certificate was ignored 2022-03-23 14:25:53 +03:00
99b5fcd562 python 2022-03-23 13:29:24 +03:00
7e34067410 java 2022-03-23 12:38:38 +03:00
a44787c625 java-spring 2022-03-23 11:11:03 +03:00
105afb2c34 php 2022-03-23 10:57:33 +03:00
002f9b958e nodejs 2022-03-23 10:53:51 +03:00
56d5913808 ruby 2022-03-23 10:48:28 +03:00
6664864bed nodejs 2022-03-22 13:52:28 +03:00
6c9e6e9304 Merge pull request #268 from ONLYOFFICE/feature/language-update
Feature/language update
2022-03-22 12:21:43 +03:00
416b1fde8c Merge pull request #270 from ONLYOFFICE/feature/hide-history-for-anonymous
Feature/hide history for anonymous
2022-03-22 11:54:12 +03:00
383f240825 Merge pull request #269 from ONLYOFFICE/feature/ban-renaming-for-anonymous
Feature/ban renaming for anonymous
2022-03-22 11:48:57 +03:00
642e145142 php: certificate was ignored 2022-03-22 11:15:09 +03:00
8f09dadfa0 ruby: java-spring: bugfix 2022-03-21 17:10:11 +03:00
495f1cf49a nodejs: split filename 2022-03-21 11:18:30 +03:00
cf01b5e0ae csharp: csharp-mvc: version history button was hidden 2022-03-21 09:38:48 +03:00
0673fed928 java: java-spring: version history button was hidden 2022-03-21 09:35:58 +03:00
9b0b30a0b0 nodejs: version history button was hidden 2022-03-21 09:32:27 +03:00
200187edce python: version history button was hidden 2022-03-21 09:29:32 +03:00
23176ddf07 ruby: version history button was hidden 2022-03-21 09:27:26 +03:00
9857cef8fc php: version history button was hidden 2022-03-21 09:22:31 +03:00
204f770401 java-spring: bugfix 2022-03-18 15:58:02 +03:00
61834e3ec6 Merge branch 'feature/language-update' of github.com:ONLYOFFICE/document-server-integration into feature/language-update 2022-03-18 15:24:45 +03:00
2ca6185ac4 php: bugfix 2022-03-18 15:24:30 +03:00
e818bb978b csharp: removed rename action for anonymous 2022-03-18 15:08:20 +03:00
3a4cf5e6e6 csharp-mvc: removed rename action for anonymous 2022-03-18 15:06:46 +03:00
7ec16b90e3 java: removed rename action for anonymous 2022-03-18 15:04:28 +03:00
fcfb6efda7 java-spring: removed rename action for anonymous 2022-03-18 15:02:45 +03:00
e4c72c98d1 nodejs: removed rename action for anonymous 2022-03-18 14:59:27 +03:00
c2bbda542a python: removed rename action for anonymous 2022-03-18 14:56:17 +03:00
2c12393c78 ruby: removed rename action for anonymous 2022-03-18 14:52:59 +03:00
4e93f6ebac php: fix 2022-03-18 14:47:59 +03:00
d10ba9f773 Merge branch 'develop' into feature/ban-renaming-for-anonymous 2022-03-18 14:40:38 +03:00
a0bf7db118 php: removed rename action 2022-03-18 14:36:46 +03:00
e40e7cc41c csharp-mvc: move languages to config 2022-03-18 11:25:54 +03:00
f616655f4c csharp: move languages to config 2022-03-18 11:14:49 +03:00
4ba708631e Merge pull request #266 from ONLYOFFICE/feature/renaming-files
Feature/renaming files
2022-03-18 10:31:19 +03:00
b9c1bc0f42 java-spring: changing arguments 2022-03-18 09:50:59 +03:00
215ade01a3 java: changing arguments 2022-03-18 09:32:34 +03:00
4d25418fc8 java: move languages to config 2022-03-17 14:05:56 +03:00
4539bac5db Merge pull request #267 from ONLYOFFICE/feature/customization
Feature/customization
2022-03-17 11:10:14 +03:00
eb196613e7 format 2022-03-17 10:36:38 +03:00
7ac788f589 csharp: jwt in body 2022-03-17 10:27:47 +03:00
55119458af java-spring: move languages to config 2022-03-17 10:14:02 +03:00
3c18add1fc Merge remote-tracking branch 'remotes/origin/release/v7.1.0' into develop 2022-03-17 09:56:20 +03:00
6bf63b7166 nodejs: move languages to config 2022-03-16 16:30:56 +03:00
32df2d3e34 php: move languages to config 2022-03-16 15:41:45 +03:00
97c7859db5 ruby: move languages to config 2022-03-16 15:32:47 +03:00
492f9c7baa python: config 2022-03-16 14:58:16 +03:00
e0c0595796 removed chat 2022-03-16 13:06:37 +03:00
40b8fb88a8 Merge branch 'feature/renaming-files' of github.com:ONLYOFFICE/document-server-integration into feature/renaming-files 2022-03-16 11:36:17 +03:00
b0df0d72df java-spring: refactoring 2022-03-16 10:48:43 +03:00
1053add1d9 csharp-mvc: refactoring 2022-03-16 09:47:49 +03:00
f1fc0e5fae csharp: refactoring 2022-03-16 09:38:30 +03:00
a192c6ce1f ruby: refactoring 2022-03-15 18:45:35 +03:00
e8aec0b68c java: php: python: refactoring 2022-03-15 18:10:02 +03:00
d9667f9757 nodejs: fix 2022-03-15 15:17:19 +03:00
3a985da120 Merge branch 'feature/renaming-files' of github.com:ONLYOFFICE/document-server-integration into feature/renaming-files 2022-03-15 14:19:34 +03:00
a88f84ddac nodejs: use commandRequest 2022-03-15 14:19:16 +03:00
6525d7210f micro fix 2022-03-15 13:33:33 +03:00
6b93311ce5 customization change 2022-03-15 13:10:34 +03:00
999561ffd6 Merge branch 'feature/renaming-files' of github.com:ONLYOFFICE/document-server-integration into feature/renaming-files 2022-03-15 10:51:43 +03:00
e539c1205f python: nodejs: jwt fix 2022-03-15 10:51:26 +03:00
9a52a538cb csharp-mvc: jwt fix 2022-03-15 08:24:11 +03:00
e8038a8e88 csharp: jwt fix 2022-03-15 08:18:34 +03:00
1045b314b6 Merge pull request #265 from ONLYOFFICE/bugfix/wopi
fix wopi
2022-03-14 17:50:35 +03:00
1636732521 nodejs: fix userHost in wopi 2022-03-14 17:48:32 +03:00
daa9a5f3fa fix wopi 2022-03-14 15:49:24 +03:00
9bf3973215 csharp-mvc: meta command 2022-03-14 14:00:05 +03:00
cad2a20cdf csharp: meta command 2022-03-14 13:41:12 +03:00
82a5a68e6c java: meta command 2022-03-11 14:59:10 +03:00
0e1a580a86 refactoring 2022-03-11 14:13:09 +03:00
c09f3fc4b9 Merge branch 'feature/renaming-files' of github.com:ONLYOFFICE/document-server-integration into feature/renaming-files 2022-03-11 11:02:39 +03:00
d4d7c4e222 java-spring: meta command 2022-03-11 10:58:54 +03:00
14429c5b05 php: rename refactoring 2022-03-11 09:45:42 +03:00
131e33c6af Merge pull request #264 from ONLYOFFICE/feature/fix-mentions
Feature/fix mentions
2022-03-10 16:19:50 +03:00
8a04e5fbc4 ruby:meta command 2022-03-09 13:50:47 +03:00
1b6435a7dc python:meta command 2022-03-08 10:50:05 +03:00
b8eecab45f nodejs:meta command 2022-03-07 22:01:03 +03:00
f7259409a2 php:jwt 2022-03-04 14:34:50 +03:00
0ea9e68c7c meta command 2022-03-04 11:15:43 +03:00
4b72e0a664 php: add request rename in doceditor + add function renamefile() in webeditor 2022-03-03 14:34:57 +03:00
935377a941 all: fix link in mentions 2022-03-02 17:42:12 +03:00
3690aacb66 nodejs: fix link in mentions 2022-03-02 17:10:41 +03:00
96 changed files with 1247 additions and 668 deletions

View File

@ -67,6 +67,15 @@ The methods described below are available for all of the test examples.
| **Response** | **Code:** 200 OK <br />**Content on success:**<br /> `[{ "version": <file_version>, "id": <file_id>, "contentLength": <file_size_in_kilobytes>, "pureContentLength": <file_size_in_bytes>, "title": <file_name>, "updated": <last_change_date>}]`<br />**Content on error:**<br /> `"File not found"` |
| **Sample** | `curl -X GET http://localhost/files/{fileId}` |
## Important security info
Please keep in mind the following security aspects when you are using test examples:
* There is no protection of the storage from unauthorized access since there is no need for authorization.
* There are no checks against parameter substitution in links, since the parameters are generated by the code according to the pre-arranged scripts.
* There are no data checks in requests of saving the file after editing, since each test example is intended for requests only from ONLYOFFICE Document Server.
* There are no prohibitions on using test examples from other sites, since they are intended to interact with ONLYOFFICE Document Server from another domain.
## Project Information
Official website: [https://www.onlyoffice.com](https://www.onlyoffice.com/?utm_source=github&utm_medium=cpc&utm_campaign=GitHubIntegrationEx)

View File

@ -25,6 +25,7 @@ using System.Web;
using System.Web.Configuration;
using System.Web.Script.Serialization;
using OnlineEditorsExampleMVC.Models;
using System.Net;
namespace OnlineEditorsExampleMVC.Helpers
{
@ -416,5 +417,27 @@ namespace OnlineEditorsExampleMVC.Helpers
return files;
}
// enable certificate ignore
public static void VerifySSL()
{
// hack. http://ubuntuforums.org/showthread.php?t=1841740
if(WebConfigurationManager.AppSettings["files.docservice.verify-peer-off"].Equals("true")) {
ServicePointManager.ServerCertificateValidationCallback += (s, ce, ca, p) => true;
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls;
}
}
public static Dictionary<string, string> GetLanguages()
{
var languages = new Dictionary<string, string>();
String[] couples = (WebConfigurationManager.AppSettings["files.docservice.languages"] ?? "").Split('|');
foreach (string couple in couples)
{
String[] tmp = couple.Split(':');
languages.Add(tmp[0],tmp[1]);
}
return languages;
}
}
}

View File

@ -143,6 +143,8 @@ namespace OnlineEditorsExampleMVC.Helpers
requestStream.Write(bytes, 0, bytes.Length); // and write the serialized body object to it
}
DocManagerHelper.VerifySSL();
string dataResponse;
using (var response = request.GetResponse())
using (var stream = response.GetResponseStream()) // get the response stream

View File

@ -76,7 +76,9 @@ namespace OnlineEditorsExampleMVC.Helpers
if (token != null && !token.Equals("")) // invalid signature error
{
fileData = (Dictionary<string, object>)jss.Deserialize<Dictionary<string, object>>(token)["payload"];
fileData = jss.Deserialize<Dictionary<string, object>>(token);
if (fileData.ContainsKey("payload"))
fileData = (Dictionary<string, object>)fileData["payload"];
}
else
{
@ -126,6 +128,8 @@ namespace OnlineEditorsExampleMVC.Helpers
}
}
DocManagerHelper.VerifySSL();
var storagePath = DocManagerHelper.StoragePath(newFileName, userAddress); // get the file path
var histDir = DocManagerHelper.HistoryDir(storagePath); // get the path to the history directory
if (!Directory.Exists(histDir)) Directory.CreateDirectory(histDir);
@ -201,6 +205,8 @@ namespace OnlineEditorsExampleMVC.Helpers
}
}
DocManagerHelper.VerifySSL();
string forcesavePath = "";
Boolean isSubmitForm = fileData["forcesavetype"].ToString().Equals("3"); // SubmitForm
@ -243,8 +249,10 @@ namespace OnlineEditorsExampleMVC.Helpers
}
// create a command request
public static void commandRequest(string method, string key)
public static void commandRequest(string method, string key, object meta = null)
{
DocManagerHelper.VerifySSL();
string documentCommandUrl = WebConfigurationManager.AppSettings["files.docservice.url.site"] + WebConfigurationManager.AppSettings["files.docservice.url.command"];
var request = (HttpWebRequest)WebRequest.Create(documentCommandUrl);
@ -256,6 +264,11 @@ namespace OnlineEditorsExampleMVC.Helpers
{ "key", key }
};
if (meta != null)
{
body.Add("meta", meta);
}
// check if a secret key to generate token exists or not
if (JwtManager.Enabled)
{

View File

@ -66,7 +66,8 @@ namespace OnlineEditorsExampleMVC.Helpers
"The file favorite state is undefined",
"Can't mention others in comments",
"Can't create new files from the editor",
"Cant see anyones information"
"Cant see anyones information",
"Can't rename files from the editor"
};
private static List<User> users = new List<User>() {

View File

@ -188,6 +188,7 @@ namespace OnlineEditorsExampleMVC.Models
"customization", new Dictionary<string, object>
{
{ "about", true }, // the About section display
{ "comments", true },
{ "feedback", true }, // the Feedback & Support menu button display
{ "forcesave", false }, // adds the request for the forced file saving to the callback handler
{ "submitForm", submitForm }, // if the Submit form button is displayed or not

View File

@ -70,3 +70,12 @@ Configure the IIS components for the server to work correctly:
In case the example and Document Server are installed on different computers, make sure that your server with the example installed has access to the Document Server with the address which you specify instead of **documentserver** in the configuration files.
Make sure that the Document Server has access to the server with the example installed with the address which you specify instead of **example.com** in the configuration files.
## Important security info
Please keep in mind the following security aspects when you are using test examples:
* There is no protection of the storage from unauthorized access since there is no need for authorization.
* There are no checks against parameter substitution in links, since the parameters are generated by the code according to the pre-arranged scripts.
* There are no data checks in requests of saving the file after editing, since each test example is intended for requests only from ONLYOFFICE Document Server.
* There are no prohibitions on using test examples from other sites, since they are intended to interact with ONLYOFFICE Document Server from another domain.

View File

@ -46,6 +46,7 @@
<script type="text/javascript" language="javascript">
var docEditor;
var config;
var innerAlert = function (message, inEditor) {
if (console && console.log)
@ -107,10 +108,14 @@
// the meta information of the document is changed via the meta command
var onMetaChange = function (event) {
var favorite = !!event.data.favorite;
var title = document.title.replace(/^\☆/g, "");
document.title = (favorite ? "☆" : "") + title;
docEditor.setFavorite(favorite); // change the Favorite icon state
if (event.data.favorite) {
var favorite = !!event.data.favorite;
var title = document.title.replace(/^\☆/g, "");
document.title = (favorite ? "☆" : "") + title;
docEditor.setFavorite(favorite); // change the Favorite icon state
}
innerAlert("onMetaChange: " + JSON.stringify(event.data));
};
// the user is trying to insert an image by clicking the Image from Storage button
@ -146,7 +151,7 @@
};
let xhr = new XMLHttpRequest();
xhr.open("POST", "webeditor.ashx?type=saveas");
xhr.setRequestHeader( 'Content-Type', 'application/json');
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.send(JSON.stringify(data));
xhr.onload = function () {
innerAlert(xhr.responseText);
@ -154,7 +159,25 @@
}
};
var config = <%= Model.GetDocConfig(Request, Url) %>;
var onRequestRename = function(event) { // the user is trying to rename file by clicking Rename... button
innerAlert("onRequestRename: " + JSON.stringify(event.data));
var newfilename = event.data;
var data = {
newfilename: newfilename,
dockey: config.document.key,
};
let xhr = new XMLHttpRequest();
xhr.open("POST", "webeditor.ashx?type=rename");
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.send(JSON.stringify(data));
xhr.onload = function () {
innerAlert(xhr.responseText);
}
};
config = <%= Model.GetDocConfig(Request, Url) %>;
config.width = "100%";
config.height = "100%";
@ -174,42 +197,49 @@
<% string hist, histData; %>
<% Model.GetHistory(out hist, out histData); %>
<% if (!string.IsNullOrEmpty(hist) && !string.IsNullOrEmpty(histData))
{ %>
// the user is trying to show the document version history
config.events['onRequestHistory'] = function () {
docEditor.refreshHistory(<%= hist %>); // show the document version history
};
// the user is trying to click the specific document version in the document version history
config.events['onRequestHistoryData'] = function (event) {
var ver = event.data;
var histData = <%= histData %>;
docEditor.setHistoryData(histData[ver - 1]); // send the link to the document for viewing the version history
};
// the user is trying to go back to the document from viewing the document version history
config.events['onRequestHistoryClose '] = function () {
document.location.reload();
};
<% } %>
<% string usersForMentions; %>
<% Model.GetUsersMentions(Request, out usersForMentions); %>
<% if (!string.IsNullOrEmpty(usersForMentions))
// add mentions for not anonymous users
{ %>
config.events['onRequestUsers'] = function () {
docEditor.setUsers({ // set a list of users to mention in the comments
"users": <%= usersForMentions%>
});
};
// the user is mentioned in a comment
config.events['onRequestSendNotify'] = function (event) {
event.data.actionLink = replaceActionLink(location.href, event.data.actionLink);
var data = JSON.stringify(event.data);
innerAlert("onRequestSendNotify: " + data);
};
<% } %>
if (config.editorConfig.user.id) {
<% if (!string.IsNullOrEmpty(hist) && !string.IsNullOrEmpty(histData))
{ %>
// the user is trying to show the document version history
config.events['onRequestHistory'] = function () {
docEditor.refreshHistory(<%= hist %>); // show the document version history
};
// the user is trying to click the specific document version in the document version history
config.events['onRequestHistoryData'] = function (event) {
var ver = event.data;
var histData = <%= histData %>;
docEditor.setHistoryData(histData[ver - 1]); // send the link to the document for viewing the version history
};
// the user is trying to go back to the document from viewing the document version history
config.events['onRequestHistoryClose '] = function () {
document.location.reload();
};
<% } %>
// add mentions for not anonymous users
<% if (!string.IsNullOrEmpty(usersForMentions))
{ %>
config.events['onRequestUsers'] = function () {
docEditor.setUsers({ // set a list of users to mention in the comments
"users": <%= usersForMentions %>
});
};
<% } %>
// the user is mentioned in a comment
config.events['onRequestSendNotify'] = function (event) {
event.data.actionLink = replaceActionLink(location.href, JSON.stringify(event.data.actionLink));
var data = JSON.stringify(event.data);
innerAlert("onRequestSendNotify: " + data);
};
// prevent file renaming for anonymous users
config.events['onRequestRename'] = onRequestRename;
}
if (config.editorConfig.createUrl) {
config.events.onRequestSaveAs = onRequestSaveAs;
};

View File

@ -4,6 +4,7 @@
<%@ Import Namespace="System.Web.Configuration" %>
<%@ Import Namespace="OnlineEditorsExampleMVC.Helpers" %>
<%@ Import Namespace="OnlineEditorsExampleMVC.Models" %>
<%@ Import Namespace="System.Collections.Generic" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
@ -89,7 +90,7 @@
<select class="select-user" id="user">
<% foreach (User user in Users.getAllUsers())
{ %>
<option value=<%= user.id %> ><%= user.name.IsEmpty() ? "Anonymous" : user.name %></option>
<option value="<%= user.id %>"><%= user.name.IsEmpty() ? "Anonymous" : user.name %></option>
<% } %>
</select>
</td>
@ -98,37 +99,11 @@
<td valign="middle">
<span class="select-user">Language editors interface</span>
<select class="select-user" id="language">
<option value="en">English</option>
<option value="be">Belarusian</option>
<option value="bg">Bulgarian</option>
<option value="ca">Catalan</option>
<option value="zh">Chinese</option>
<option value="cs">Czech</option>
<option value="da">Danish</option>
<option value="nl">Dutch</option>
<option value="fi">Finnish</option>
<option value="fr">French</option>
<option value="de">German</option>
<option value="el">Greek</option>
<option value="hu">Hungarian</option>
<option value="id">Indonesian</option>
<option value="it">Italian</option>
<option value="ja">Japanese</option>
<option value="ko">Korean</option>
<option value="lv">Latvian</option>
<option value="lo">Lao</option>
<option value="nb">Norwegian</option>
<option value="pl">Polish</option>
<option value="pt">Portuguese</option>
<option value="ro">Romanian</option>
<option value="ru">Russian</option>
<option value="sk">Slovak</option>
<option value="sl">Slovenian</option>
<option value="sv">Swedish</option>
<option value="es">Spanish</option>
<option value="tr">Turkish</option>
<option value="uk">Ukrainian</option>
<option value="vi">Vietnamese</option>
<% Dictionary<string, string> languages = DocManagerHelper.GetLanguages();
foreach (var lang in languages)
{ %>
<option value="<%= lang.Key %>"><%= lang.Value %></option>
<% } %>
</select>
</td>
</tr>

View File

@ -19,6 +19,7 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Linq;
using System.Net;
using System.Web;
@ -70,6 +71,9 @@ namespace OnlineEditorsExampleMVC
case "saveas":
SaveAs(context);
break;
case "rename":
Rename(context);
break;
}
}
@ -113,6 +117,8 @@ namespace OnlineEditorsExampleMVC
var req = (HttpWebRequest)WebRequest.Create(fileUrl);
DocManagerHelper.VerifySSL();
using (var stream = req.GetResponse().GetResponseStream())
{
@ -151,6 +157,8 @@ namespace OnlineEditorsExampleMVC
context.Response.ContentType = "text/plain";
try
{
DocManagerHelper.VerifySSL();
var httpPostedFile = context.Request.Files[0];
string fileName;
@ -250,6 +258,8 @@ namespace OnlineEditorsExampleMVC
var req = (HttpWebRequest)WebRequest.Create(newFileUri);
DocManagerHelper.VerifySSL();
using (var stream = req.GetResponse().GetResponseStream()) // get response stream of the converting file
{
if (stream == null) throw new Exception("Stream is null");
@ -541,5 +551,36 @@ namespace OnlineEditorsExampleMVC
context.Response.Write("{ \"error\": \"File not found!\"}");
}
}
// rename a file
private static void Rename(HttpContext context)
{
// read request body
context.Response.ContentType = "text/plain";
string fileData;
try
{
using (var receiveStream = context.Request.InputStream)
using (var readStream = new StreamReader(receiveStream))
{
fileData = readStream.ReadToEnd();
if (string.IsNullOrEmpty(fileData)) context.Response.Write("{\"error\":\"Request stream is empty\"}");
}
}
catch (Exception e)
{
throw new HttpException((int)HttpStatusCode.BadRequest, e.Message);
}
var jss = new JavaScriptSerializer();
var body = jss.Deserialize<Dictionary<string, object>>(fileData);
var newFileName = (string) body["newfilename"];
var docKey = (string) body["dockey"];
var meta = new Dictionary<string, object>() {
{ "title", newFileName }
};
TrackManager.commandRequest("meta", docKey, meta);
context.Response.Write("{ \"result\": \"OK\"}");
}
}
}

View File

@ -1,7 +1,7 @@
<?xml version="1.0"?>
<?xml version="1.0"?>
<appSettings>
<clear />
<add key="version" value="1.1.0"/>
<add key="version" value="1.2.0"/>
<add key="filesize-max" value="52428800"/>
<add key="storage-path" value=""/>
@ -14,6 +14,10 @@
<add key="files.docservice.secret" value="" />
<add key="files.docservice.header" value="Authorization" />
<add key="files.docservice.verify-peer-off" value="true"/>
<add key="files.docservice.languages" value="en:English|az:Azerbaijani|be:Belarusian|bg:Bulgarian|ca:Catalan|zh:Chinese|cs:Czech|da:Danish|nl:Dutch|fi:Finnish|fr:French|gl:Galego|de:German|el:Greek|hu:Hungarian|id:Indonesian|it:Italian|ja:Japanese|ko:Korean|lv:Latvian|lo:Lao|nb:Norwegian|pl:Polish|pt:Portuguese|ro:Romanian|ru:Russian|sk:Slovak|sl:Slovenian|es:Spanish|sv:Swedish|tr:Turkish|uk:Ukrainian|vi:Vietnamese"/>
<add key="files.docservice.url.site" value="http://documentserver/"/>
<add key="files.docservice.url.converter" value="ConvertService.ashx"/>

View File

@ -5,6 +5,7 @@
<%@ Import Namespace="System.Linq" %>
<%@ Import Namespace="System.Web.Configuration" %>
<%@ Import Namespace="OnlineEditorsExample" %>
<%@ Import Namespace="System.Collections.Generic" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
@ -100,37 +101,11 @@
<td valign="middle">
<span class="select-user">Language editors interface</span>
<select class="select-user" id="language">
<option value="en">English</option>
<option value="be">Belarusian</option>
<option value="bg">Bulgarian</option>
<option value="ca">Catalan</option>
<option value="zh">Chinese</option>
<option value="cs">Czech</option>
<option value="da">Danish</option>
<option value="nl">Dutch</option>
<option value="fi">Finnish</option>
<option value="fr">French</option>
<option value="de">German</option>
<option value="el">Greek</option>
<option value="hu">Hungarian</option>
<option value="id">Indonesian</option>
<option value="it">Italian</option>
<option value="ja">Japanese</option>
<option value="ko">Korean</option>
<option value="lv">Latvian</option>
<option value="lo">Lao</option>
<option value="nb">Norwegian</option>
<option value="pl">Polish</option>
<option value="pt">Portuguese</option>
<option value="ro">Romanian</option>
<option value="ru">Russian</option>
<option value="sk">Slovak</option>
<option value="sl">Slovenian</option>
<option value="sv">Swedish</option>
<option value="es">Spanish</option>
<option value="tr">Turkish</option>
<option value="uk">Ukrainian</option>
<option value="vi">Vietnamese</option>
<% Dictionary<string, string> languages = GetLanguages();
foreach (var lang in languages)
{ %>
<option value="<%= lang.Key %>"><%= lang.Value %></option>
<% } %>
</select>
</td>
</tr>

View File

@ -353,11 +353,7 @@ namespace OnlineEditorsExample
try
{
// hack. http://ubuntuforums.org/showthread.php?t=1841740
if (IsMono)
{
ServicePointManager.ServerCertificateValidationCallback += (s, ce, ca, p) => true;
}
VerifySSL();
using (var stream = req.GetResponse().GetResponseStream()) // get response stream of the uploading file
{
@ -420,11 +416,7 @@ namespace OnlineEditorsExample
var req = (HttpWebRequest)WebRequest.Create(fileUrl);
// hack. http://ubuntuforums.org/showthread.php?t=1841740
if (IsMono)
{
ServicePointManager.ServerCertificateValidationCallback += (s, ce, ca, p) => true;
}
VerifySSL();
using (var stream = req.GetResponse().GetResponseStream())
{
@ -508,11 +500,7 @@ namespace OnlineEditorsExample
var req = (HttpWebRequest)WebRequest.Create(newFileUri);
// hack. http://ubuntuforums.org/showthread.php?t=1841740
if (IsMono)
{
ServicePointManager.ServerCertificateValidationCallback += (s, ce, ca, p) => true;
}
VerifySSL();
using (var stream = req.GetResponse().GetResponseStream()) // get response stream of the converting file
{
@ -616,5 +604,27 @@ namespace OnlineEditorsExample
return files;
}
// enable certificate ignore
public static void VerifySSL()
{
// hack. http://ubuntuforums.org/showthread.php?t=1841740
if(WebConfigurationManager.AppSettings["files.docservice.verify-peer-off"].Equals("true")) {
ServicePointManager.ServerCertificateValidationCallback += (s, ce, ca, p) => true;
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls;
}
}
public static Dictionary<string, string> GetLanguages()
{
var languages = new Dictionary<string, string>();
String[] couples = (WebConfigurationManager.AppSettings["files.docservice.languages"] ?? "").Split('|');
foreach (string couple in couples)
{
String[] tmp = couple.Split(':');
languages.Add(tmp[0],tmp[1]);
}
return languages;
}
}
}

View File

@ -64,6 +64,7 @@
<script type="text/javascript" language="javascript">
var docEditor;
var config;
var innerAlert = function (message, inEditor) {
if (console && console.log)
@ -125,10 +126,14 @@
// the meta information of the document is changed via the meta command
var onMetaChange = function (event) {
var favorite = !!event.data.favorite;
var title = document.title.replace(/^\☆/g, "");
document.title = (favorite ? "☆" : "") + title;
docEditor.setFavorite(favorite); // change the Favorite icon state
if (event.data.favorite) {
var favorite = !!event.data.favorite;
var title = document.title.replace(/^\☆/g, "");
document.title = (favorite ? "☆" : "") + title;
docEditor.setFavorite(favorite); // change the Favorite icon state
}
innerAlert("onMetaChange: " + JSON.stringify(event.data));
};
// the user is trying to insert an image by clicking the Image from Storage button
@ -158,7 +163,7 @@
};
let xhr = new XMLHttpRequest();
xhr.open("POST", "webeditor.ashx?type=saveas");
xhr.setRequestHeader( 'Content-Type', 'application/json');
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.send(JSON.stringify(data));
xhr.onload = function () {
innerAlert(xhr.responseText);
@ -166,7 +171,25 @@
}
};
var config = <%= DocConfig %>;
var onRequestRename = function(event) { // the user is trying to rename file by clicking Rename... button
innerAlert("onRequestRename: " + JSON.stringify(event.data));
var newfilename = event.data;
var data = {
newfilename: newfilename,
dockey: config.document.key,
};
let xhr = new XMLHttpRequest();
xhr.open("POST", "webeditor.ashx?type=rename");
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.send(JSON.stringify(data));
xhr.onload = function () {
innerAlert(xhr.responseText);
}
};
config = <%= DocConfig %>;
config.width = "100%";
config.height = "100%";
@ -184,37 +207,42 @@
"onRequestMailMergeRecipients": onRequestMailMergeRecipients,
};
<% if (!string.IsNullOrEmpty(History) && !string.IsNullOrEmpty(HistoryData))
{ %>
config.events['onRequestHistory'] = function () { // the user is trying to show the document version history
docEditor.refreshHistory(<%= History %>); // show the document version history
};
config.events['onRequestHistoryData'] = function (event) { // the user is trying to click the specific document version in the document version history
var ver = event.data;
var histData = <%= HistoryData %>;
docEditor.setHistoryData(histData[ver - 1]); // send the link to the document for viewing the version history
};
config.events['onRequestHistoryClose '] = function () { // the user is trying to go back to the document from viewing the document version history
document.location.reload();
};
<% } %>
if (config.editorConfig.user.id) {
<% if (!string.IsNullOrEmpty(History) && !string.IsNullOrEmpty(HistoryData))
{ %>
config.events['onRequestHistory'] = function () { // the user is trying to show the document version history
docEditor.refreshHistory(<%= History %>); // show the document version history
};
config.events['onRequestHistoryData'] = function (event) { // the user is trying to click the specific document version in the document version history
var ver = event.data;
var histData = <%= HistoryData %>;
docEditor.setHistoryData(histData[ver - 1]); // send the link to the document for viewing the version history
};
config.events['onRequestHistoryClose '] = function () { // the user is trying to go back to the document from viewing the document version history
document.location.reload();
};
<% } %>
// add mentions for not anonymous users
<% if (!string.IsNullOrEmpty(UsersForMentions))
{ %>
config.events['onRequestUsers'] = function () {
docEditor.setUsers({ // set a list of users to mention in the comments
"users": <%= UsersForMentions %>
});
};
<% } %>
// the user is mentioned in a comment
config.events['onRequestSendNotify'] = function (event) {
event.data.actionLink = replaceActionLink(location.href, JSON.stringify(event.data.actionLink));
var data = JSON.stringify(event.data);
innerAlert("onRequestSendNotify: " + data);
};
// prevent file renaming for anonymous users
config.events['onRequestRename'] = onRequestRename;
}
<% if (!string.IsNullOrEmpty(UsersForMentions))
{ %>
// add mentions for not anonymous users
config.events['onRequestUsers'] = function () {
docEditor.setUsers({ // set a list of users to mention in the comments
"users": <%= UsersForMentions %>
});
};
// the user is mentioned in a comment
config.events['onRequestSendNotify'] = function (event) {
event.data.actionLink = replaceActionLink(location.href, event.data.actionLink);
var data = JSON.stringify(event.data);
innerAlert("onRequestSendNotify: " + data);
};
<% } %>
if (config.editorConfig.createUrl) {
config.events.onRequestSaveAs = onRequestSaveAs;
};

1
web/documentserver-example/csharp/DocEditor.aspx.cs Normal file → Executable file
View File

@ -256,6 +256,7 @@ namespace OnlineEditorsExample
"customization", new Dictionary<string, object>
{
{ "about", true }, // the About section display
{ "comments", true },
{ "feedback", true }, // the Feedback & Support menu button display
{ "forcesave", false }, // adds the request for the forced file saving to the callback handler
{ "submitForm", submitForm }, // if the Submit form button is displayed or not

View File

@ -145,11 +145,7 @@ namespace ASC.Api.DocumentConverter
requestStream.Write(bytes, 0, bytes.Length); // and write the serialized body object to it
}
// hack. http://ubuntuforums.org/showthread.php?t=1841740
if (_Default.IsMono)
{
ServicePointManager.ServerCertificateValidationCallback += (s, ce, ca, p) => true;
}
_Default.VerifySSL();
string dataResponse;
using (var response = request.GetResponse())

View File

@ -72,3 +72,12 @@ Configure the IIS components for the server to work correctly:
In case the example and Document Server are installed on different computers, make sure that your server with the example installed has access to the Document Server with the address which you specify instead of **documentserver** in the configuration files.
Make sure that the Document Server in its turn has access to the server with the example installed with the address which you specify instead of **example.com** in the configuration files.
## Important security info
Please keep in mind the following security aspects when you are using test examples:
* There is no protection of the storage from unauthorized access since there is no need for authorization.
* There are no checks against parameter substitution in links, since the parameters are generated by the code according to the pre-arranged scripts.
* There are no data checks in requests of saving the file after editing, since each test example is intended for requests only from ONLYOFFICE Document Server.
* There are no prohibitions on using test examples from other sites, since they are intended to interact with ONLYOFFICE Document Server from another domain.

View File

@ -78,7 +78,9 @@ namespace OnlineEditorsExample
if (token != null && !token.Equals("")) // invalid signature error
{
fileData = (Dictionary<string, object>)jss.Deserialize<Dictionary<string, object>>(token)["payload"];
fileData = jss.Deserialize<Dictionary<string, object>>(token);
if (fileData.ContainsKey("payload"))
fileData = (Dictionary<string, object>)fileData["payload"];
}
else
{
@ -128,11 +130,7 @@ namespace OnlineEditorsExample
}
}
// hack. http://ubuntuforums.org/showthread.php?t=1841740
if (_Default.IsMono)
{
ServicePointManager.ServerCertificateValidationCallback += (s, ce, ca, p) => true;
}
_Default.VerifySSL();
var storagePath = _Default.StoragePath(newFileName, userAddress); // get the file path
var histDir = _Default.HistoryDir(storagePath); // get the path to the history directory
@ -209,11 +207,7 @@ namespace OnlineEditorsExample
}
}
// hack. http://ubuntuforums.org/showthread.php?t=1841740
if (_Default.IsMono)
{
ServicePointManager.ServerCertificateValidationCallback += (s, ce, ca, p) => true;
}
_Default.VerifySSL();
string forcesavePath = "";
Boolean isSubmitForm = fileData["forcesavetype"].ToString().Equals("3"); // SubmitForm
@ -258,8 +252,10 @@ namespace OnlineEditorsExample
}
// create a command request
public static void commandRequest(string method, string key)
public static void commandRequest(string method, string key, object meta = null)
{
_Default.VerifySSL();
string documentCommandUrl = WebConfigurationManager.AppSettings["files.docservice.url.site"] + WebConfigurationManager.AppSettings["files.docservice.url.command"];
var request = (HttpWebRequest)WebRequest.Create(documentCommandUrl);
@ -271,13 +267,18 @@ namespace OnlineEditorsExample
{ "key", key }
};
if (meta != null)
{
body.Add("meta", meta);
}
// check if a secret key to generate token exists or not
if (JwtManager.Enabled)
{
var payload = new Dictionary<string, object>
{
{ "payload", body }
};
{
{ "payload", body }
};
var payloadToken = JwtManager.Encode(payload); // encode a payload object into a header token
var bodyToken = JwtManager.Encode(body); // encode body into a body token

View File

@ -65,7 +65,8 @@ namespace OnlineEditorsExample
"The file favorite state is undefined",
"Can't mention others in comments",
"Can't create new files from the editor",
"Cant see anyones information"
"Cant see anyones information",
"Can't rename files from the editor"
};
private static List<User> users = new List<User>() {

View File

@ -68,6 +68,9 @@ namespace OnlineEditorsExample
case "saveas":
SaveAs(context);
break;
case "rename":
Rename(context);
break;
}
}
@ -368,5 +371,34 @@ namespace OnlineEditorsExample
context.Response.Write("{ \"error\": \"File not found!\"}");
}
}
// rename a file
private static void Rename(HttpContext context)
{
string fileData;
try
{
using (var receiveStream = context.Request.InputStream)
using (var readStream = new StreamReader(receiveStream))
{
fileData = readStream.ReadToEnd();
if (string.IsNullOrEmpty(fileData)) return;
}
}
catch (Exception e)
{
throw new HttpException((int)HttpStatusCode.BadRequest, e.Message);
}
var jss = new JavaScriptSerializer();
var body = jss.Deserialize<Dictionary<string, object>>(fileData);
var newFileName = (string) body["newfilename"];
var docKey = (string) body["dockey"];
var meta = new Dictionary<string, object>() {
{ "title", newFileName }
};
TrackManager.commandRequest("meta", docKey, meta);
context.Response.Write("{ \"result\": \"OK\"}");
}
}
}

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8" ?>
<?xml version="1.0" encoding="utf-8" ?>
<appSettings>
<clear />
<add key="version" value="1.1.0"/>
<add key="version" value="1.2.0"/>
<add key="filesize-max" value="52428800"/>
<add key="storage-path" value=""/>
@ -13,6 +13,9 @@
<add key="files.docservice.timeout" value="120000" />
<add key="files.docservice.secret" value="" />
<add key="files.docservice.header" value="Authorization" />
<add key="files.docservice.verify-peer-off" value="true"/>
<add key="files.docservice.languages" value="en:English|az:Azerbaijani|be:Belarusian|bg:Bulgarian|ca:Catalan|zh:Chinese|cs:Czech|da:Danish|nl:Dutch|fi:Finnish|fr:French|gl:Galego|de:German|el:Greek|hu:Hungarian|id:Indonesian|it:Italian|ja:Japanese|ko:Korean|lv:Latvian|lo:Lao|nb:Norwegian|pl:Polish|pt:Portuguese|ro:Romanian|ru:Russian|sk:Slovak|sl:Slovenian|es:Spanish|sv:Swedish|tr:Turkish|uk:Ukrainian|vi:Vietnamese"/>
<add key="files.docservice.url.site" value="http://documentserver/"/>

View File

@ -236,3 +236,12 @@ Make sure that the Document Server has access to the server with the example ins
```
http://server.address:server.port/
```
## Important security info
Please keep in mind the following security aspects when you are using test examples:
* There is no protection of the storage from unauthorized access since there is no need for authorization.
* There are no checks against parameter substitution in links, since the parameters are generated by the code according to the pre-arranged scripts.
* There are no data checks in requests of saving the file after editing, since each test example is intended for requests only from ONLYOFFICE Document Server.
* There are no prohibitions on using test examples from other sites, since they are intended to interact with ONLYOFFICE Document Server from another domain.

View File

@ -41,7 +41,8 @@ public class ExampleData {
"The file favorite state is undefined",
"Can't mention others in comments",
"Can't create new files from the editor",
"Cant see anyones information"
"Cant see anyones information",
"Can't rename files from the editor"
);
List<String> description_user_1 = List.of( // the description for user 1
"File author by default",

View File

@ -30,15 +30,23 @@ import org.springframework.context.annotation.Configuration;
import javax.annotation.PostConstruct;
import com.onlyoffice.integration.documentserver.util.SSLUtils;
@Configuration
public class IntegrationConfiguration {
@Value("${files.storage}")
private String storageAddress;
@Value("${files.docservice.verify-peer-off}")
private String verifyPerrOff;
@Autowired
private FileStoragePathBuilder storagePathBuilder;
@Autowired
private SSLUtils ssl;
@Bean
public ModelMapper mapper(){ // create the model mapper
ModelMapper mapper = new ModelMapper();
@ -58,6 +66,17 @@ public class IntegrationConfiguration {
@PostConstruct
public void init(){ // initialize the storage path builder
storagePathBuilder.configure(storageAddress.isBlank() ? null : storageAddress);
if(!verifyPerrOff.isEmpty()) {
try{
if(verifyPerrOff.equals("true")) {
ssl.turnOffSslChecking(); //the certificate will be ignored
} else {
ssl.turnOnSslChecking(); //the certificate will be verified
}
} catch(Exception e) {
e.printStackTrace();
}
}
}
@Bean

View File

@ -31,6 +31,7 @@ import com.onlyoffice.integration.services.UserServices;
import com.onlyoffice.integration.documentserver.util.file.FileUtility;
import com.onlyoffice.integration.documentserver.util.service.ServiceConverter;
import com.onlyoffice.integration.documentserver.managers.document.DocumentManager;
import com.onlyoffice.integration.documentserver.managers.callback.CallbackManager;
import org.json.simple.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
@ -61,6 +62,12 @@ public class FileController {
@Value("${filesize-max}")
private String filesizeMax;
@Value("${files.docservice.url.site}")
private String docserviceUrlSite;
@Value("${files.docservice.url.command}")
private String docserviceUrlCommand;
@Autowired
private FileUtility fileUtility;
@Autowired
@ -79,6 +86,8 @@ public class FileController {
private ObjectMapper objectMapper;
@Autowired
private ServiceConverter serviceConverter;
@Autowired
private CallbackManager callbackManager;
// create user metadata
private String createUserMetadata(String uid, String fullFileName) {
@ -356,4 +365,22 @@ public class FileController {
return "{ \"error\" : 1, \"message\" : \"" + e.getMessage() + "\"}";
}
}
@PostMapping("/rename")
@ResponseBody
public String rename(@RequestBody JSONObject body) {
String newfilename = (String) body.get("newfilename");
String dockey = (String) body.get("dockey");
HashMap<String, String> meta = new HashMap<>();
meta.put("title", newfilename);
try {
callbackManager.commandRequest("meta", dockey, meta);
return "result ok";
} catch (Exception e) {
e.printStackTrace();
return e.getMessage();
}
}
}

View File

@ -64,6 +64,9 @@ public class IndexController {
@Value("${url.editor}")
private String urlEditor;
@Value("${files.docservice.languages}")
private String langs;
@GetMapping("${url.index}")
public String index(Model model){
java.io.File[] files = storageMutator.getStoredFiles(); // get all the stored files from the storage
@ -71,6 +74,14 @@ public class IndexController {
List<Boolean> filesEditable = new ArrayList<>();
List<String> versions = new ArrayList<>();
List<Boolean> isFillFormDoc = new ArrayList<>();
List<String> langsAndKeys = Arrays.asList(langs.split("\\|"));
Map<String, String> languages = new HashMap<>();
langsAndKeys.forEach((str) -> {
String[] couple = str.split(":");
languages.put(couple[0], couple[1]);
});
List<User> users = userService.findAll(); // get a list of all the users
@ -95,6 +106,7 @@ public class IndexController {
model.addAttribute("datadocs", docserviceSite+docservicePreloader);
model.addAttribute("tooltip", tooltip);
model.addAttribute("users", users);
model.addAttribute("languages", languages);
return "index.html";
}

View File

@ -39,7 +39,7 @@ public class EditCallback implements Callback {
if (!body.getUsers().contains(user)) { // if this user is not specified in the body
String key = body.getKey(); // get document key
try {
callbackManager.commandRequest("forcesave", key); // create a command request to forcibly save the document being edited without closing it
callbackManager.commandRequest("forcesave", key, null); // create a command request to forcibly save the document being edited without closing it
} catch (Exception e) {
e.printStackTrace();
result = 1;

View File

@ -19,9 +19,10 @@
package com.onlyoffice.integration.documentserver.managers.callback;
import com.onlyoffice.integration.dto.Track;
import java.util.HashMap;
public interface CallbackManager { // specify the callback manager functions
void processSave(Track body, String fileName); // file saving process
void commandRequest(String method, String key); // create a command request
void commandRequest(String method, String key, HashMap meta); // create a command request
void processForceSave(Track body, String fileName); // file force saving process
}

View File

@ -153,16 +153,20 @@ public class DefaultCallbackManager implements CallbackManager {
//TODO: Replace (String method) with (Enum method)
@SneakyThrows
public void commandRequest(String method, String key) { // create a command request
public void commandRequest(String method, String key, HashMap meta) { // create a command request
String DocumentCommandUrl = docserviceUrlSite + docserviceUrlCommand;
URL url = new URL(DocumentCommandUrl);
java.net.HttpURLConnection connection = (java.net.HttpURLConnection) url.openConnection();
HashMap<String, Object> params = new HashMap<>();
HashMap<String, Object> params = new HashMap<String, Object>();
params.put("c", method);
params.put("key", key);
if (meta != null) {
params.put("meta", meta);
}
String headerToken;
if (jwtManager.tokenEnabled()) // check if a secret key to generate token exists or not
{

View File

@ -34,7 +34,6 @@ public class Customization { // the parameters which allow to customize the edi
@Autowired
private Goback goback; // the settings for the Open file location menu button and upper right corner button
private Boolean autosave = true; // if the Autosave menu option is enabled or disabled
private Boolean chat = true; // if the Chat menu button is displayed or hidden
private Boolean comments = true; // if the Comments menu button is displayed or hidden
private Boolean compactHeader = false; // if the additional action buttons are displayed in the upper part of the editor window header next to the logo (false) or in the toolbar (true)
private Boolean compactToolbar = false; // if the top toolbar type displayed is full (false) or compact (true)

View File

@ -49,5 +49,7 @@ public enum Language {
es,
tr,
uk,
vi
vi,
gl,
az
}

View File

@ -0,0 +1,59 @@
package com.onlyoffice.integration.documentserver.util;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.X509Certificate;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import org.springframework.stereotype.Component;
/**
* Disables and enables certificate and host-name checking in
* HttpsURLConnection, the default JVM implementation of the HTTPS/TLS protocol.
* Has no effect on implementations such as Apache Http Client, Ok Http.
*/
@Component
public final class SSLUtils {
private final HostnameVerifier jvmHostnameVerifier = HttpsURLConnection.getDefaultHostnameVerifier();
private final HostnameVerifier trivialHostnameVerifier = new HostnameVerifier() {
public boolean verify(String hostname, SSLSession sslSession) {
return true;
}
};
private final TrustManager[] UNQUESTIONING_TRUST_MANAGER = new TrustManager[] { new X509TrustManager() {
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return null;
}
public void checkClientTrusted(X509Certificate[] certs, String authType) {
}
public void checkServerTrusted(X509Certificate[] certs, String authType) {
}
} };
public void turnOffSslChecking() throws NoSuchAlgorithmException, KeyManagementException {
HttpsURLConnection.setDefaultHostnameVerifier(trivialHostnameVerifier);
// Install the all-trusting trust manager
SSLContext sc = SSLContext.getInstance("SSL");
sc.init(null, UNQUESTIONING_TRUST_MANAGER, null);
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
}
public void turnOnSslChecking() throws KeyManagementException, NoSuchAlgorithmException {
HttpsURLConnection.setDefaultHostnameVerifier(jvmHostnameVerifier);
// Return it to the initial state (discovered by reflection, now hardcoded)
SSLContext sc = SSLContext.getInstance("SSL");
sc.init(null, null, null);
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
}
}

View File

@ -1,4 +1,4 @@
server.version=1.1.0
server.version=1.2.0
server.address=
server.port=4000
@ -25,6 +25,10 @@ files.docservice.url.example=
files.docservice.secret=
files.docservice.header=Authorization
files.docservice.verify-peer-off=true
files.docservice.languages=en:English|az:Azerbaijani|be:Belarusian|bg:Bulgarian|ca:Catalan|zh:Chinese|cs:Czech|da:Danish|nl:Dutch|fi:Finnish|fr:French|gl:Galego|de:German|el:Greek|hu:Hungarian|id:Indonesian|it:Italian|ja:Japanese|ko:Korean|lv:Latvian|lo:Lao|nb:Norwegian|pl:Polish|pt:Portuguese|ro:Romanian|ru:Russian|sk:Slovak|sl:Slovenian|es:Spanish|sv:Swedish|tr:Turkish|uk:Ukrainian|vi:Vietnamese
spring.datasource.url=jdbc:h2:mem:usersdb
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.username=sa

View File

@ -30,6 +30,7 @@
<script th:inline="javascript">
var docEditor;
var config;
var innerAlert = function (message, inEditor) {
if (console && console.log)
@ -90,10 +91,13 @@
// the meta information of the document is changed via the meta command
var onMetaChange = function (event) {
var favorite = !!event.data.favorite;
var title = document.title.replace(/^\☆/g, "");
document.title = (favorite ? "☆" : "") + title;
docEditor.setFavorite(favorite);
if (event.data.favorite) {
var favorite = !!event.data.favorite;
var title = document.title.replace(/^\☆/g, "");
document.title = (favorite ? "☆" : "") + title;
docEditor.setFavorite(favorite);
}
innerAlert("onMetaChange: " + JSON.stringify(event.data));
};
@ -115,7 +119,7 @@
docEditor.setMailMergeRecipients([[${dataMailMergeRecipients}]]);
};
var config = [[${model}]];
config = [[${model}]];
if (config.editorConfig.user.name == "Anonymous") {
config.editorConfig.user.name = "";
@ -130,7 +134,7 @@
};
let xhr = new XMLHttpRequest();
xhr.open("POST", "saveas");
xhr.setRequestHeader( 'Content-Type', 'application/json');
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.send(JSON.stringify(data));
xhr.onload = function () {
innerAlert(xhr.responseText);
@ -138,6 +142,23 @@
}
};
var onRequestRename = function(event) { // the user is trying to rename file by clicking Rename... button
innerAlert("onRequestRename: " + JSON.stringify(event.data));
var newfilename = event.data;
var data = {
newfilename: newfilename,
dockey: config.document.key,
};
let xhr = new XMLHttpRequest();
xhr.open("POST", "rename");
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.send(JSON.stringify(data));
xhr.onload = function () {
innerAlert(xhr.responseText);
}
};
config.width = "100%";
config.height = "100%";
config.events = {
@ -158,24 +179,23 @@
var historyData = histArray[1];
var usersForMentions = [[${usersForMentions}]];
if (hist && historyData) {
// the user is trying to show the document version history
config.events['onRequestHistory'] = function () {
docEditor.refreshHistory(JSON.parse(hist)); // show the document version history
};
// the user is trying to click the specific document version in the document version history
config.events['onRequestHistoryData'] = function (event) {
var ver = event.data;
var histData = historyData;
docEditor.setHistoryData(JSON.parse(histData)[ver - 1]); // send the link to the document for viewing the version history
};
// the user is trying to go back to the document from viewing the document version history
config.events['onRequestHistoryClose'] = function () {
document.location.reload();
};
}
if(usersForMentions){
if (config.editorConfig.user.id != 4) {
if (hist && historyData) {
// the user is trying to show the document version history
config.events['onRequestHistory'] = function () {
docEditor.refreshHistory(JSON.parse(hist)); // show the document version history
};
// the user is trying to click the specific document version in the document version history
config.events['onRequestHistoryData'] = function (event) {
var ver = event.data;
var histData = historyData;
docEditor.setHistoryData(JSON.parse(histData)[ver - 1]); // send the link to the document for viewing the version history
};
// the user is trying to go back to the document from viewing the document version history
config.events['onRequestHistoryClose'] = function () {
document.location.reload();
};
}
// add mentions for not anonymous users
config.events['onRequestUsers'] = function () {
docEditor.setUsers({ // set a list of users to mention in the comments
@ -184,10 +204,12 @@
};
// the user is mentioned in a comment
config.events['onRequestSendNotify'] = function (event) {
event.data.actionLink = replaceActionLink(location.href, event.data.actionLink);
event.data.actionLink = replaceActionLink(location.href, JSON.stringify(event.data.actionLink));
var data = JSON.stringify(event.data);
innerAlert("onRequestSendNotify: " + data);
};
// prevent file renaming for anonymous users
config.events['onRequestRename'] = onRequestRename;
}
if (config.editorConfig.createUrl) {

View File

@ -87,37 +87,9 @@
<td valign="middle">
<span class="select-user">Language editors interface</span>
<select class="select-user" id="language">
<option value="en" selected="selected">English</option>
<option value="be">Belarusian</option>
<option value="bg">Bulgarian</option>
<option value="ca">Catalan</option>
<option value="zh">Chinese</option>
<option value="cs">Czech</option>
<option value="da">Danish</option>
<option value="nl">Dutch</option>
<option value="fi">Finnish</option>
<option value="fr">French</option>
<option value="de">German</option>
<option value="el">Greek</option>
<option value="hu">Hungarian</option>
<option value="id">Indonesian</option>
<option value="it">Italian</option>
<option value="ja">Japanese</option>
<option value="ko">Korean</option>
<option value="lv">Latvian</option>
<option value="lo">Lao</option>
<option value="nb">Norwegian</option>
<option value="pl">Polish</option>
<option value="pt">Portuguese</option>
<option value="ro">Romanian</option>
<option value="ru">Russian</option>
<option value="sk">Slovak</option>
<option value="sl">Slovenian</option>
<option value="sv">Swedish</option>
<option value="es">Spanish</option>
<option value="tr">Turkish</option>
<option value="uk">Ukrainian</option>
<option value="vi">Vietnamese</option>
<option th:each="language: ${languages}"
th:value="${language.key}"
th:text="${language.value}"/>
</select>
</td>
</tr>
@ -345,5 +317,10 @@
<script type="text/javascript" src="scripts/jquery.dropdownToggle.js"></script>
<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";
});
</script>
</body>
</html>

View File

@ -263,3 +263,12 @@ Make sure that the Document Server has access to the server with the example ins
```
4. After it, all the *bin* files will be passed to the *./target* folder.
## Important security info
Please keep in mind the following security aspects when you are using test examples:
* There is no protection of the storage from unauthorized access since there is no need for authorization.
* There are no checks against parameter substitution in links, since the parameters are generated by the code according to the pre-arranged scripts.
* There are no data checks in requests of saving the file after editing, since each test example is intended for requests only from ONLYOFFICE Document Server.
* There are no prohibitions on using test examples from other sites, since they are intended to interact with ONLYOFFICE Document Server from another domain.

View File

@ -29,6 +29,7 @@ import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import helpers.*;
public class GlobalServletContextListener implements ServletContextListener
{
@ -70,16 +71,19 @@ public class GlobalServletContextListener implements ServletContextListener
SSLContext sc;
try
{
// register the all-trusting trust manager for HTTPS
sc = SSLContext.getInstance("SSL");
sc.init(null, trustAllCerts, new java.security.SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
}
catch (NoSuchAlgorithmException | KeyManagementException ex)
{
if(!ConfigManager.GetProperty("files.docservice.verify-peer-off").isEmpty()) {
try
{
// register the all-trusting trust manager for HTTPS
sc = SSLContext.getInstance("SSL");
sc.init(null, trustAllCerts, new java.security.SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
}
catch (NoSuchAlgorithmException | KeyManagementException ex)
{
}
}
// create all-trusting host name verifier
HostnameVerifier allHostsValid = new HostnameVerifier()

View File

@ -29,6 +29,8 @@ import java.util.*;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.charset.StandardCharsets;
import javax.servlet.ServletException;
import javax.servlet.annotation.MultipartConfig;
import javax.servlet.annotation.WebServlet;
@ -36,7 +38,9 @@ import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.Part;
import entities.FileType;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
@ -45,6 +49,7 @@ import org.primeframework.jwt.Verifier;
import org.primeframework.jwt.domain.JWT;
import org.primeframework.jwt.hmac.HMACVerifier;
@WebServlet(name = "IndexServlet", urlPatterns = {"/IndexServlet"})
@MultipartConfig
public class IndexServlet extends HttpServlet
@ -97,6 +102,9 @@ public class IndexServlet extends HttpServlet
case "saveas":
SaveAs(request, response, writer);
break;
case "rename":
Rename(request, response, writer);
break;
}
}
@ -321,7 +329,7 @@ public class IndexServlet extends HttpServlet
if (users.indexOf(user) == -1) {
String key = (String) body.get("key");
try {
TrackManager.commandRequest("forcesave", key); // create a command request with the forcesave method
TrackManager.commandRequest("forcesave", key, null); // create a command request with the forcesave method
} catch (Exception e) {
e.printStackTrace();
}
@ -551,6 +559,32 @@ public class IndexServlet extends HttpServlet
}
}
// rename a file
private static void Rename(HttpServletRequest request, HttpServletResponse response, PrintWriter writer) {
try {
Scanner scanner = new Scanner(request.getInputStream());
scanner.useDelimiter("\\A");
String bodyString = scanner.hasNext() ? scanner.next() : "";
scanner.close();
JSONParser parser = new JSONParser();
JSONObject body = (JSONObject) parser.parse(bodyString);
String newfilename = (String) body.get("newfilename");
String dockey = (String) body.get("dockey");
HashMap<String, String> meta = new HashMap<>();
meta.put("title", newfilename);
TrackManager.commandRequest("meta", dockey, meta);
} catch (Exception e) {
e.printStackTrace();
writer.write("{ \"error\" : 1, \"message\" : \"" + e.getMessage() + "\"}");
}
}
// process get request
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException

View File

@ -348,14 +348,12 @@ public class FileModel
public Boolean forcesave;
public Boolean submitForm;
public Boolean about;
public Boolean chat;
public Boolean comments;
public Boolean feedback;
public Customization()
{
about = true;
chat = true;
comments = true;
feedback = true;
forcesave = false;

View File

@ -568,4 +568,19 @@ public class DocumentManager
{
return ConfigManager.GetProperty("files.docservice.secret");
}
// get languages
public static Map<String, String> GetLanguages()
{
String langs = ConfigManager.GetProperty("files.docservice.languages");
List<String> langsAndKeys = Arrays.asList(langs.split("\\|"));
Map<String, String> languages = new HashMap<>();
langsAndKeys.forEach((str) -> {
String[] couple = str.split(":");
languages.put(couple[0], couple[1]);
});
return languages;
}
}

View File

@ -277,7 +277,7 @@ public class TrackManager {
}
// create a command request
public static void commandRequest(String method, String key) throws Exception {
public static void commandRequest(String method, String key, HashMap meta) throws Exception {
String DocumentCommandUrl = ConfigManager.GetProperty("files.docservice.url.site") + ConfigManager.GetProperty("files.docservice.url.command");
URL url = new URL(DocumentCommandUrl);
@ -287,6 +287,10 @@ public class TrackManager {
params.put("c", method);
params.put("key", key);
if (meta != null) {
params.put("meta", meta);
}
String headerToken = "";
if (DocumentManager.TokenEnabled()) // check if a secret key to generate token exists or not
{
@ -314,7 +318,7 @@ public class TrackManager {
try (OutputStream os = connection.getOutputStream()) {
os.write(bodyByte); // write bytes to the output stream
}
InputStream stream = connection.getInputStream();; // get input stream
InputStream stream = connection.getInputStream(); // get input stream
if (stream == null)
throw new Exception("Could not get an answer");

View File

@ -64,6 +64,7 @@ public class Users {
add("Can't mention others in comments");
add("Can't create new files from the editor");
add("Cant see anyones information");
add("Can't rename files from the editor");
}};
private static List<User> users = new ArrayList<User>() {{

View File

@ -1,4 +1,4 @@
version=1.1.0
version=1.2.0
filesize-max=5242880
storage-folder=app_data
@ -16,5 +16,9 @@ files.docservice.url.api=web-apps/apps/api/documents/api.js
files.docservice.url.preloader=web-apps/apps/api/documents/cache-scripts.html
files.docservice.url.example=
files.docservice.languages=en:English|az:Azerbaijani|be:Belarusian|bg:Bulgarian|ca:Catalan|zh:Chinese|cs:Czech|da:Danish|nl:Dutch|fi:Finnish|fr:French|gl:Galego|de:German|el:Greek|hu:Hungarian|id:Indonesian|it:Italian|ja:Japanese|ko:Korean|lv:Latvian|lo:Lao|nb:Norwegian|pl:Polish|pt:Portuguese|ro:Romanian|ru:Russian|sk:Slovak|sl:Slovenian|es:Spanish|sv:Swedish|tr:Turkish|uk:Ukrainian|vi:Vietnamese
files.docservice.secret=
files.docservice.header=Authorization
files.docservice.header=Authorization
files.docservice.verify-peer-off=TRUE

View File

@ -36,6 +36,7 @@
<script type="text/javascript" language="javascript">
var docEditor;
var config;
var innerAlert = function (message, inEditor) {
if (console && console.log)
@ -97,10 +98,14 @@
// the meta information of the document is changed via the meta command
var onMetaChange = function (event) {
var favorite = !!event.data.favorite;
var title = document.title.replace(/^\☆/g, "");
document.title = (favorite ? "☆" : "") + title;
docEditor.setFavorite(favorite); // change the Favorite icon state
if (event.data.favorite) {
var favorite = !!event.data.favorite;
var title = document.title.replace(/^\☆/g, "");
document.title = (favorite ? "☆" : "") + title;
docEditor.setFavorite(favorite); // change the Favorite icon state
}
innerAlert("onMetaChange: " + JSON.stringify(event.data));
};
// the user is trying to insert an image by clicking the Image from Storage button
@ -130,7 +135,7 @@
};
let xhr = new XMLHttpRequest();
xhr.open("POST", "IndexServlet?type=saveas");
xhr.setRequestHeader( 'Content-Type', 'application/json');
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.send(JSON.stringify(data));
xhr.onload = function () {
innerAlert(xhr.responseText);
@ -138,7 +143,24 @@
}
};
var config = JSON.parse('<%= FileModel.Serialize(Model) %>');
var onRequestRename = function(event) { // the user is trying to rename file by clicking Rename... button
innerAlert("onRequestRename: " + JSON.stringify(event.data));
var newfilename = event.data;
var data = {
newfilename: newfilename,
dockey: config.document.key,
};
let xhr = new XMLHttpRequest();
xhr.open("POST", "IndexServlet?type=rename");
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.send(JSON.stringify(data));
xhr.onload = function () {
innerAlert(xhr.responseText);
}
};
config = JSON.parse('<%= FileModel.Serialize(Model) %>');
config.width = "100%";
config.height = "100%";
config.events = {
@ -161,37 +183,38 @@
String usersForMentions = (String) request.getAttribute("usersForMentions");
%>
<% if (!history.isEmpty() && !historyData.isEmpty()) { %>
// the user is trying to show the document version history
config.events['onRequestHistory'] = function () {
docEditor.refreshHistory(<%= history %>); // show the document version history
};
// the user is trying to click the specific document version in the document version history
config.events['onRequestHistoryData'] = function (event) {
var ver = event.data;
var histData = <%= historyData %>;
docEditor.setHistoryData(histData[ver - 1]); // send the link to the document for viewing the version history
};
// the user is trying to go back to the document from viewing the document version history
config.events['onRequestHistoryClose'] = function () {
document.location.reload();
};
<% } %>
<% if (usersForMentions != null) { %>
if (config.editorConfig.user.id) {
<% if (!history.isEmpty() && !historyData.isEmpty()) { %>
// the user is trying to show the document version history
config.events['onRequestHistory'] = function () {
docEditor.refreshHistory(<%= history %>); // show the document version history
};
// the user is trying to click the specific document version in the document version history
config.events['onRequestHistoryData'] = function (event) {
var ver = event.data;
var histData = <%= historyData %>;
docEditor.setHistoryData(histData[ver - 1]); // send the link to the document for viewing the version history
};
// the user is trying to go back to the document from viewing the document version history
config.events['onRequestHistoryClose'] = function () {
document.location.reload();
};
<% } %>
// add mentions for not anonymous users
config.events['onRequestUsers'] = function () {
docEditor.setUsers({ // set a list of users to mention in the comments
"users": ${usersForMentions}
"users": <%=usersForMentions%>
});
};
// the user is mentioned in a comment
config.events['onRequestSendNotify'] = function (event) {
event.data.actionLink = replaceActionLink(location.href, event.data.actionLink);
event.data.actionLink = replaceActionLink(location.href, JSON.stringify(event.data.actionLink));
var data = JSON.stringify(event.data);
innerAlert("onRequestSendNotify: " + data);
};
<% } %>
// prevent file renaming for anonymous users
config.events['onRequestRename'] = onRequestRename;
}
if (config.editorConfig.createUrl) {
config.events.onRequestSaveAs = onRequestSaveAs;

View File

@ -4,6 +4,8 @@
<%@page import="java.util.Calendar"%>
<%@page import="java.io.File"%>
<%@page import="java.net.URLEncoder"%>
<%@page import="java.util.Map.Entry"%>
<%@page import="java.util.Map"%>
<%@page import="helpers.Users"%>
<%@page import="entities.User"%>
@ -97,37 +99,10 @@
<td valign="middle">
<span class="select-user">Language editors interface</span>
<select class="select-user" id="language">
<option value="en">English</option>
<option value="be">Belarusian</option>
<option value="bg">Bulgarian</option>
<option value="ca">Catalan</option>
<option value="zh">Chinese</option>
<option value="cs">Czech</option>
<option value="da">Danish</option>
<option value="nl">Dutch</option>
<option value="fi">Finnish</option>
<option value="fr">French</option>
<option value="de">German</option>
<option value="el">Greek</option>
<option value="hu">Hungarian</option>
<option value="id">Indonesian</option>
<option value="it">Italian</option>
<option value="ja">Japanese</option>
<option value="ko">Korean</option>
<option value="lv">Latvian</option>
<option value="lo">Lao</option>
<option value="nb">Norwegian</option>
<option value="pl">Polish</option>
<option value="pt">Portuguese</option>
<option value="ro">Romanian</option>
<option value="ru">Russian</option>
<option value="sk">Slovak</option>
<option value="sl">Slovenian</option>
<option value="sv">Swedish</option>
<option value="es">Spanish</option>
<option value="tr">Turkish</option>
<option value="uk">Ukrainian</option>
<option value="vi">Vietnamese</option>
<% Map<String, String> languages = DocumentManager.GetLanguages(); %>
<% for (Map.Entry<String, String> language : languages.entrySet()) { %>
<option value="<%=language.getKey()%>"><%=language.getValue()%></option>
<% } %>
</select>
</td>
</tr>
@ -373,7 +348,10 @@
var EditedExtList = "<%= String.join(",", DocumentManager.GetEditedExts()) %>";
var UrlConverter = "IndexServlet?type=convert";
var UrlEditor = "EditorServlet";
</script>
document.addEventListener('DOMContentLoaded', function(){
document.getElementById("language").value="en";
});
</script>
</body>
</html>

View File

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

View File

@ -146,3 +146,12 @@ See the detailed guide to learn how to [install Document Server for Linux](https
In case the example and Document Server are installed on different computers, make sure that your server with the example installed has access to the Document Server with the address which you specify instead of **documentserver** in the configuration files.
Make sure that the Document Server has access to the server with the example installed with the address which you specify instead of **example.com** in the configuration files.
## Important security info
Please keep in mind the following security aspects when you are using test examples:
* There is no protection of the storage from unauthorized access since there is no need for authorization.
* There are no checks against parameter substitution in links, since the parameters are generated by the code according to the pre-arranged scripts.
* There are no data checks in requests of saving the file after editing, since each test example is intended for requests only from ONLYOFFICE Document Server.
* There are no prohibitions on using test examples from other sites, since they are intended to interact with ONLYOFFICE Document Server from another domain.

23
web/documentserver-example/nodejs/app.js Normal file → Executable file
View File

@ -44,9 +44,11 @@ const cfgSignatureAuthorizationHeaderPrefix = configServer.get('token.authorizat
const cfgSignatureSecretExpiresIn = configServer.get('token.expiresIn');
const cfgSignatureSecret = configServer.get('token.secret');
const urllib = require("urllib");
const verifyPeerOff = configServer.get('verify_peer_off');
process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";
if(verifyPeerOff) {
process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";
}
String.prototype.hashCode = function () {
const len = this.length;
@ -70,6 +72,7 @@ String.prototype.format = function () {
const app = express(); // create an application object
app.disable("x-powered-by");
app.set("views", path.join(__dirname, "views")); // specify the path to the main template
app.set("view engine", "ejs"); // specify which template engine is used
@ -108,6 +111,7 @@ app.get("/", function (req, res) { // define a handler for default page
params: req.docManager.getCustomParams(),
users: users,
serverUrl: req.docManager.getServerUrl(),
languages: configServer.get('languages'),
});
}
@ -969,6 +973,21 @@ app.get("/editor", function (req, res) { // define a handler for editing docume
}
});
app.post("/rename", function (req, res) { //define a handler for renaming file
var newfilename = req.body.newfilename;
var dockey = req.body.dockey;
var meta = {title: newfilename};
var result = function(err, data, ress) {
res.writeHead(200, {"Content-Type": "application/json" });
res.write(JSON.stringify({ "result": ress }));
res.end();
};
documentService.commandRequest("meta", dockey, meta, result);
});
wopiApp.registerRoutes(app);
// "Not found" error with 404 status

View File

@ -1,5 +1,5 @@
{
"version": "1.1.0",
"version": "1.2.0",
"log": {
"appenders": [
{
@ -44,6 +44,42 @@
"authorizationHeaderPrefix": "Bearer ",
"secret": "secret",
"expiresIn": "5m"
},
"verify_peer_off": true,
"languages": {
"en": "English",
"az": "Azerbaijani",
"be": "Belarusian",
"bg": "Bulgarian",
"ca": "Catalan",
"zh": "Chinese",
"cs": "Czech",
"da": "Danish",
"nl": "Dutch",
"fi": "Finnish",
"fr": "French",
"gl": "Galego",
"de": "German",
"el": "Greek",
"hu": "Hungarian",
"id": "Indonesian",
"it": "Italian",
"ja": "Japanese",
"ko": "Korean",
"lv": "Latvian",
"lo": "Lao",
"nb": "Norwegian",
"pl": "Polish",
"pt": "Portuguese",
"ro": "Romanian",
"ru": "Russian",
"sk": "Slovak",
"sl": "Slovenian",
"es": "Spanish",
"sv": "Swedish",
"tr": "Turkish",
"uk": "Ukrainian",
"vi": "Vietnamese"
}
},
"plugins": {

View File

@ -385,8 +385,8 @@ docManager.prototype.getTemplateImageUrl = function (fileType) {
}
// get document key
docManager.prototype.getKey = function (fileName) {
const userAddress = this.curUserHostAddress();
docManager.prototype.getKey = function (fileName, userAddress) {
userAddress = userAddress || this.curUserHostAddress();
let key = userAddress + this.getlocalFileUri(fileName); // get document key by adding local file url to the current user host address
let historyPath = this.historyPath(fileName, userAddress); // get the path to the file history

View File

@ -168,13 +168,18 @@ documentService.getResponseUri = function (json) {
};
// create a command request
documentService.commandRequest = function (method, documentRevisionId, callback) {
documentService.commandRequest = function (method, documentRevisionId, meta = null, callback) {
documentRevisionId = documentService.generateRevisionId(documentRevisionId); // generate the document key value
var params = { // create a parameter object with command method and the document key value in it
params = { // create a parameter object with command method and the document key value in it
c: method,
key: documentRevisionId
};
if (meta) {
params.meta = meta;
}
var uri = siteUrl + configServer.get('commandUrl'); // get the absolute command url
var headers = { // create a headers object
'Content-Type': 'application/json'

View File

@ -22,7 +22,9 @@ var fileUtility = {};
fileUtility.getFileName = function (url, withoutExtension) {
if (!url) return "";
var parts = url.split("/");
var parts = url.split("\\");
parts = parts.pop();
parts = parts.split("/");
var fileName = parts.pop(); // get the file name from the last part of the url
fileName = fileName.split("?")[0];

View File

@ -59,6 +59,7 @@ var descr_user_0 = [
"Can't mention others in comments",
"Can't create new files from the editor",
"Cant see anyones information",
"Can't rename files from the editor",
//"Cant submit forms"
];

View File

@ -23,6 +23,7 @@ const fileSystem = require("fs");
const mime = require("mime");
const path = require("path");
const users = require("../users");
const docManager = require("../docManager");
const actionMapping = {};
actionMapping[reqConsts.requestType.GetFile] = getFile;
@ -255,8 +256,8 @@ function putFile(wopi, req, res, userHost) {
// return information about the file properties, access rights and editor settings
function checkFileInfo(wopi, req, res, userHost) {
let userAddress = req.docManager.curUserHostAddress(userHost);
let version = req.docManager.getKey(wopi.id);
let version = req.docManager.getKey(wopi.id, userAddress);
let path = req.docManager.storagePath(wopi.id, userAddress);
// add wopi query
var query = new URLSearchParams(wopi.accessToken);
@ -289,6 +290,7 @@ function returnLockMismatch(res, lock, reason) {
exports.fileRequestHandler = (req, res) => {
let userAddress = null;
req.docManager = new docManager(req, res);
if (req.params['id'].includes("@")) { // if there is the "@" sign in the id parameter
let split = req.params['id'].split("@"); // split this parameter by "@"
req.params['id'] = split[0]; // rewrite id with the first part of the split parameter
@ -310,5 +312,5 @@ exports.fileRequestHandler = (req, res) => {
return;
}
action(wopiData, req, res);
action(wopiData, req, res, userAddress);
}

View File

@ -83,6 +83,7 @@ exports.registerRoutes = function(app) {
convertExts: configServer.get('convertedDocs'),
editedExts: editedExts,
fillExts: fillExts,
languages: configServer.get('languages'),
});
} catch (ex) {

1
web/documentserver-example/nodejs/views/config.ejs Normal file → Executable file
View File

@ -48,7 +48,6 @@
},
"customization": {
"about": true,
"chat": true,
"comments": true,
"feedback": true,
"forcesave": false,

View File

@ -38,6 +38,7 @@
<script type="text/javascript" language="javascript">
var docEditor;
var config;
var innerAlert = function (message, inEditor) {
if (console && console.log)
@ -56,10 +57,14 @@
};
var onMetaChange = function (event) { // the meta information of the document is changed via the meta command
var favorite = !!event.data.favorite;
var title = document.title.replace(/^\☆/g, "");
document.title = (favorite ? "☆" : "") + title;
docEditor.setFavorite(favorite); // change the Favorite icon state
if (event.data.favorite) {
var favorite = !!event.data.favorite;
var title = document.title.replace(/^\☆/g, "");
document.title = (favorite ? "☆" : "") + title;
docEditor.setFavorite(favorite); // change the Favorite icon state
}
innerAlert("onMetaChange: " + JSON.stringify(event.data));
};
var onRequestEditRights = function () { // the user is trying to switch the document from the viewing into the editing mode
@ -141,7 +146,7 @@
};
var onRequestSendNotify = function(event) { // the user is mentioned in a comment
event.data.actionLink = replaceActionLink(location.href, event.data.actionLink);
event.data.actionLink = replaceActionLink(location.href, JSON.stringify(event.data.actionLink));
var data = JSON.stringify(event.data);
innerAlert("onRequestSendNotify: " + data);
};
@ -155,7 +160,7 @@
}
let xhr = new XMLHttpRequest();
xhr.open("POST", "create");
xhr.setRequestHeader( 'Content-Type', 'application/json');
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.send(JSON.stringify(data));
xhr.onload = function () {
innerAlert(xhr.responseText);
@ -163,15 +168,29 @@
}
}
var config = {<%- include("config") %>,
var onRequestRename = function(event) { // the user is trying to rename file by clicking Rename... button
innerAlert("onRequestRename: " + JSON.stringify(event.data));
var newfilename = event.data;
var data = {
newfilename: newfilename,
dockey: config.document.key,
};
let xhr = new XMLHttpRequest();
xhr.open("POST", "rename");
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.send(JSON.stringify(data));
xhr.onload = function () {
innerAlert(xhr.responseText);
}
};
config = {<%- include("config") %>,
events: {
"onAppReady": onAppReady,
"onDocumentStateChange": onDocumentStateChange,
"onRequestEditRights": onRequestEditRights,
"onError": onError,
"onRequestHistory": onRequestHistory,
"onRequestHistoryData": onRequestHistoryData,
"onRequestHistoryClose": onRequestHistoryClose,
"onOutdatedVersion": onOutdatedVersion,
"onMakeActionLink": onMakeActionLink,
"onMetaChange": onMetaChange,
@ -181,7 +200,11 @@
}
};
if (<%- JSON.stringify(usersForMentions) %> != null) {
if (<%- JSON.stringify(editor.userid) %> != null) {
config.events.onRequestHistory = onRequestHistory;
config.events.onRequestHistoryData = onRequestHistoryData;
config.events.onRequestHistoryClose = onRequestHistoryClose;
config.events.onRequestRename = onRequestRename;
config.events.onRequestUsers = onRequestUsers;
config.events.onRequestSendNotify = onRequestSendNotify;
}

34
web/documentserver-example/nodejs/views/index.ejs Normal file → Executable file
View File

@ -88,37 +88,9 @@
<td valign="middle">
<span class="select-user">Language editors interface</span>
<select class="select-user" id="language">
<option value="en">English</option>
<option value="be">Belarusian</option>
<option value="bg">Bulgarian</option>
<option value="ca">Catalan</option>
<option value="zh">Chinese</option>
<option value="cs">Czech</option>
<option value="da">Danish</option>
<option value="nl">Dutch</option>
<option value="fi">Finnish</option>
<option value="fr">French</option>
<option value="de">German</option>
<option value="el">Greek</option>
<option value="hu">Hungarian</option>
<option value="id">Indonesian</option>
<option value="it">Italian</option>
<option value="ja">Japanese</option>
<option value="ko">Korean</option>
<option value="lv">Latvian</option>
<option value="lo">Lao</option>
<option value="nb">Norwegian</option>
<option value="pl">Polish</option>
<option value="pt">Portuguese</option>
<option value="ro">Romanian</option>
<option value="ru">Russian</option>
<option value="sk">Slovak</option>
<option value="sl">Slovenian</option>
<option value="sv">Swedish</option>
<option value="es">Spanish</option>
<option value="tr">Turkish</option>
<option value="uk">Ukrainian</option>
<option value="vi">Vietnamese</option>
<% Object.keys(languages).forEach(key => { %>
<option value="<%= key %>"><%= languages[key] %></option>
<% }) %>
</select>
</td>
</tr>

34
web/documentserver-example/nodejs/views/wopiIndex.ejs Normal file → Executable file
View File

@ -89,37 +89,9 @@
<td valign="middle">
<span class="select-user">Language editors interface</span>
<select class="select-user" id="language">
<option value="en">English</option>
<option value="be">Belarusian</option>
<option value="bg">Bulgarian</option>
<option value="ca">Catalan</option>
<option value="zh">Chinese</option>
<option value="cs">Czech</option>
<option value="da">Danish</option>
<option value="nl">Dutch</option>
<option value="fi">Finnish</option>
<option value="fr">French</option>
<option value="de">German</option>
<option value="el">Greek</option>
<option value="hu">Hungarian</option>
<option value="id">Indonesian</option>
<option value="it">Italian</option>
<option value="ja">Japanese</option>
<option value="ko">Korean</option>
<option value="lv">Latvian</option>
<option value="lo">Lao</option>
<option value="nb">Norwegian</option>
<option value="pl">Polish</option>
<option value="pt">Portuguese</option>
<option value="ro">Romanian</option>
<option value="ru">Russian</option>
<option value="sk">Slovak</option>
<option value="sl">Slovenian</option>
<option value="sv">Swedish</option>
<option value="es">Spanish</option>
<option value="tr">Turkish</option>
<option value="uk">Ukrainian</option>
<option value="vi">Vietnamese</option>
<% Object.keys(languages).forEach(key => { %>
<option value="<%= key %>"><%= languages[key] %></option>
<% }) %>
</select>
</td>
</tr>

View File

@ -180,3 +180,12 @@ See the detailed guide to learn how to [install Document Server for Linux](https
In case the example and Document Server are installed on different computers, make sure that your server with the example installed has access to the Document Server with the address which you specify instead of **documentserver** in the configuration files.
Make sure that the Document Server has access to the server with the example installed with the address which you specify instead of **example.com** in the configuration files.
## Important security info
Please keep in mind the following security aspects when you are using test examples:
* There is no protection of the storage from unauthorized access since there is no need for authorization.
* There are no checks against parameter substitution in links, since the parameters are generated by the code according to the pre-arranged scripts.
* There are no data checks in requests of saving the file after editing, since each test example is intended for requests only from ONLYOFFICE Document Server.
* There are no prohibitions on using test examples from other sites, since they are intended to interact with ONLYOFFICE Document Server from another domain.

View File

@ -1,6 +1,6 @@
<?php
$GLOBALS['version'] = "1.1.0";
$GLOBALS['version'] = "1.2.0";
$GLOBALS['FILE_SIZE_MAX'] = 5242880;
$GLOBALS['STORAGE_PATH'] = "";
@ -24,6 +24,8 @@ $GLOBALS['DOC_SERV_COMMAND_URL'] = "coauthoring/CommandService.ashx";
$GLOBALS['DOC_SERV_JWT_SECRET'] = "";
$GLOBALS['DOC_SERV_JWT_HEADER'] = "Authorization";
$GLOBALS['DOC_SERV_VERIFY_PEER_OFF'] = TRUE;
$GLOBALS['EXAMPLE_URL'] = "";
$GLOBALS['MOBILE_REGEX'] = "android|avantgo|playbook|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od|ad)|iris|kindle|lge |maemo|midp|mmp|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\\/|plucker|pocket|psp|symbian|treo|up\\.(browser|link)|vodafone|wap|windows (ce|phone)|xda|xiino";
@ -44,5 +46,39 @@ $GLOBALS['ExtsDocument'] = array(".doc", ".docx", ".docm",
".html", ".htm", ".mht", ".xml",
".pdf", ".djvu", ".fb2", ".epub", ".xps", ".oxps", ".oform");
$GLOBALS['LANGUAGES'] = array(
'en' => 'English',
'az' => 'Azerbaijani',
'be' => 'Belarusian',
'bg' => 'Bulgarian',
'ca' => 'Catalan',
'zh' => 'Chinese',
'cs' => 'Czech',
'da' => 'Danish',
'nl' => 'Dutch',
'fi' => 'Finnish',
'fr' => 'French',
'gl' => 'Galego',
'de' => 'German',
'el' => 'Greek',
'hu' => 'Hungarian',
'id' => 'Indonesian',
'it' => 'Italian',
'ja' => 'Japanese',
'ko' => 'Korean',
'lv' => 'Latvian',
'lo' => 'Lao',
'nb' => 'Norwegian',
'pl' => 'Polish',
'pt' => 'Portuguese',
'ro' => 'Romanian',
'ru' => 'Russian',
'sk' => 'Slovak',
'sl' => 'Slovenian',
'es' => 'Spanish',
'sv' => 'Swedish',
'tr' => 'Turkish',
'uk' => 'Ukrainian',
'vi' => 'Vietnamese'
);
?>

View File

@ -131,6 +131,7 @@
],
"customization" => [ // the parameters for the editor interface
"about" => true, // the About section display
"comments" => true,
"feedback" => true, // the Feedback & Support menu button display
"forcesave" => false, // adds the request for the forced file saving to the callback handler when saving the document
"submitForm" => $submitForm, // if the Submit form button is displayed or not
@ -359,6 +360,7 @@
<script type="text/javascript">
var docEditor;
var config;
var innerAlert = function (message, inEditor) {
if (console && console.log)
@ -420,10 +422,14 @@
// the meta information of the document is changed via the meta command
var onMetaChange = function (event) {
var favorite = !!event.data.favorite;
var title = document.title.replace(/^\☆/g, "");
document.title = (favorite ? "☆" : "") + title;
docEditor.setFavorite(favorite); // change the Favorite icon state
if (event.data.favorite) {
var favorite = !!event.data.favorite;
var title = document.title.replace(/^\☆/g, "");
document.title = (favorite ? "☆" : "") + title;
docEditor.setFavorite(favorite); // change the Favorite icon state
}
innerAlert("onMetaChange: " + JSON.stringify(event.data));
};
// the user is trying to insert an image by clicking the Image from Storage button
@ -453,7 +459,7 @@
};
let xhr = new XMLHttpRequest();
xhr.open("POST", "webeditor-ajax.php?type=saveas");
xhr.setRequestHeader( 'Content-Type', 'application/json');
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.send(JSON.stringify(data));
xhr.onload = function () {
innerAlert(xhr.responseText);
@ -461,6 +467,24 @@
}
};
var onRequestRename = function(event) { // the user is trying to rename file by clicking Rename... button
innerAlert("onRequestRename: " + JSON.stringify(event.data));
var newfilename = event.data;
var data = {
newfilename: newfilename,
dockey: config.document.key,
};
let xhr = new XMLHttpRequest();
xhr.open("POST", "webeditor-ajax.php?type=rename");
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.send(JSON.stringify(data));
xhr.onload = function () {
innerAlert(xhr.responseText);
}
};
var сonnectEditor = function () {
<?php
@ -469,7 +493,7 @@
}
?>
var config = <?php echo json_encode($config) ?>;
config = <?php echo json_encode($config) ?>;
config.width = "100%";
config.height = "100%";
@ -492,36 +516,38 @@
$history = $out[0];
$historyData = $out[1];
?>
<?php if ($history != null && $historyData != null): ?>
// the user is trying to show the document version history
config.events['onRequestHistory'] = function () {
docEditor.refreshHistory(<?php echo json_encode($history) ?>); // show the document version history
};
// the user is trying to click the specific document version in the document version history
config.events['onRequestHistoryData'] = function (event) {
var ver = event.data;
var histData = <?php echo json_encode($historyData) ?>;
docEditor.setHistoryData(histData[ver - 1]); // send the link to the document for viewing the version history
};
// the user is trying to go back to the document from viewing the document version history
config.events['onRequestHistoryClose'] = function () {
document.location.reload();
};
<?php endif; ?>
<?php if ($usersForMentions != null): ?>
// add mentions for not anonymous users
config.events['onRequestUsers'] = function () {
docEditor.setUsers({ // set a list of users to mention in the comments
"users": <?php echo json_encode($usersForMentions) ?>
});
};
// the user is mentioned in a comment
config.events['onRequestSendNotify'] = function (event) {
event.data.actionLink = replaceActionLink(location.href, event.data.actionLink);
var data = JSON.stringify(event.data);
innerAlert("onRequestSendNotify: " + data);
};
<?php if ($user->id != "uid-0"): ?>
<?php if ($history != null && $historyData != null): ?>
// the user is trying to show the document version history
config.events['onRequestHistory'] = function () {
docEditor.refreshHistory(<?php echo json_encode($history) ?>); // show the document version history
};
// the user is trying to click the specific document version in the document version history
config.events['onRequestHistoryData'] = function (event) {
var ver = event.data;
var histData = <?php echo json_encode($historyData) ?>;
docEditor.setHistoryData(histData[ver - 1]); // send the link to the document for viewing the version history
};
// the user is trying to go back to the document from viewing the document version history
config.events['onRequestHistoryClose'] = function () {
document.location.reload();
};
<?php endif; ?>
// add mentions for not anonymous users
config.events['onRequestUsers'] = function () {
docEditor.setUsers({ // set a list of users to mention in the comments
"users": <?php echo json_encode($usersForMentions) ?>
});
};
// the user is mentioned in a comment
config.events['onRequestSendNotify'] = function (event) {
event.data.actionLink = replaceActionLink(location.href, JSON.stringify(event.data.actionLink));
var data = JSON.stringify(event.data);
innerAlert("onRequestSendNotify: " + data);
};
// prevent file renaming for anonymous users
config.events['onRequestRename'] = onRequestRename;
<?php endif; ?>
if (config.editorConfig.createUrl) {

View File

@ -175,7 +175,9 @@ function SendRequestToConvertService($document_uri, $from_extension, $to_extensi
);
if (substr($urlToConverter, 0, strlen("https")) === "https") {
$opts['ssl'] = array( 'verify_peer' => FALSE );
if($GLOBALS['DOC_SERV_VERIFY_PEER_OFF'] === TRUE) {
$opts['ssl'] = array( 'verify_peer' => FALSE, 'verify_peer_name' => FALSE );
}
}
$context = stream_context_create($opts);

View File

@ -100,37 +100,9 @@
<td valign="middle">
<span class="select-user">Language editors interface</span>
<select class="select-user" id="language">
<option value="en">English</option>
<option value="be">Belarusian</option>
<option value="bg">Bulgarian</option>
<option value="ca">Catalan</option>
<option value="zh">Chinese</option>
<option value="cs">Czech</option>
<option value="da">Danish</option>
<option value="nl">Dutch</option>
<option value="fi">Finnish</option>
<option value="fr">French</option>
<option value="de">German</option>
<option value="el">Greek</option>
<option value="hu">Hungarian</option>
<option value="id">Indonesian</option>
<option value="it">Italian</option>
<option value="ja">Japanese</option>
<option value="ko">Korean</option>
<option value="lv">Latvian</option>
<option value="lo">Lao</option>
<option value="nb">Norwegian</option>
<option value="pl">Polish</option>
<option value="pt">Portuguese</option>
<option value="ro">Romanian</option>
<option value="ru">Russian</option>
<option value="sk">Slovak</option>
<option value="sl">Slovenian</option>
<option value="sv">Swedish</option>
<option value="es">Spanish</option>
<option value="tr">Turkish</option>
<option value="uk">Ukrainian</option>
<option value="vi">Vietnamese</option>
<?php foreach ($GLOBALS['LANGUAGES'] as $key => $language) { ?>
<option value="<?=$key?>"><?=$language?></option>
<?php } ?>
</select>
</td>
</tr>

9
web/documentserver-example/php/trackmanager.php Normal file → Executable file
View File

@ -226,7 +226,7 @@ function processForceSave($data, $fileName, $userAddress) {
}
// create a command request
function commandRequest($method, $key){
function commandRequest($method, $key, $meta = null){
$documentCommandUrl = $GLOBALS['DOC_SERV_SITE_URL'].$GLOBALS['DOC_SERV_COMMAND_URL'];
$arr = [
@ -234,6 +234,9 @@ function commandRequest($method, $key){
"key" => $key
];
if($meta)
$arr["meta"] = $meta;
$headerToken = "";
$jwtHeader = $GLOBALS['DOC_SERV_JWT_HEADER'] == "" ? "Authorization" : $GLOBALS['DOC_SERV_JWT_HEADER'];
@ -252,7 +255,9 @@ function commandRequest($method, $key){
));
if (substr($documentCommandUrl, 0, strlen("https")) === "https") {
$opts['ssl'] = array( 'verify_peer' => FALSE );
if($GLOBALS['DOC_SERV_VERIFY_PEER_OFF'] === TRUE) {
$opts['ssl'] = array( 'verify_peer' => FALSE, 'verify_peer_name' => FALSE );
}
}
$context = stream_context_create($opts);

View File

@ -73,7 +73,8 @@ $descr_user_0 = [
"The file favorite state is undefined",
"Can't mention others in comments",
"Can't create new files from the editor",
"Cant see anyones information"
"Cant see anyones information",
"Can't rename files from the editor"
];
$users = [

26
web/documentserver-example/php/webeditor-ajax.php Normal file → Executable file
View File

@ -39,6 +39,16 @@ $_trackerStatus = array(
7 => 'CorruptedForceSave'
);
// ignore self-signed certificate
if($GLOBALS['DOC_SERV_VERIFY_PEER_OFF'] === TRUE) {
stream_context_set_default( [
'ssl' => [
'verify_peer' => false,
'verify_peer_name' => false,
],
]);
}
// check if type value exists
if (isset($_GET["type"]) && !empty($_GET["type"])) {
$response_array;
@ -95,6 +105,9 @@ if (isset($_GET["type"]) && !empty($_GET["type"])) {
$response_array = saveas();
$response_array['status'] = 'success';
die (json_encode($response_array));
case "rename":
$response_array = renamefile();
die (json_encode($response_array));
default:
$response_array['status'] = 'error';
$response_array['error'] = '404 Method not found';
@ -452,4 +465,17 @@ function delTree($dir) {
return rmdir($dir);
}
// rename...
function renamefile() {
$post = json_decode(file_get_contents('php://input'), true);
$newfilename = $post["newfilename"];
$dockey = $post["dockey"];
$meta = ["title" => $newfilename];
$commandRequest = commandRequest("meta", $dockey, $meta); // create a command request with the forcasave method
sendlog(" CommandRequest rename: " . serialize($commandRequest), "webedior-ajax.log");
return array("result" => $commandRequest);
}
?>

View File

@ -1,6 +1,6 @@
import os
VERSION = '1.1.0'
VERSION = '1.2.0'
FILE_SIZE_MAX = 5242880
STORAGE_PATH = 'app_data'
@ -30,6 +30,8 @@ EXAMPLE_DOMAIN = None
DOC_SERV_JWT_SECRET = '' # the secret key for generating token
DOC_SERV_JWT_HEADER = 'Authorization'
DOC_SERV_VERIFY_PEER = False
EXT_SPREADSHEET = [
".xls", ".xlsx", ".xlsm", ".xlsb",
".xlt", ".xltx", ".xltm",
@ -51,6 +53,42 @@ EXT_DOCUMENT = [
".pdf", ".djvu", ".fb2", ".epub", ".xps", ".oxps", ".oform"
]
LANGUAGES = {
'en': 'English',
'az': 'Azerbaijani',
'be': 'Belarusian',
'bg': 'Bulgarian',
'ca': 'Catalan',
'zh': 'Chinese',
'cs': 'Czech',
'da': 'Danish',
'nl': 'Dutch',
'fi': 'Finnish',
'fr': 'French',
'gl': 'Galego',
'de': 'German',
'el': 'Greek',
'hu': 'Hungarian',
'id': 'Indonesian',
'it': 'Italian',
'ja': 'Japanese',
'ko': 'Korean',
'lv': 'Latvian',
'lo': 'Lao',
'nb': 'Norwegian',
'pl': 'Polish',
'pt': 'Portuguese',
'ro': 'Romanian',
'ru': 'Russian',
'sk': 'Slovak',
'sl': 'Slovenian',
'es': 'Spanish',
'sv': 'Swedish',
'tr': 'Turkish',
'uk': 'Ukrainian',
'vi': 'Vietnamese'
}
if os.environ.get("EXAMPLE_DOMAIN"): # generates a link for example domain
EXAMPLE_DOMAIN = os.environ.get("EXAMPLE_DOMAIN")
if os.environ.get("DOC_SERV"): # generates links for document server

9
web/documentserver-example/python/readme.md Normal file → Executable file
View File

@ -71,3 +71,12 @@ See the detailed guide to learn how to install Document Server [for Windows](htt
In case the example and Document Server are installed on different computers, make sure that your server with the example installed has access to the Document Server with the address which you specify instead of **documentserver** in the configuration files.
Make sure that the Document Server has access to the server with the example installed with the address which you specify instead of **example.com** in the configuration files.
## Important security info
Please keep in mind the following security aspects when you are using test examples:
* There is no protection of the storage from unauthorized access since there is no need for authorization.
* There are no checks against parameter substitution in links, since the parameters are generated by the code according to the pre-arranged scripts.
* There are no data checks in requests of saving the file after editing, since each test example is intended for requests only from ONLYOFFICE Document Server.
* There are no prohibitions on using test examples from other sites, since they are intended to interact with ONLYOFFICE Document Server from another domain.

View File

@ -41,7 +41,8 @@ urlpatterns = [
path('remove', actions.remove),
path('csv', actions.csv),
path('files', actions.files),
path('saveas', actions.saveAs)
path('saveas', actions.saveAs),
path('rename', actions.rename)
]
urlpatterns += staticfiles_urlpatterns()

View File

@ -39,40 +39,6 @@ from django.http import HttpResponse, HttpResponseRedirect, FileResponse
from src import settings
from . import fileUtils, historyManager
LANGUAGES = {
'en': 'English',
'be': 'Belarusian',
'bg': 'Bulgarian',
'ca': 'Catalan',
'zh': 'Chinese',
'cs': 'Czech',
'da': 'Danish',
'nl': 'Dutch',
'fi': 'Finnish',
'fr': 'French',
'de': 'German',
'el': 'Greek',
'hu': 'Hungarian',
'id': 'Indonesian',
'it': 'Italian',
'ja': 'Japanese',
'ko': 'Korean',
'lv': 'Latvian',
'lo': 'Lao',
'nb': 'Norwegian',
'pl': 'Polish',
'pt': 'Portuguese',
'ro': 'Romanian',
'ru': 'Russian',
'sk': 'Slovak',
'sl': 'Slovenian',
'es': 'Spanish',
'sv': 'Swedish',
'tr': 'Turkish',
'uk': 'Ukrainian',
'vi': 'Vietnamese'
}
def isCanFillForms(ext):
return ext in config.DOC_SERV_FILLFORMS
@ -253,7 +219,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)
resp = requests.get(uri, stream=True, verify = config.DOC_SERV_VERIFY_PEER)
createFileResponse(resp, path, req, meta)
return

View File

@ -58,7 +58,7 @@ 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 ) # 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) # send the headers and body values to the converter and write the result to the response
json = response.json()
return getResponseUri(json)

View File

@ -150,7 +150,7 @@ def processForceSave(body, filename, usAddr):
return
# create a command request
def commandRequest(method, key):
def commandRequest(method, key, meta = None):
documentCommandUrl = config.DOC_SERV_SITE_URL + config.DOC_SERV_COMMAND_URL
payload = {
@ -158,6 +158,10 @@ def commandRequest(method, key):
'key': key
}
if (meta):
payload['meta'] = meta
headers={'accept': 'application/json'}
if jwtManager.isEnabled(): # check if a secret key to generate token exists or not
@ -166,8 +170,10 @@ def commandRequest(method, key):
headers[jwtHeader] = f'Bearer {headerToken}' # add a header Authorization with a header token with Authorization prefix in it
payload['token'] = jwtManager.encode(payload) # encode a payload object into a body token
response = requests.post(documentCommandUrl, json=payload, headers=headers)
response = requests.post(documentCommandUrl, json=payload, headers=headers, verify = config.DOC_SERV_VERIFY_PEER)
if (meta):
return response
return

View File

@ -79,7 +79,8 @@ descr_user_0 = [
"The file favorite state is undefined",
"Can't mention others in comments",
"Can't create new files from the editor",
"Cant see anyones information"
"Cant see anyones information",
"Can't rename files from the editor"
]
USERS = [

20
web/documentserver-example/python/src/views/actions.py Normal file → Executable file
View File

@ -118,7 +118,7 @@ def createNew(request):
# save file as...
def saveAs(request):
response ={}
response = {}
try:
body = json.loads(request.body)
@ -127,7 +127,7 @@ def saveAs(request):
filename = docManager.getCorrectName(title, request)
path = docManager.getStoragePath(filename, request)
resp = requests.get(saveAsFileUrl)
resp = requests.get(saveAsFileUrl, verify = config.DOC_SERV_VERIFY_PEER)
if ((len(resp.content) > config.FILE_SIZE_MAX) | (len(resp.content) <= 0)): # check if the file size exceeds the maximum size allowed (5242880)
response.setdefault('error', 'File size is incorrect')
@ -147,6 +147,21 @@ def saveAs(request):
return HttpResponse(json.dumps(response), content_type='application/json')
# rename file
def rename(request):
response = {}
body = json.loads(request.body)
newfilename = body['newfilename']
dockey = body['dockey']
meta = {'title': newfilename}
trackManager.commandRequest('meta', dockey, meta)
response.setdefault('result', trackManager.commandRequest('meta', dockey, meta).json())
return HttpResponse(json.dumps(response), content_type='application/json')
# edit a file
def edit(request):
filename = fileUtils.getFileName(request.GET['filename'])
@ -250,6 +265,7 @@ def edit(request):
},
'customization': { # the parameters for the editor interface
'about': True, # the About section display
'comments': True,
'feedback': True, # the Feedback & Support menu button display
'forcesave': False, # adds the request for the forced file saving to the callback handler
'submitForm': submitForm, # if the Submit form button is displayed or not

2
web/documentserver-example/python/src/views/index.py Normal file → Executable file
View File

@ -35,7 +35,7 @@ from src.utils import docManager
def default(request): # default parameters that will be passed to the template
context = {
'users': users.USERS,
'languages': docManager.LANGUAGES,
'languages': config.LANGUAGES,
'preloadurl': config.DOC_SERV_SITE_URL + config.DOC_SERV_PRELOADER_URL,
'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

74
web/documentserver-example/python/templates/editor.html Normal file → Executable file
View File

@ -49,6 +49,7 @@
<script type="text/javascript" language="javascript">
var docEditor;
var config;
var innerAlert = function (message, inEditor) {
if (console && console.log)
@ -110,10 +111,14 @@
// the meta information of the document is changed via the meta command
var onMetaChange = function (event) {
var favorite = !!event.data.favorite;
var title = document.title.replace(/^\☆/g, "");
document.title = (favorite ? "☆" : "") + title;
docEditor.setFavorite(favorite); // change the Favorite icon state
if (event.data.favorite) {
var favorite = !!event.data.favorite;
var title = document.title.replace(/^\☆/g, "");
document.title = (favorite ? "☆" : "") + title;
docEditor.setFavorite(favorite); // change the Favorite icon state
}
innerAlert("onMetaChange: " + JSON.stringify(event.data));
};
// the user is trying to insert an image by clicking the Image from Storage button
@ -145,7 +150,7 @@
};
let xhr = new XMLHttpRequest();
xhr.open("POST", "saveas");
xhr.setRequestHeader( 'Content-Type', 'application/json');
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.send(JSON.stringify(data));
xhr.onload = function () {
innerAlert(xhr.responseText);
@ -153,6 +158,23 @@
}
};
var onRequestRename = function(event) { // the user is trying to rename file by clicking Rename... button
innerAlert("onRequestRename: " + JSON.stringify(event.data));
var newfilename = event.data;
var data = {
newfilename: newfilename,
dockey: config.document.key,
};
let xhr = new XMLHttpRequest();
xhr.open("POST", "rename");
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.send(JSON.stringify(data));
xhr.onload = function () {
innerAlert(xhr.responseText);
}
};
var connectEditor = function () {
config = {{ cfg | safe }}
@ -171,26 +193,28 @@
"onRequestMailMergeRecipients": onRequestMailMergeRecipients,
};
{% if history and historyData %}
// the user is trying to show the document version history
config.events['onRequestHistory'] = function () {
docEditor.refreshHistory({{ history | safe }}); // show the document version history
};
// the user is trying to click the specific document version in the document version history
config.events['onRequestHistoryData'] = function (event) {
var ver = event.data;
var histData = {{ historyData | safe }};
docEditor.setHistoryData(histData[ver - 1]); // send the link to the document for viewing the version history
};
// the user is trying to go back to the document from viewing the document version history
config.events['onRequestHistoryClose'] = function () {
document.location.reload();
};
if (config.editorConfig.user.id) {
{% endif %}
{% if history and historyData %}
{% if usersForMentions %}
// the user is trying to show the document version history
config.events['onRequestHistory'] = function () {
docEditor.refreshHistory({{ history | safe }}); // show the document version history
};
// the user is trying to click the specific document version in the document version history
config.events['onRequestHistoryData'] = function (event) {
var ver = event.data;
var histData = {{ historyData | safe }};
docEditor.setHistoryData(histData[ver - 1]); // send the link to the document for viewing the version history
};
// the user is trying to go back to the document from viewing the document version history
config.events['onRequestHistoryClose'] = function () {
document.location.reload();
};
{% endif %}
// add mentions for not anonymous users
config.events['onRequestUsers'] = function () {
@ -200,12 +224,14 @@
};
// the user is mentioned in a comment
config.events['onRequestSendNotify'] = function (event) {
event.data.actionLink = replaceActionLink(location.href, event.data.actionLink);
event.data.actionLink = replaceActionLink(location.href, JSON.stringify(event.data.actionLink));
var data = JSON.stringify(event.data);
innerAlert("onRequestSendNotify: " + data);
};
// prevent file renaming for anonymous users
config.events['onRequestRename'] = onRequestRename;
{% endif %}
}
if (config.editorConfig.createUrl) {
config.events.onRequestSaveAs = onRequestSaveAs;

9
web/documentserver-example/ruby/README.md Normal file → Executable file
View File

@ -79,3 +79,12 @@ See the detailed guide to learn how to install Document Server [for Windows](htt
In case the example and Document Server are installed on different computers, make sure that your server with the example installed has access to the Document Server with the address which you specify instead of **documentserver** in the configuration files.
Make sure that the Document Server has access to the server with the example installed with the address which you specify instead of **example.com** in the configuration files.
## Important security info
Please keep in mind the following security aspects when you are using test examples:
* There is no protection of the storage from unauthorized access since there is no need for authorization.
* There are no checks against parameter substitution in links, since the parameters are generated by the code according to the pre-arranged scripts.
* There are no data checks in requests of saving the file after editing, since each test example is intended for requests only from ONLYOFFICE Document Server.
* There are no prohibitions on using test examples from other sites, since they are intended to interact with ONLYOFFICE Document Server from another domain.

View File

@ -118,10 +118,7 @@ class HomeController < ApplicationController
uri = URI.parse(new_file_uri) # create the request url
http = Net::HTTP.new(uri.host, uri.port) # create a connection to the http server
if new_file_uri.start_with?('https')
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_NONE # set the flags for the server certificate verification at the beginning of SSL session
end
DocumentHelper.verify_ssl(new_file_uri, http)
req = Net::HTTP::Get.new(uri.request_uri) # create the get requets
res = http.request(req)
@ -324,10 +321,8 @@ class HomeController < ApplicationController
uri = URI.parse(file_url) # create the request url
http = Net::HTTP.new(uri.host, uri.port) # create a connection to the http server
if file_url.start_with?('https')
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_NONE # set the flags for the server certificate verification at the beginning of SSL session
end
DocumentHelper.verify_ssl(file_url, http)
req = Net::HTTP::Get.new(uri.request_uri) # create the get requets
res = http.request(req)
data = res.body
@ -350,4 +345,17 @@ class HomeController < ApplicationController
return
end
end
# Rename...
def rename
body = JSON.parse(request.body.read)
dockey = body["dockey"]
newfilename = body["newfilename"]
meta = {
:title => newfilename
}
json_data = TrackHelper.command_request("meta", dockey, meta)
render plain: '{ "result" : "' + JSON.dump(json_data) + '"}'
end
end

View File

@ -340,7 +340,13 @@ class DocumentHelper
return result
end
end
# enable ignore certificate
def verify_ssl(file_uri, http)
if file_uri.start_with?('https') && Rails.configuration.verify_peer_off.eql?('true')
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_NONE # set the flags for the server certificate verification at the beginning of SSL session
end
end
end
end

View File

@ -151,8 +151,14 @@ class FileModel
:toolbarDocked => "top" # the place for the embedded viewer toolbar (top or bottom)
},
:customization => { # the parameters for the editor interface
:about => true, # the About section display
:comments => true,
:feedback => true, # the Feedback & Support menu button display
:forcesave => false, # adding the request for the forced file saving to the callback handler
:submitForm => submitForm # the Submit form button state
:submitForm => submitForm, # the Submit form button state
:goback => {
:url => DocumentHelper.get_server_url(true)
},
}
}
}

View File

@ -51,10 +51,7 @@ class ServiceConverter
uri = URI.parse(@@document_converter_url) # create the request url
http = Net::HTTP.new(uri.host, uri.port) # create a connection to the http server
if @@document_converter_url.start_with?('https')
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_NONE # set the flags for the server certificate verification at the beginning of SSL session
end
DocumentHelper.verify_ssl(@@document_converter_url, http)
http.read_timeout = @@convert_timeout
req = Net::HTTP::Post.new(uri.request_uri) # create the post request

View File

@ -206,14 +206,18 @@ class TrackHelper
end
# send the command request
def command_request(method, key)
def command_request(method, key, meta = nil)
document_command_url = Rails.configuration.urlSite + Rails.configuration.commandUrl # get the document command url
# create a payload object with the method and key
payload = {
:c => method,
:key => key
}
}
if (meta != nil)
payload.merge!({:meta => meta})
end
data = nil
begin
@ -221,10 +225,7 @@ class TrackHelper
uri = URI.parse(document_command_url) # parse the document command url
http = Net::HTTP.new(uri.host, uri.port) # create a connection to the http server
if document_command_url.start_with?('https') # check if the documnent command url starts with https
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_NONE # set the flags for the server certificate verification at the beginning of SSL session
end
DocumentHelper.verify_ssl(document_command_url, http)
req = Net::HTTP::Post.new(uri.request_uri) # create the post request
req.add_field("Content-Type", "application/json") # set headers
@ -251,10 +252,7 @@ class TrackHelper
uri = URI.parse(uristr) # parse the url string
http = Net::HTTP.new(uri.host, uri.port) # create a connection to the http server
if uristr.start_with?('https') # check if the documnent command url starts with https
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_NONE # set the flags for the server certificate verification at the beginning of SSL session
end
DocumentHelper.verify_ssl(uristr, http)
req = Net::HTTP::Get.new(uri)
res = http.request(req) # get the response

View File

@ -72,7 +72,8 @@ class Users
"The file favorite state is undefined",
"Can't mention others in comments",
"Can't create new files from the editor",
"Cant see anyones information"
"Cant see anyones information",
"Can't rename files from the editor"
];
@@users = [

View File

@ -26,6 +26,7 @@
<script type="text/javascript" language="javascript">
var docEditor;
var config;
var innerAlert = function (message, inEditor) {
if (console && console.log)
@ -87,10 +88,14 @@
// the meta information of the document is changed via the meta command
var onMetaChange = function (event) {
var favorite = !!event.data.favorite;
var title = document.title.replace(/^\☆/g, "");
document.title = (favorite ? "☆" : "") + title;
docEditor.setFavorite(favorite); // change the Favorite icon state
if (event.data.favorite) {
var favorite = !!event.data.favorite;
var title = document.title.replace(/^\☆/g, "");
document.title = (favorite ? "☆" : "") + title;
docEditor.setFavorite(favorite); // change the Favorite icon state
}
innerAlert("onMetaChange: " + JSON.stringify(event.data));
};
// the user is trying to insert an image by clicking the Image from Storage button
@ -120,7 +125,7 @@
};
let xhr = new XMLHttpRequest();
xhr.open("POST", "saveas");
xhr.setRequestHeader( 'Content-Type', 'application/json');
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.send(JSON.stringify(data));
xhr.onload = function () {
innerAlert(xhr.responseText);
@ -128,9 +133,26 @@
}
};
var onRequestRename = function(event) { // the user is trying to rename file by clicking Rename... button
innerAlert("onRequestRename: " + JSON.stringify(event.data));
var newfilename = event.data;
var data = {
newfilename: newfilename,
dockey: config.document.key,
};
let xhr = new XMLHttpRequest();
xhr.open("POST", "rename");
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.send(JSON.stringify(data));
xhr.onload = function () {
innerAlert(xhr.responseText);
}
};
var сonnectEditor = function () {
var config = <%= raw @file.get_config.to_json %>;
config = <%= raw @file.get_config.to_json %>;
config.width = "100%";
config.height = "100%";
@ -149,27 +171,25 @@
<%
history = @file.get_history
if history %>
// the user is trying to show the document version history
config.events['onRequestHistory'] = function () {
docEditor.refreshHistory(<%= raw history[:hist].to_json %>); // show the document version history
};
// the user is trying to click the specific document version in the document version history
config.events['onRequestHistoryData'] = function (event) {
var ver = event.data;
var histData = <%= raw history[:histData].to_json %>;
docEditor.setHistoryData(histData[ver - 1]); // send the link to the document for viewing the version history
};
// the user is trying to go back to the document from viewing the document version history
config.events['onRequestHistoryClose'] = function () {
document.location.reload();
};
<% end
%>
usersMentions = @file.get_users_mentions %>
<%
usersMentions = @file.get_users_mentions
if usersMentions %>
if (config.editorConfig.user.id) {
<% if history %>
// the user is trying to show the document version history
config.events['onRequestHistory'] = function () {
docEditor.refreshHistory(<%= raw history[:hist].to_json %>); // show the document version history
};
// the user is trying to click the specific document version in the document version history
config.events['onRequestHistoryData'] = function (event) {
var ver = event.data;
var histData = <%= raw history[:histData].to_json %>;
docEditor.setHistoryData(histData[ver - 1]); // send the link to the document for viewing the version history
};
// the user is trying to go back to the document from viewing the document version history
config.events['onRequestHistoryClose'] = function () {
document.location.reload();
};
<% end %>
// add mentions for not anonymous users
config.events['onRequestUsers'] = function () {
docEditor.setUsers({ // set a list of users to mention in the comments
@ -178,12 +198,13 @@
};
// the user is mentioned in a comment
config.events['onRequestSendNotify'] = function (event) {
event.data.actionLink = replaceActionLink(location.href, event.data.actionLink);
event.data.actionLink = replaceActionLink(location.href, JSON.stringify(event.data.actionLink));
var data = JSON.stringify(event.data);
innerAlert("onRequestSendNotify: " + data);
};
<% end
%>
// prevent file renaming for anonymous users
config.events['onRequestRename'] = onRequestRename;
}
if (config.editorConfig.createUrl) {
config.events.onRequestSaveAs = onRequestSaveAs;

View File

@ -72,37 +72,9 @@
<td valign="middle">
<span class="select-user">Language editors interface</span>
<select class="select-user" id="language">
<option value="en">English</option>
<option value="be">Belarusian</option>
<option value="bg">Bulgarian</option>
<option value="ca">Catalan</option>
<option value="zh">Chinese</option>
<option value="cs">Czech</option>
<option value="da">Danish</option>
<option value="nl">Dutch</option>
<option value="fi">Finnish</option>
<option value="fr">French</option>
<option value="de">German</option>
<option value="el">Greek</option>
<option value="hu">Hungarian</option>
<option value="id">Indonesian</option>
<option value="it">Italian</option>
<option value="ja">Japanese</option>
<option value="ko">Korean</option>
<option value="lv">Latvian</option>
<option value="lo">Lao</option>
<option value="nb">Norwegian</option>
<option value="pl">Polish</option>
<option value="pt">Portuguese</option>
<option value="ro">Romanian</option>
<option value="ru">Russian</option>
<option value="sk">Slovak</option>
<option value="sl">Slovenian</option>
<option value="sv">Swedish</option>
<option value="es">Spanish</option>
<option value="tr">Turkish</option>
<option value="uk">Ukrainian</option>
<option value="vi">Vietnamese</option>
<% Rails.configuration.languages.each { |key, language|%>
<option value="<%=key %>"> <%=language %> </option>
<% } %>
</select>
</td>
</tr>

View File

@ -26,7 +26,7 @@ module OnlineEditorsExampleRuby
end
end
Rails.configuration.version="1.1.0"
Rails.configuration.version="1.2.0"
Rails.configuration.fileSizeMax=5242880
Rails.configuration.storagePath="app_data"
@ -48,5 +48,42 @@ module OnlineEditorsExampleRuby
Rails.configuration.jwtSecret = ""
Rails.configuration.header="Authorization"
Rails.configuration.verify_peer_off = "true"
Rails.configuration.languages={
'en' => 'English',
'az' => 'Azerbaijani',
'be' => 'Belarusian',
'bg' => 'Bulgarian',
'ca' => 'Catalan',
'zh' => 'Chinese',
'cs' => 'Czech',
'da' => 'Danish',
'nl' => 'Dutch',
'fi' => 'Finnish',
'fr' => 'French',
'gl' => 'Galego'
'de' => 'German',
'el' => 'Greek',
'hu' => 'Hungarian',
'id' => 'Indonesian',
'it' => 'Italian',
'ja' => 'Japanese',
'ko' => 'Korean',
'lv' => 'Latvian',
'lo' => 'Lao',
'nb' => 'Norwegian',
'pl' => 'Polish',
'pt' => 'Portuguese',
'ro' => 'Romanian',
'ru' => 'Russian',
'sk' => 'Slovak',
'sl' => 'Slovenian',
'es' => 'Spanish',
'sv' => 'Swedish',
'tr' => 'Turkish',
'uk' => 'Ukrainian',
'vi' => 'Vietnamese'
}
end
end

View File

@ -13,6 +13,7 @@ Rails.application.routes.draw do
match '/csv', to: 'home#csv', via: 'get'
match '/files', to: 'home#files', via: 'get'
match '/saveas', to: 'home#saveas', via: 'post'
match '/rename', to: 'home#rename', via: 'post'
# The priority is based upon order of creation: first created -> highest priority.
# See how all your routes lay out with "rake routes".