mirror of
https://github.com/ONLYOFFICE/document-server-integration.git
synced 2026-04-07 14:06:11 +08:00
Compare commits
425 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 05a3110c99 | |||
| 8bafa3ff3a | |||
| 56679a3b75 | |||
| d4d758770f | |||
| 874ebff886 | |||
| 4f2f877f0e | |||
| 5cc6b4cb15 | |||
| 7a70a44bcb | |||
| e42bd53664 | |||
| 23e616aade | |||
| f035da0db4 | |||
| 3e12ec4ebe | |||
| 589ca9b601 | |||
| 32f1ec82d1 | |||
| 54bb5b0a24 | |||
| 8274c16f6d | |||
| 7a982fc785 | |||
| 6f5800fbde | |||
| 8ec632eebd | |||
| b6ca4535ce | |||
| 089fc8bfa0 | |||
| 0b4c17ea0a | |||
| 405be2847b | |||
| f809c7e525 | |||
| 44061c82a9 | |||
| ef4e283804 | |||
| 4b0ad1a192 | |||
| 60469b0dba | |||
| f5ac95e1cc | |||
| c4c2fbb945 | |||
| 99b5fcd562 | |||
| 7e34067410 | |||
| a44787c625 | |||
| 105afb2c34 | |||
| 002f9b958e | |||
| 56d5913808 | |||
| 6664864bed | |||
| 6c9e6e9304 | |||
| 416b1fde8c | |||
| 383f240825 | |||
| 642e145142 | |||
| 8f09dadfa0 | |||
| 495f1cf49a | |||
| cf01b5e0ae | |||
| 0673fed928 | |||
| 9b0b30a0b0 | |||
| 200187edce | |||
| 23176ddf07 | |||
| 9857cef8fc | |||
| 204f770401 | |||
| 61834e3ec6 | |||
| 2ca6185ac4 | |||
| e818bb978b | |||
| 3a4cf5e6e6 | |||
| 7ec16b90e3 | |||
| fcfb6efda7 | |||
| e4c72c98d1 | |||
| c2bbda542a | |||
| 2c12393c78 | |||
| 4e93f6ebac | |||
| d10ba9f773 | |||
| a0bf7db118 | |||
| e40e7cc41c | |||
| f616655f4c | |||
| 4ba708631e | |||
| b9c1bc0f42 | |||
| 215ade01a3 | |||
| 4d25418fc8 | |||
| 4539bac5db | |||
| eb196613e7 | |||
| 7ac788f589 | |||
| 55119458af | |||
| 3c18add1fc | |||
| 6bf63b7166 | |||
| 32df2d3e34 | |||
| 97c7859db5 | |||
| 492f9c7baa | |||
| e0c0595796 | |||
| 40b8fb88a8 | |||
| b0df0d72df | |||
| 1053add1d9 | |||
| f1fc0e5fae | |||
| a192c6ce1f | |||
| e8aec0b68c | |||
| d9667f9757 | |||
| 3a985da120 | |||
| a88f84ddac | |||
| 6525d7210f | |||
| 6b93311ce5 | |||
| 999561ffd6 | |||
| e539c1205f | |||
| 9a52a538cb | |||
| e8038a8e88 | |||
| 1045b314b6 | |||
| 1636732521 | |||
| daa9a5f3fa | |||
| 9bf3973215 | |||
| cad2a20cdf | |||
| 82a5a68e6c | |||
| 0e1a580a86 | |||
| c09f3fc4b9 | |||
| d4d7c4e222 | |||
| 14429c5b05 | |||
| 131e33c6af | |||
| 8a04e5fbc4 | |||
| 1b6435a7dc | |||
| b8eecab45f | |||
| a55cb60542 | |||
| f7259409a2 | |||
| 0ea9e68c7c | |||
| 4b72e0a664 | |||
| f4ae62e02d | |||
| 935377a941 | |||
| 3690aacb66 | |||
| b8b375a19a | |||
| 69d2e14438 | |||
| fec77a9e75 | |||
| f0171cbb18 | |||
| fe49aeb815 | |||
| 8416f36581 | |||
| b9f3bfd2e2 | |||
| 02b22e9e26 | |||
| f43f08012d | |||
| 1c27610e8d | |||
| 148caf6225 | |||
| b24e4503bc | |||
| 58378827d4 | |||
| 502f14c7be | |||
| ded2d19672 | |||
| 6116f05625 | |||
| 1e2a9cf4f2 | |||
| 1d7775f25b | |||
| 05c7a5a6db | |||
| c3500e39fd | |||
| 23169c6fea | |||
| f2fddc75c6 | |||
| f542e9dcfc | |||
| 6737a7e0d0 | |||
| e9c17c55da | |||
| f334bf4b19 | |||
| f2139949de | |||
| 48314b2c7f | |||
| 8804844281 | |||
| 3a21d29568 | |||
| b6a08e242d | |||
| 596235d34b | |||
| 254fbaccea | |||
| 69c07a30a7 | |||
| 6283ff934d | |||
| db231faca0 | |||
| a3dd0394d2 | |||
| f9fd73fc7e | |||
| 0931936b3c | |||
| b91b49c8fa | |||
| b0a0050201 | |||
| 1c780a639f | |||
| ad6ac4dedd | |||
| 8ba33f524b | |||
| 2f5b25d6ab | |||
| 44eef53a03 | |||
| 08388f739c | |||
| 1d8175b88f | |||
| 1400ec5a4b | |||
| e5f61ec95e | |||
| 7c669cca19 | |||
| 81f8bd1a9b | |||
| c4c819c513 | |||
| 03332b3cd9 | |||
| ebc864736d | |||
| af86ec1ca3 | |||
| d1d9915953 | |||
| c663bfe464 | |||
| 1bb7dd152a | |||
| a52000fc97 | |||
| 88b7fbf55c | |||
| f9449f7742 | |||
| 9d2b8c4830 | |||
| 4068e23556 | |||
| fc760af338 | |||
| c55ab7cc75 | |||
| 00c9b3e2b9 | |||
| 47074c588d | |||
| 018d1bbead | |||
| 82713572ab | |||
| 34d06235f4 | |||
| 468488c384 | |||
| ff4b387acf | |||
| 20012c7678 | |||
| 382160f2fc | |||
| 761e578faf | |||
| 7b7cbebc75 | |||
| dbc5ebf098 | |||
| c5d61b685b | |||
| f3acca4b4b | |||
| b92c4191f9 | |||
| 5b6f2696d2 | |||
| 625df85b51 | |||
| 6716d38a40 | |||
| 84d574906d | |||
| 3c760c3136 | |||
| bf28236d0d | |||
| 6d71a553be | |||
| fed5598294 | |||
| 02351113e1 | |||
| a07edeb5de | |||
| 5bbc4c6232 | |||
| 770c2fe551 | |||
| 4916537977 | |||
| 77ec1649a5 | |||
| 204ff947c3 | |||
| d36fe2466a | |||
| e927da28f5 | |||
| 17b5c6e4c9 | |||
| 03f853dfef | |||
| 1d7e65b2ba | |||
| 8ebb67c925 | |||
| 8524ff27ed | |||
| 7bedc4b877 | |||
| f25c211630 | |||
| 0f4785d14f | |||
| 288add4d45 | |||
| 1ee492838c | |||
| f9ce3d1d33 | |||
| 5f6687571a | |||
| a1e5a4d48e | |||
| 6e9518631f | |||
| 88d8086853 | |||
| d22f4f11ca | |||
| 29cbe66d09 | |||
| c2410268eb | |||
| 57cd71095d | |||
| 224d2bc570 | |||
| c7f18f1085 | |||
| fb05ad32ab | |||
| bac989efd1 | |||
| 8a203ac062 | |||
| 7e1386008b | |||
| 8ff206a411 | |||
| 83a0330725 | |||
| c5269a53cf | |||
| f86b26928d | |||
| f8d77947c8 | |||
| a62ac23aeb | |||
| a900183056 | |||
| 67d34f4bfa | |||
| 507a7f3162 | |||
| 703281aa07 | |||
| aefec3e105 | |||
| 8cc211b011 | |||
| 68ec626970 | |||
| 065f338a79 | |||
| 43548c04b9 | |||
| c7c95ecfbe | |||
| 064c0dcc35 | |||
| 9a01f465d0 | |||
| 2d85a4166e | |||
| 77c598049c | |||
| c1baac3d6f | |||
| c5e30b6512 | |||
| 0fa6f43716 | |||
| edc43bdf31 | |||
| f75453bf2d | |||
| d03326a1e1 | |||
| 8be501a0ab | |||
| a4c71eb69a | |||
| 132545c655 | |||
| 5caaf0b1c6 | |||
| 8f18cc8ab2 | |||
| db976766cc | |||
| 57f6028829 | |||
| 05706ff038 | |||
| 9cf7ce276e | |||
| 0b35179ef0 | |||
| d396f92f4d | |||
| 1e78da4cfc | |||
| a8c9c331c1 | |||
| 0b2e09cf1d | |||
| f81ae23a64 | |||
| 6f90ff3391 | |||
| 4f3882f892 | |||
| 727418277f | |||
| 2f795de6ad | |||
| bb28257a2d | |||
| 379dba8b7c | |||
| 05ea165f77 | |||
| 7a61fac6b7 | |||
| 31c3e050af | |||
| 0c677f3d65 | |||
| 6efa357c19 | |||
| 3b33846f9d | |||
| 3de8463359 | |||
| e05ead7ce6 | |||
| cdc8647f21 | |||
| c2b333fac7 | |||
| cae75d9888 | |||
| ee674e6a57 | |||
| 7207a9d860 | |||
| 8cc5f685af | |||
| a61a8ccb4f | |||
| e857a2bed7 | |||
| 514303d053 | |||
| 7d4f511a5d | |||
| 9b11e8b098 | |||
| 8351905cee | |||
| 15b7a07963 | |||
| ef1c53d330 | |||
| 9bcb871132 | |||
| 25a4b9c97b | |||
| a21fbd6802 | |||
| c7249ab27f | |||
| 450d37161b | |||
| ee46a77684 | |||
| 3b7e3c9258 | |||
| 783ad9f2de | |||
| 78571f6c23 | |||
| a5c0b9bfb1 | |||
| 5047e64f3b | |||
| d115e4092f | |||
| e7a1c2c6eb | |||
| 85f95ba4b9 | |||
| 133013dfde | |||
| 6acdc34e10 | |||
| 19304920d1 | |||
| 13b3eed5ed | |||
| d9c1c7e051 | |||
| 2d0b17e334 | |||
| 384381cebc | |||
| 16d830baf4 | |||
| efcfaf95e8 | |||
| 606f7d2d44 | |||
| 357c14b6d4 | |||
| c5a2b72b39 | |||
| dab9e4bb16 | |||
| 27b6cb3293 | |||
| 058b0c4f23 | |||
| 05c62bbdf3 | |||
| 425bd81f08 | |||
| 096102fa59 | |||
| c612320a65 | |||
| e0b60a6956 | |||
| 16a0846248 | |||
| 71e1b28f47 | |||
| 182f5f378e | |||
| 9d3f4b2300 | |||
| ab3d385c61 | |||
| 8d194b78a1 | |||
| b8e726a7be | |||
| dfd2d49e6c | |||
| fbe0c18315 | |||
| ec6ea72069 | |||
| 2accdeac3b | |||
| 63f4b6fbb6 | |||
| 642caddae8 | |||
| dac09bd1e1 | |||
| c6e3af5d3b | |||
| 183fb80077 | |||
| 63c3337938 | |||
| 0268298f2b | |||
| 32ea01784c | |||
| 8e4a2c6359 | |||
| 71041fea9f | |||
| 8b25a7a869 | |||
| dd20d79236 | |||
| 299a68e0bd | |||
| 9ad27d2cf0 | |||
| 828115e5b0 | |||
| 461a005cfa | |||
| 24cfd661ef | |||
| 6481ac7e13 | |||
| a194af0d19 | |||
| c0d240728d | |||
| 89c0f03318 | |||
| bc1c9f455c | |||
| df1a5f38c1 | |||
| 6559c76fbd | |||
| a7db14811f | |||
| abffa3e75f | |||
| 631f70148f | |||
| c7e7c9c19d | |||
| f2d4eb2a42 | |||
| 778cb91317 | |||
| beb9885b03 | |||
| 65e34e52f9 | |||
| b453aa19f0 | |||
| 600570f7c7 | |||
| 20f28afec1 | |||
| 2768ca5f6c | |||
| 7841822c54 | |||
| f3e24a8b5e | |||
| 2425898cc8 | |||
| d3b962dcb8 | |||
| 3cee92d3a3 | |||
| 95ea50210f | |||
| 40016395a8 | |||
| 8f2c2f96d2 | |||
| f9dbe89fd9 | |||
| c3a4c0a66b | |||
| edd423cd87 | |||
| e026a7027b | |||
| 11e8f40f8c | |||
| bf18854ec0 | |||
| 08d1080527 | |||
| 9ca242fe82 | |||
| b3c02a5afd | |||
| ec65ebbfb8 | |||
| 8544974202 | |||
| 90eeae5334 | |||
| 970cfa6dd0 | |||
| f04a26a0f4 | |||
| 53a58e2666 | |||
| 0ab0762aa5 | |||
| 4aeef2b873 | |||
| 60c03c1403 | |||
| a597c37684 | |||
| 5206171a70 | |||
| 375d916fe2 | |||
| 35afb7a8fe | |||
| 8d1c4d8042 | |||
| b969944ede | |||
| da7450c732 | |||
| 1db5e865a6 | |||
| 69ac7771d5 | |||
| 04f5cac85d | |||
| ccdd2a4cdc | |||
| 33140a2ca6 |
18
Readme.md
18
Readme.md
@ -1,10 +1,11 @@
|
||||
## Integration examples
|
||||
|
||||
Test examples are simple document management systems that can be built into your
|
||||
application for testing (please, do not use it for production without proper code
|
||||
modifications).
|
||||
Test examples are simple document management systems that can be built into your application for testing.
|
||||
Do NOT use these integration examples on your own server without proper code modifications!
|
||||
In case you enabled any of the test examples, disable it before going for production.
|
||||
|
||||
These examples show the way to integrate [ONLYOFFICE Docs][2] into your own website or application using one of the programming languages. The package contains examples written in .Net (C# MVC), .Net (C#), Java, Node.js, PHP and Ruby.
|
||||
These examples show the way to integrate [ONLYOFFICE Docs][2] into your own website or application using one of the programming languages.
|
||||
The package contains examples written in .Net (C# MVC), .Net (C#), Java, Node.js, PHP and Ruby.
|
||||
|
||||
You should change `http://documentserver` to your server address in these files:
|
||||
* [.Net (C# MVC)](https://github.com/ONLYOFFICE/document-server-integration/tree/master/web/documentserver-example/csharp-mvc) - `web/documentserver-example/csharp-mvc/web.appsettings.config`
|
||||
@ -66,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)
|
||||
|
||||
@ -87,10 +87,6 @@
|
||||
}
|
||||
|
||||
@media (max-width: 1008px) {
|
||||
#portal-info {
|
||||
width: 65vw;
|
||||
}
|
||||
|
||||
.left-panel {
|
||||
margin-left: 0;
|
||||
}
|
||||
@ -128,6 +124,10 @@
|
||||
height: 80px;
|
||||
}
|
||||
|
||||
.main {
|
||||
height: calc(100% - 128px);
|
||||
}
|
||||
|
||||
.main-panel {
|
||||
left: 0;
|
||||
padding: 48px 18px 24px;
|
||||
@ -312,6 +312,9 @@
|
||||
.tableRow td:first-child {
|
||||
max-width: 17%;
|
||||
}
|
||||
#portal-info {
|
||||
max-width: 60vw;
|
||||
}
|
||||
}
|
||||
|
||||
.downloadContentCellShift:after {
|
||||
@ -363,6 +366,10 @@
|
||||
height: 80px;
|
||||
}
|
||||
|
||||
.main {
|
||||
height: calc(100% - 128px);
|
||||
}
|
||||
|
||||
.copy {
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
@ -436,6 +443,58 @@
|
||||
display: none;
|
||||
width: 1%;
|
||||
}
|
||||
/* Mobile Upload*/
|
||||
.blockUI.blockMsg.blockPage.ui-dialog.ui-widget.ui-corner-all.ui-widget-content.ui-draggable {
|
||||
width: 344px !important;
|
||||
box-shadow: 0px 7px 15px rgba(85, 85, 85, 0.1);
|
||||
border-radius: 2px;
|
||||
top: 10% !important;
|
||||
margin-left: -172px !important;
|
||||
}
|
||||
|
||||
.ui-dialog .ui-dialog-titlebar {
|
||||
padding: 0;
|
||||
}
|
||||
.ui-dialog .ui-dialog-content {
|
||||
padding: 0 !important;
|
||||
}
|
||||
#mainProgress {
|
||||
margin: 24px 16px 0 !important;
|
||||
}
|
||||
.blockTitle {
|
||||
padding: 10px 10px 6px 16px !important;
|
||||
font-size: 14px !important;
|
||||
}
|
||||
#mainProgress .describeUpload {
|
||||
padding: 8px 0 !important;
|
||||
}
|
||||
.dialog-close {
|
||||
margin: 0 !important;
|
||||
}
|
||||
.step-descr{
|
||||
line-height: 150%;
|
||||
}
|
||||
.step {
|
||||
line-height: 160%;
|
||||
}
|
||||
.buttonsMobile{
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
.button.gray{
|
||||
margin: 0;
|
||||
}
|
||||
.button, .button:hover{
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
padding: 0 !important;
|
||||
width: 144px;
|
||||
height: 56px;
|
||||
margin-bottom: 24px !important;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 560px) and (min-width: 510px) {
|
||||
|
||||
@ -22,6 +22,7 @@
|
||||
}
|
||||
|
||||
body {
|
||||
display: block;
|
||||
background: #FFFFFF;
|
||||
color: #333333;
|
||||
font-family: Open Sans;
|
||||
@ -71,6 +72,7 @@ header img {
|
||||
}
|
||||
|
||||
.main {
|
||||
display: table;
|
||||
height: calc(100% - 112px);
|
||||
min-height: 536px;
|
||||
}
|
||||
@ -97,6 +99,10 @@ header img {
|
||||
width: 896px;
|
||||
}
|
||||
|
||||
#portal-info {
|
||||
max-width: 65vw;
|
||||
}
|
||||
|
||||
.portal-name {
|
||||
color: #FF6F3D;
|
||||
font-size: 24px;
|
||||
@ -728,12 +734,9 @@ html {
|
||||
width: 30vw;
|
||||
min-width: 200px;
|
||||
max-width: 400px;
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.user-descr > b {
|
||||
margin-left: 25px;
|
||||
}
|
||||
|
||||
.portal-descr:nth-child(3) {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
@ -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
|
||||
{
|
||||
@ -79,19 +80,37 @@ namespace OnlineEditorsExampleMVC.Helpers
|
||||
// get the storage path of the file
|
||||
public static string StoragePath(string fileName, string userAddress = null)
|
||||
{
|
||||
var directory = HttpRuntime.AppDomainAppPath + CurUserHostAddress(userAddress) + "\\";
|
||||
var directory = "";
|
||||
if (!string.IsNullOrEmpty(WebConfigurationManager.AppSettings["storage-path"]) && Path.IsPathRooted(WebConfigurationManager.AppSettings["storage-path"]))
|
||||
{
|
||||
directory = WebConfigurationManager.AppSettings["storage-path"] + "\\";
|
||||
}
|
||||
else
|
||||
{
|
||||
directory = HttpRuntime.AppDomainAppPath + WebConfigurationManager.AppSettings["storage-path"] + CurUserHostAddress(userAddress) + "\\";
|
||||
}
|
||||
|
||||
if (!Directory.Exists(directory))
|
||||
{
|
||||
Directory.CreateDirectory(directory);
|
||||
}
|
||||
return directory + Path.GetFileName(fileName);
|
||||
return directory + (fileName.Contains("\\") ? fileName : Path.GetFileName(fileName));
|
||||
}
|
||||
|
||||
// get the path to the forcesaved file version
|
||||
public static string ForcesavePath(string fileName, string userAddress, Boolean create)
|
||||
{
|
||||
// create the directory to this file version
|
||||
var directory = HttpRuntime.AppDomainAppPath + CurUserHostAddress(userAddress) + "\\";
|
||||
var directory = "";
|
||||
if (!string.IsNullOrEmpty(WebConfigurationManager.AppSettings["storage-path"]) && Path.IsPathRooted(WebConfigurationManager.AppSettings["storage-path"]))
|
||||
{
|
||||
directory = WebConfigurationManager.AppSettings["storage-path"] + "\\";
|
||||
}
|
||||
else
|
||||
{
|
||||
directory = HttpRuntime.AppDomainAppPath + WebConfigurationManager.AppSettings["storage-path"] + CurUserHostAddress(userAddress) + "\\";
|
||||
}
|
||||
|
||||
if (!Directory.Exists(directory))
|
||||
{
|
||||
return "";
|
||||
@ -172,7 +191,16 @@ namespace OnlineEditorsExampleMVC.Helpers
|
||||
// get all the stored files from the user host address
|
||||
public static List<FileInfo> GetStoredFiles()
|
||||
{
|
||||
var directory = HttpRuntime.AppDomainAppPath + WebConfigurationManager.AppSettings["storage-path"] + CurUserHostAddress(null) + "\\";
|
||||
var directory = "";
|
||||
if (!string.IsNullOrEmpty(WebConfigurationManager.AppSettings["storage-path"]) && Path.IsPathRooted(WebConfigurationManager.AppSettings["storage-path"]))
|
||||
{
|
||||
directory = WebConfigurationManager.AppSettings["storage-path"] + "\\";
|
||||
}
|
||||
else
|
||||
{
|
||||
directory = HttpRuntime.AppDomainAppPath + WebConfigurationManager.AppSettings["storage-path"] + CurUserHostAddress(null) + "\\";
|
||||
}
|
||||
|
||||
if (!Directory.Exists(directory)) return new List<FileInfo>();
|
||||
|
||||
var directoryInfo = new DirectoryInfo(directory);
|
||||
@ -228,8 +256,7 @@ namespace OnlineEditorsExampleMVC.Helpers
|
||||
{
|
||||
var uri = new UriBuilder(GetServerUrl(true))
|
||||
{
|
||||
Path = HttpRuntime.AppDomainAppVirtualPath + "/"
|
||||
+ path,
|
||||
Path = HttpRuntime.AppDomainAppVirtualPath + "/" + path,
|
||||
Query = ""
|
||||
};
|
||||
|
||||
@ -284,6 +311,24 @@ namespace OnlineEditorsExampleMVC.Helpers
|
||||
return createUrl.ToString();
|
||||
}
|
||||
|
||||
// create the public history url
|
||||
public static string GetHistoryDownloadUrl(string filename, string version, string file)
|
||||
{
|
||||
var downloadUrl = new UriBuilder(GetServerUrl(true))
|
||||
{
|
||||
Path =
|
||||
HttpRuntime.AppDomainAppVirtualPath
|
||||
+ (HttpRuntime.AppDomainAppVirtualPath.EndsWith("/") ? "" : "/")
|
||||
+ "webeditor.ashx",
|
||||
Query = "type=downloadhistory"
|
||||
+ "&fileName=" + HttpUtility.UrlEncode(filename)
|
||||
+ "&userAddress=" + HttpUtility.UrlEncode(HttpContext.Current.Request.UserHostAddress)
|
||||
+ "&ver=" + version
|
||||
+ "&file="+ file
|
||||
};
|
||||
return downloadUrl.ToString();
|
||||
}
|
||||
|
||||
// get url to download a file
|
||||
public static string GetDownloadUrl(string fileName)
|
||||
{
|
||||
@ -372,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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
{
|
||||
@ -95,7 +97,11 @@ namespace OnlineEditorsExampleMVC.Helpers
|
||||
}
|
||||
var downloadUri = (string)fileData["url"];
|
||||
string curExt = Path.GetExtension(fileName).ToLower(); // get current file extension
|
||||
string downloadExt = Path.GetExtension(downloadUri).ToLower() ?? ""; // get the extension of the downloaded file
|
||||
|
||||
var downloadExt = fileData.ContainsKey("filetype")
|
||||
? "." + (string)fileData["filetype"]
|
||||
: Path.GetExtension(downloadUri).ToLower() ?? ""; // TODO: Delete in version 7.0 or higher. Support for versions below 7.0
|
||||
|
||||
var newFileName = fileName;
|
||||
|
||||
// convert downloaded file to the file with the current extension if these extensions aren't equal
|
||||
@ -122,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);
|
||||
@ -167,7 +175,11 @@ namespace OnlineEditorsExampleMVC.Helpers
|
||||
var downloadUri = (string)fileData["url"];
|
||||
|
||||
string curExt = Path.GetExtension(fileName).ToLower(); // get current file extension
|
||||
string downloadExt = Path.GetExtension(downloadUri).ToLower(); // get the extension of the downloaded file
|
||||
|
||||
var downloadExt = fileData.ContainsKey("filetype")
|
||||
? "." + (string)fileData["filetype"]
|
||||
: Path.GetExtension(downloadUri).ToLower(); // TODO: Delete in version 7.0 or higher. Support for versions below 7.0
|
||||
|
||||
Boolean newFileName = false;
|
||||
|
||||
// convert downloaded file to the file with the current extension if these extensions aren't equal
|
||||
@ -193,6 +205,8 @@ namespace OnlineEditorsExampleMVC.Helpers
|
||||
}
|
||||
}
|
||||
|
||||
DocManagerHelper.VerifySSL();
|
||||
|
||||
string forcesavePath = "";
|
||||
Boolean isSubmitForm = fileData["forcesavetype"].ToString().Equals("3"); // SubmitForm
|
||||
|
||||
@ -235,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);
|
||||
@ -248,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)
|
||||
{
|
||||
|
||||
@ -30,7 +30,8 @@ namespace OnlineEditorsExampleMVC.Helpers
|
||||
"Can review all the changes",
|
||||
"Can perform all actions with comments",
|
||||
"The file favorite state is undefined",
|
||||
"Can create files from templates using data from the editor"
|
||||
"Can create files from templates using data from the editor",
|
||||
"Can see the information about all users"
|
||||
};
|
||||
|
||||
static List<string> descr_user_2 = new List<string>()
|
||||
@ -39,7 +40,8 @@ namespace OnlineEditorsExampleMVC.Helpers
|
||||
"Can review only his own changes or changes made by users with no group",
|
||||
"Can view comments, edit his own comments and comments left by users with no group. Can remove his own comments only",
|
||||
"This file is marked as favorite",
|
||||
"Can create new files from the editor"
|
||||
"Can create new files from the editor",
|
||||
"Can see the information about users from Group2 and users who don’t belong to any group"
|
||||
};
|
||||
|
||||
static List<string> descr_user_3 = new List<string>()
|
||||
@ -51,7 +53,8 @@ namespace OnlineEditorsExampleMVC.Helpers
|
||||
"Can’t copy data from the file to clipboard",
|
||||
"Can’t download the file",
|
||||
"Can’t print the file",
|
||||
"Can create new files from the editor"
|
||||
"Can create new files from the editor",
|
||||
"Can see the information about Group2 users"
|
||||
};
|
||||
|
||||
static List<string> descr_user_0 = new List<string>()
|
||||
@ -62,7 +65,9 @@ namespace OnlineEditorsExampleMVC.Helpers
|
||||
"Can perform all actions with comments",
|
||||
"The file favorite state is undefined",
|
||||
"Can't mention others in comments",
|
||||
"Can't create new files from the editor"
|
||||
"Can't create new files from the editor",
|
||||
"Can’t see anyone’s information",
|
||||
"Can't rename files from the editor"
|
||||
};
|
||||
|
||||
private static List<User> users = new List<User>() {
|
||||
@ -70,10 +75,11 @@ namespace OnlineEditorsExampleMVC.Helpers
|
||||
"uid-1",
|
||||
"John Smith",
|
||||
"smith@example.com",
|
||||
null,
|
||||
"",
|
||||
null,
|
||||
new Dictionary<string, object>(),
|
||||
null,
|
||||
null,
|
||||
new List<string>(),
|
||||
descr_user_1,
|
||||
true
|
||||
@ -90,6 +96,7 @@ namespace OnlineEditorsExampleMVC.Helpers
|
||||
{ "edit", new List<string>() { "group-2", "" } },
|
||||
{ "remove", new List<string>() { "group-2" } }
|
||||
},
|
||||
new List<string>() { "group-2", "" },
|
||||
true,
|
||||
new List<string>(),
|
||||
descr_user_2,
|
||||
@ -107,6 +114,7 @@ namespace OnlineEditorsExampleMVC.Helpers
|
||||
{ "edit", new List<string>() { "group-2" } },
|
||||
{ "remove", new List<string>() { } }
|
||||
},
|
||||
new List<string>() { "group-2" },
|
||||
false,
|
||||
new List<string>() { "copy", "download", "print" },
|
||||
descr_user_3,
|
||||
@ -116,9 +124,10 @@ namespace OnlineEditorsExampleMVC.Helpers
|
||||
"uid-0",
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
"",
|
||||
null,
|
||||
new Dictionary<string,object>(),
|
||||
new List<string>(),
|
||||
null,
|
||||
new List<string>(),
|
||||
descr_user_0,
|
||||
@ -173,8 +182,9 @@ namespace OnlineEditorsExampleMVC.Helpers
|
||||
public List<string> deniedPermissions;
|
||||
public List<string> descriptions;
|
||||
public bool templates;
|
||||
public List<string> userInfoGroups;
|
||||
|
||||
public User(string id, string name, string email, string group, List<string> reviewGroups, Dictionary<string, object> commentGroups, bool? favorite, List<string> deniedPermissions, List<string> descriptions, bool templates)
|
||||
public User(string id, string name, string email, string group, List<string> reviewGroups, Dictionary<string, object> commentGroups, List<string> userInfoGroups, bool? favorite, List<string> deniedPermissions, List<string> descriptions, bool templates)
|
||||
{
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
@ -186,6 +196,7 @@ namespace OnlineEditorsExampleMVC.Helpers
|
||||
this.deniedPermissions = deniedPermissions;
|
||||
this.descriptions = descriptions;
|
||||
this.templates = templates;
|
||||
this.userInfoGroups = userInfoGroups;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
31
web/documentserver-example/csharp-mvc/Models/FileModel.cs
Normal file → Executable file
31
web/documentserver-example/csharp-mvc/Models/FileModel.cs
Normal file → Executable file
@ -21,6 +21,7 @@ using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Web;
|
||||
using System.Web.Configuration;
|
||||
using System.Web.Mvc;
|
||||
using System.Web.Script.Serialization;
|
||||
using OnlineEditorsExampleMVC.Helpers;
|
||||
@ -42,7 +43,7 @@ namespace OnlineEditorsExampleMVC.Models
|
||||
// get file url for user
|
||||
public string FileUriUser
|
||||
{
|
||||
get { return DocManagerHelper.GetFileUri(FileName, false); }
|
||||
get { return Path.IsPathRooted(WebConfigurationManager.AppSettings["storage-path"]) ? DownloadUrl + "&dmode=emb" : DocManagerHelper.GetFileUri(FileName, false); }
|
||||
}
|
||||
|
||||
public string FileName { get; set; } // file name
|
||||
@ -148,7 +149,8 @@ namespace OnlineEditorsExampleMVC.Models
|
||||
{ "modifyContentControl", editorsMode != "blockcontent" },
|
||||
{ "review", canEdit && (editorsMode == "edit" || editorsMode == "review") },
|
||||
{ "reviewGroups", user.reviewGroups },
|
||||
{ "commentGroups", user.commentGroups }
|
||||
{ "commentGroups", user.commentGroups },
|
||||
{ "userInfoGroups", user.userInfoGroups }
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -166,7 +168,7 @@ namespace OnlineEditorsExampleMVC.Models
|
||||
// the user currently viewing or editing the document
|
||||
"user", new Dictionary<string, object>
|
||||
{
|
||||
{ "id", user.id },
|
||||
{ "id", !user.id.Equals("uid-0") ? user.id : null },
|
||||
{ "name", user.name },
|
||||
{ "group", user.group }
|
||||
}
|
||||
@ -186,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
|
||||
@ -214,7 +217,8 @@ namespace OnlineEditorsExampleMVC.Models
|
||||
|
||||
// get the document history
|
||||
public void GetHistory(out string history, out string historyData)
|
||||
{
|
||||
{
|
||||
var storagePath = WebConfigurationManager.AppSettings["storage-path"];
|
||||
var jss = new JavaScriptSerializer();
|
||||
var histDir = DocManagerHelper.HistoryDir(DocManagerHelper.StoragePath(FileName, null));
|
||||
|
||||
@ -253,9 +257,22 @@ namespace OnlineEditorsExampleMVC.Models
|
||||
}
|
||||
}
|
||||
|
||||
var ext = Path.GetExtension(FileName).ToLower();
|
||||
dataObj.Add("fileType", ext.Replace(".", ""));
|
||||
dataObj.Add("key", key);
|
||||
// write file url to the data object
|
||||
dataObj.Add("url", i == currentVersion ? FileUri : DocManagerHelper.GetPathUri(Directory.GetFiles(verDir, "prev.*")[0].Substring(HttpRuntime.AppDomainAppPath.Length)));
|
||||
string prevFileUrl;
|
||||
if (Path.IsPathRooted(storagePath) && !string.IsNullOrEmpty(storagePath))
|
||||
{
|
||||
prevFileUrl = i == currentVersion ? DocManagerHelper.GetHistoryDownloadUrl(FileName, i.ToString(), "prev" + ext)
|
||||
: DocManagerHelper.GetDownloadUrl(Directory.GetFiles(verDir, "prev.*")[0].Replace(storagePath + "\\", ""));
|
||||
}
|
||||
else {
|
||||
prevFileUrl = i == currentVersion ? FileUri
|
||||
: DocManagerHelper.GetHistoryDownloadUrl(FileName, i.ToString(), "prev" + ext);
|
||||
}
|
||||
|
||||
dataObj.Add("url", prevFileUrl);
|
||||
dataObj.Add("version", i);
|
||||
if (i > 1) // check if the version number is greater than 1 (the file was modified)
|
||||
{
|
||||
@ -274,11 +291,13 @@ namespace OnlineEditorsExampleMVC.Models
|
||||
|
||||
var prev = (Dictionary<string, object>)histData[(i - 2).ToString()]; // get the history data from the previous file version
|
||||
dataObj.Add("previous", new Dictionary<string, object>() { // write information about previous file version to the data object
|
||||
{ "fileType", prev["fileType"] },
|
||||
{ "key", prev["key"] }, // write key and url information about previous file version
|
||||
{ "url", prev["url"] },
|
||||
});
|
||||
// write the path to the diff.zip archive with differences in this file version
|
||||
dataObj.Add("changesUrl", DocManagerHelper.GetPathUri(Path.Combine(DocManagerHelper.VersionDir(histDir, i - 1), "diff.zip").Substring(HttpRuntime.AppDomainAppPath.Length)));
|
||||
var changesUrl = DocManagerHelper.GetHistoryDownloadUrl(FileName, (i - 1).ToString(), "diff.zip");
|
||||
dataObj.Add("changesUrl", changesUrl);
|
||||
}
|
||||
if(JwtManager.Enabled)
|
||||
{
|
||||
|
||||
@ -55,7 +55,7 @@ namespace OnlineEditorsExampleMVC.Models
|
||||
// spreadsheet extensions
|
||||
public static readonly List<string> ExtsSpreadsheet = new List<string>
|
||||
{
|
||||
".xls", ".xlsx", ".xlsm",
|
||||
".xls", ".xlsx", ".xlsm", ".xlsb",
|
||||
".xlt", ".xltx", ".xltm",
|
||||
".ods", ".fods", ".ots", ".csv"
|
||||
};
|
||||
|
||||
@ -13,7 +13,7 @@
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>OnlineEditorsExampleMVC</RootNamespace>
|
||||
<AssemblyName>OnlineEditorsExampleMVC</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
|
||||
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
|
||||
<MvcBuildViews>false</MvcBuildViews>
|
||||
<UseIISExpress>true</UseIISExpress>
|
||||
<IISExpressSSLPort />
|
||||
|
||||
@ -2,22 +2,25 @@
|
||||
|
||||
This example will help you integrate ONLYOFFICE Docs into your web application written in .Net (C# MVC).
|
||||
|
||||
It is aimed at testing the editors. Please, do not use it for production without proper modifications.
|
||||
**Please note**: It is intended for testing purposes and demonstrating functionality of the editors. Do NOT use this integration example on your own server without proper code modifications! In case you enabled the test example, disable it before going for production.
|
||||
|
||||
## Step 1. Install ONLYOFFICE Docs
|
||||
|
||||
Download and install ONLYOFFICE Docs (packaged as Document Server).
|
||||
Download and install ONLYOFFICE Docs (packaged as Document Server).
|
||||
|
||||
See the detailed guide to learn how to install Document Server [for Windows](https://helpcenter.onlyoffice.com/installation/docs-developer-install-windows.aspx), [for Linux](https://helpcenter.onlyoffice.com/installation/docs-developer-install-ubuntu.aspx), or [for Docker](https://helpcenter.onlyoffice.com/server/developer-edition/docker/docker-installation.aspx).
|
||||
|
||||
## Step 2. Download the .Net (C# MVC) code for the editors integration
|
||||
|
||||
Download the [.Net (C# MVC) example](https://api.onlyoffice.com/editors/demopreview) from our site.
|
||||
You need to connnect the editors to your website. Specify path to the editors installation in the *settings.config* file:
|
||||
|
||||
To connect the editors to your website, specify the path to the editors installation and the path to the storage folder in the *settings.config* file:
|
||||
```
|
||||
<add key="storage-path" value=""/>
|
||||
<add key="files.docservice.url.site" value="https://documentserver/" />
|
||||
```
|
||||
where the **documentserver** is the name of the server with the ONLYOFFICE Document Server installed.
|
||||
where the **documentserver** is the name of the server with the ONLYOFFICE Document Server installed and the **storage-path** is the path where files will be created and stored. You can set an absolute path.
|
||||
|
||||
If you want to experiment with the editor configuration, modify the [parameters](https://api.onlyoffice.com/editors/advanced) in the *DocEditor.aspx* file.
|
||||
|
||||
## Step 3. Install the prerequisites
|
||||
@ -25,31 +28,41 @@ If you want to experiment with the editor configuration, modify the [parameters]
|
||||
* **Microsoft .NET Framework**: version 4.5 (download it from the [official Microsoft website](https://www.microsoft.com/en-US/download/details.aspx?id=30653));
|
||||
* **Internet Information Services**: version 7 or later.
|
||||
|
||||
Configure the IIS components for the server to work correctly:
|
||||
1. Open Windows features:
|
||||
|
||||
**Start** -> **Control Panel** -> **Programs** -> **Programs and Features** -> **Turn Windows features on or off**
|
||||
|
||||
2. In the opened window, find **Internet Information Services** and choose all the necessary features. To do this, open the **World Wide Web Services** list and check the following components:
|
||||
* **Application Development Features**: .NET Extensibility 4.8, ASP.NET 4.8, ISAPI Extensions, ISAPI Filters,
|
||||
* **Common HTTP Features**: Default Document,
|
||||
* **Security**: Request Filtering.
|
||||
|
||||
## Step 4. Run your website with the editors
|
||||
1. Run the Internet Information Service (IIS) Manager:
|
||||
|
||||
**Start** -> **Control Panel** -> **System and Security** -> **Administrative Tools** -> **Internet Information Services (IIS) Manager**
|
||||
2. Add your website in the IIS Manager.
|
||||
|
||||
|
||||
On the **Connections** panel right-click the **Sites** node in the tree, then click **Add Website**.
|
||||
|
||||

|
||||
3. In the **Add Website** dialog box specify the name of the folder with the .Net (C# MVC) project in the **Site name** box.
|
||||
|
||||
|
||||
Specify the path to the folder with your project in the **Physical Path** box.
|
||||
|
||||
|
||||
Specify the unique value used only for this website in the **Port** box.
|
||||
|
||||
|
||||

|
||||
4. Check for the .NET platform version specified in IIS Manager for you website. Choose **v4.0.** version.
|
||||
|
||||
**Application Pools** -> right-click the platform name -> **Set application Pool defaults** -> **.NET CLR version**
|
||||
|
||||
|
||||

|
||||
5. Browse your website with the IIS Manager:
|
||||
|
||||
Right-click the site -> **Manage Website** -> **Browse**
|
||||
|
||||
|
||||

|
||||
|
||||
## Step 5. Check accessibility
|
||||
@ -57,3 +70,12 @@ If you want to experiment with the editor configuration, modify the [parameters]
|
||||
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.
|
||||
@ -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,47 +197,60 @@
|
||||
|
||||
<% 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;
|
||||
};
|
||||
|
||||
var сonnectEditor = function () {
|
||||
if ((config.document.fileType === "docxf" || config.document.fileType === "oform")
|
||||
&& DocsAPI.DocEditor.version().split(".")[0] < 7) {
|
||||
innerAlert("Please update ONLYOFFICE Docs to version 7.0 to work on fillable forms online.");
|
||||
return;
|
||||
}
|
||||
|
||||
docEditor = new DocsAPI.DocEditor("iframeEditor", config);
|
||||
};
|
||||
|
||||
|
||||
@ -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">
|
||||
|
||||
@ -66,7 +67,7 @@
|
||||
<a class="try-editor slide" data-type="pptx">Presentation</a>
|
||||
</li>
|
||||
<li>
|
||||
<a class="try-editor form" data-type="docxf">Master form</a>
|
||||
<a class="try-editor form" data-type="docxf">Form template</a>
|
||||
</li>
|
||||
</ul>
|
||||
<label class="create-sample">
|
||||
@ -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>
|
||||
@ -139,12 +114,13 @@
|
||||
<td class="section">
|
||||
<div class="main-panel">
|
||||
<% var storedFiles = DocManagerHelper.GetStoredFiles(); %>
|
||||
<div id="portal-info" style="display: <%= storedFiles.Any() ? "none" : "block" %>">
|
||||
<div id="portal-info" style="display: <%= storedFiles.Any() ? "none" : "table-cell" %>">
|
||||
<span class="portal-name">ONLYOFFICE Document Editors – Welcome!</span>
|
||||
<span class="portal-descr">
|
||||
Get started with a demo-sample of ONLYOFFICE Document Editors, the first html5-based editors.
|
||||
<br /> You may upload your own documents for testing using the "<b>Upload file</b>" button and <b>selecting</b> the necessary files on your PC.
|
||||
</span>
|
||||
<span class="portal-descr">Please do NOT use this integration example on your own server without proper code modifications, it is intended for testing purposes only. In case you enabled this test example, disable it before going for production.</span>
|
||||
<span class="portal-descr">You can open the same document using different users in different Web browser sessions, so you can check out multi-user editing functions.</span>
|
||||
<% foreach (User user in Users.getAllUsers())
|
||||
{ %>
|
||||
@ -222,9 +198,6 @@
|
||||
</a>
|
||||
</td>
|
||||
<% } %>
|
||||
<% if (docType != "word" && docType != "cell") { %>
|
||||
<td class="contentCells contentCells-icon contentCellsEmpty"></td>
|
||||
<% } %>
|
||||
<% if (docType == "word") { %>
|
||||
<td class="contentCells contentCells-icon">
|
||||
<a href="<%= Url.Action("Editor", "Home", new { fileName = storedFile.Name, editorsType = "desktop", editorsMode = "blockcontent" }) %>" target="_blank">
|
||||
@ -328,10 +301,8 @@
|
||||
<span class="step-descr">They are loaded only once, they will be cached on your computer.</span>
|
||||
<input type="hidden" name="hiddenFileName" id="hiddenFileName" />
|
||||
<br />
|
||||
<br />
|
||||
<span class="progress-descr">Note the speed of all operations depends on your connection quality and server location.</span>
|
||||
<br />
|
||||
<br />
|
||||
<div class="error-message">
|
||||
<b>Upload error: </b><span></span>
|
||||
<br />
|
||||
@ -340,10 +311,12 @@
|
||||
</div>
|
||||
<iframe id="embeddedView" src="" height="345px" width="432px" frameborder="0" scrolling="no" allowtransparency></iframe>
|
||||
<br />
|
||||
<div id="beginEdit" class="button orange disable">Edit</div>
|
||||
<div id="beginView" class="button gray disable">View</div>
|
||||
<div id="beginEmbedded" class="button gray disable">Embedded view</div>
|
||||
<div id="cancelEdit" class="button gray">Cancel</div>
|
||||
<div class="buttonsMobile">
|
||||
<div id="beginEdit" class="button orange disable">Edit</div>
|
||||
<div id="beginView" class="button gray disable">View</div>
|
||||
<div id="beginEmbedded" class="button gray disable">Embedded view</div>
|
||||
<div id="cancelEdit" class="button gray">Cancel</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<span id="loadScripts" data-docs="<%= WebConfigurationManager.AppSettings["files.docservice.url.site"] + WebConfigurationManager.AppSettings["files.docservice.url.preloader"] %>"></span>
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
For more information on how to configure your ASP.NET application, please visit
|
||||
http://go.microsoft.com/fwlink/?LinkId=152368
|
||||
@ -39,7 +39,7 @@
|
||||
</handlers>
|
||||
<security>
|
||||
<requestFiltering>
|
||||
<requestLimits maxAllowedContentLength="52428800"/>
|
||||
<requestLimits maxAllowedContentLength="52428800" />
|
||||
</requestFiltering>
|
||||
</security>
|
||||
</system.webServer>
|
||||
|
||||
@ -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;
|
||||
@ -46,6 +47,9 @@ namespace OnlineEditorsExampleMVC
|
||||
case "download":
|
||||
Download(context);
|
||||
break;
|
||||
case "downloadhistory":
|
||||
DownloadHistory(context);
|
||||
break;
|
||||
case "convert":
|
||||
Convert(context);
|
||||
break;
|
||||
@ -67,6 +71,9 @@ namespace OnlineEditorsExampleMVC
|
||||
case "saveas":
|
||||
SaveAs(context);
|
||||
break;
|
||||
case "rename":
|
||||
Rename(context);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -110,6 +117,8 @@ namespace OnlineEditorsExampleMVC
|
||||
|
||||
var req = (HttpWebRequest)WebRequest.Create(fileUrl);
|
||||
|
||||
DocManagerHelper.VerifySSL();
|
||||
|
||||
using (var stream = req.GetResponse().GetResponseStream())
|
||||
{
|
||||
|
||||
@ -148,6 +157,8 @@ namespace OnlineEditorsExampleMVC
|
||||
context.Response.ContentType = "text/plain";
|
||||
try
|
||||
{
|
||||
DocManagerHelper.VerifySSL();
|
||||
|
||||
var httpPostedFile = context.Request.Files[0];
|
||||
string fileName;
|
||||
|
||||
@ -247,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");
|
||||
@ -300,7 +313,7 @@ namespace OnlineEditorsExampleMVC
|
||||
var userAddress = context.Request["userAddress"];
|
||||
var fileName = Path.GetFileName(context.Request["fileName"]);
|
||||
var status = (TrackerStatus) (int) fileData["status"]; // get status from the request body
|
||||
var saved = 1; // editing
|
||||
var saved = 0;
|
||||
switch (status)
|
||||
{
|
||||
case TrackerStatus.Editing:
|
||||
@ -357,7 +370,7 @@ namespace OnlineEditorsExampleMVC
|
||||
return;
|
||||
}
|
||||
|
||||
context.Response.Write("{\"error\":0}");
|
||||
context.Response.Write("{\"error\":" + saved + "}");
|
||||
}
|
||||
|
||||
// remove a file
|
||||
@ -443,10 +456,12 @@ namespace OnlineEditorsExampleMVC
|
||||
{
|
||||
try
|
||||
{
|
||||
var fileName = Path.GetFileName(context.Request["fileName"]);
|
||||
var fileName = Path.IsPathRooted(WebConfigurationManager.AppSettings["storage-path"]) ? context.Request["fileName"]
|
||||
: Path.GetFileName(context.Request["fileName"]);
|
||||
var userAddress = context.Request["userAddress"];
|
||||
var isEmbedded = context.Request["dmode"];
|
||||
|
||||
if (JwtManager.Enabled)
|
||||
if (JwtManager.Enabled && isEmbedded == null)
|
||||
{
|
||||
string JWTheader = WebConfigurationManager.AppSettings["files.docservice.header"].Equals("") ? "Authorization" : WebConfigurationManager.AppSettings["files.docservice.header"];
|
||||
|
||||
@ -492,5 +507,80 @@ namespace OnlineEditorsExampleMVC
|
||||
{
|
||||
get { return false; }
|
||||
}
|
||||
|
||||
// download a history file
|
||||
private static void DownloadHistory(HttpContext context)
|
||||
{
|
||||
try
|
||||
{
|
||||
var fileName = Path.GetFileName(context.Request["fileName"]);
|
||||
var userAddress = Path.GetFileName(context.Request["userAddress"]);
|
||||
var version = System.Convert.ToInt32(context.Request["ver"]);
|
||||
var file = Path.GetFileName(context.Request["file"]);
|
||||
|
||||
if (JwtManager.Enabled)
|
||||
{
|
||||
string JWTheader = WebConfigurationManager.AppSettings["files.docservice.header"].Equals("") ? "Authorization" : WebConfigurationManager.AppSettings["files.docservice.header"];
|
||||
|
||||
if (context.Request.Headers.AllKeys.Contains(JWTheader, StringComparer.InvariantCultureIgnoreCase))
|
||||
{
|
||||
var headerToken = context.Request.Headers.Get(JWTheader).Substring("Bearer ".Length);
|
||||
string token = JwtManager.Decode(headerToken);
|
||||
|
||||
if (token == null || token.Equals(""))
|
||||
{
|
||||
context.Response.StatusCode = (int)HttpStatusCode.Forbidden;
|
||||
context.Response.Write("JWT validation failed");
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
context.Response.StatusCode = (int)HttpStatusCode.Forbidden;
|
||||
context.Response.Write("JWT validation failed");
|
||||
return;
|
||||
}
|
||||
}
|
||||
var histPath = DocManagerHelper.HistoryDir(DocManagerHelper.StoragePath(fileName, userAddress));
|
||||
var filePath = Path.Combine(DocManagerHelper.VersionDir(histPath, version), file); // get the path to document version
|
||||
|
||||
download(filePath, context);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
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\"}");
|
||||
}
|
||||
}
|
||||
}
|
||||
Submodule web/documentserver-example/csharp-mvc/assets updated: 589266f57f...1d601d84c4
@ -1,18 +1,23 @@
|
||||
<?xml version="1.0"?>
|
||||
<?xml version="1.0"?>
|
||||
<appSettings>
|
||||
<clear />
|
||||
<add key="version" value="1.0.0"/>
|
||||
<add key="version" value="1.2.0"/>
|
||||
|
||||
<add key="filesize-max" value="52428800"/>
|
||||
|
||||
<add key="storage-path" value=""/>
|
||||
|
||||
<add key="files.docservice.fillform-docs" value=".oform|.docx"/>
|
||||
<add key="files.docservice.viewed-docs" value=".pdf|.djvu|.xps|.oxps"/>
|
||||
<add key="files.docservice.edited-docs" value=".docx|.xlsx|.csv|.pptx|.txt|.docxf"/>
|
||||
<add key="files.docservice.convert-docs" value=".docm|.dotx|.dotm|.dot|.doc|.odt|.fodt|.ott|.xlsm|.xltx|.xltm|.xlt|.xls|.ods|.fods|.ots|.pptm|.ppt|.ppsx|.ppsm|.pps|.potx|.potm|.pot|.odp|.fodp|.otp|.rtf|.mht|.html|.htm|.xml|.epub|.fb2"/>
|
||||
<add key="files.docservice.convert-docs" value=".docm|.dotx|.dotm|.dot|.doc|.odt|.fodt|.ott|.xlsm|.xlsb|.xltx|.xltm|.xlt|.xls|.ods|.fods|.ots|.pptm|.ppt|.ppsx|.ppsm|.pps|.potx|.potm|.pot|.odp|.fodp|.otp|.rtf|.mht|.html|.htm|.xml|.epub|.fb2"/>
|
||||
<add key="files.docservice.timeout" value="120000" />
|
||||
<add key="files.docservice.secret" value="" />
|
||||
<add key="files.docservice.header" value="Authorization" />
|
||||
|
||||
<add key="files.docservice.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"/>
|
||||
|
||||
@ -87,10 +87,6 @@
|
||||
}
|
||||
|
||||
@media (max-width: 1008px) {
|
||||
#portal-info {
|
||||
width: 65vw;
|
||||
}
|
||||
|
||||
.left-panel {
|
||||
margin-left: 0;
|
||||
}
|
||||
@ -128,6 +124,10 @@
|
||||
height: 80px;
|
||||
}
|
||||
|
||||
.main {
|
||||
height: calc(100% - 128px);
|
||||
}
|
||||
|
||||
.main-panel {
|
||||
left: 0;
|
||||
padding: 48px 18px 24px;
|
||||
@ -312,6 +312,9 @@
|
||||
.tableRow td:first-child {
|
||||
max-width: 17%;
|
||||
}
|
||||
#portal-info {
|
||||
max-width: 60vw;
|
||||
}
|
||||
}
|
||||
|
||||
.downloadContentCellShift:after {
|
||||
@ -363,6 +366,10 @@
|
||||
height: 80px;
|
||||
}
|
||||
|
||||
.main {
|
||||
height: calc(100% - 128px);
|
||||
}
|
||||
|
||||
.copy {
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
@ -436,6 +443,58 @@
|
||||
display: none;
|
||||
width: 1%;
|
||||
}
|
||||
/* Mobile Upload*/
|
||||
.blockUI.blockMsg.blockPage.ui-dialog.ui-widget.ui-corner-all.ui-widget-content.ui-draggable {
|
||||
width: 344px !important;
|
||||
box-shadow: 0px 7px 15px rgba(85, 85, 85, 0.1);
|
||||
border-radius: 2px;
|
||||
top: 10% !important;
|
||||
margin-left: -172px !important;
|
||||
}
|
||||
|
||||
.ui-dialog .ui-dialog-titlebar {
|
||||
padding: 0;
|
||||
}
|
||||
.ui-dialog .ui-dialog-content {
|
||||
padding: 0 !important;
|
||||
}
|
||||
#mainProgress {
|
||||
margin: 24px 16px 0 !important;
|
||||
}
|
||||
.blockTitle {
|
||||
padding: 10px 10px 6px 16px !important;
|
||||
font-size: 14px !important;
|
||||
}
|
||||
#mainProgress .describeUpload {
|
||||
padding: 8px 0 !important;
|
||||
}
|
||||
.dialog-close {
|
||||
margin: 0 !important;
|
||||
}
|
||||
.step-descr{
|
||||
line-height: 150%;
|
||||
}
|
||||
.step {
|
||||
line-height: 160%;
|
||||
}
|
||||
.buttonsMobile{
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
.button.gray{
|
||||
margin: 0;
|
||||
}
|
||||
.button, .button:hover{
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
padding: 0 !important;
|
||||
width: 144px;
|
||||
height: 56px;
|
||||
margin-bottom: 24px !important;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 560px) and (min-width: 510px) {
|
||||
|
||||
@ -22,6 +22,7 @@ html {
|
||||
}
|
||||
|
||||
body {
|
||||
display: block;
|
||||
background: #FFFFFF;
|
||||
color: #333333;
|
||||
font-family: Open Sans;
|
||||
@ -71,6 +72,7 @@ header img {
|
||||
}
|
||||
|
||||
.main {
|
||||
display: table;
|
||||
height: calc(100% - 112px);
|
||||
min-height: 536px;
|
||||
}
|
||||
@ -97,6 +99,10 @@ header img {
|
||||
width: 896px;
|
||||
}
|
||||
|
||||
#portal-info {
|
||||
max-width: 65vw;
|
||||
}
|
||||
|
||||
.portal-name {
|
||||
color: #FF6F3D;
|
||||
font-size: 24px;
|
||||
@ -732,12 +738,9 @@ html {
|
||||
width: 30vw;
|
||||
min-width: 200px;
|
||||
max-width: 400px;
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.user-descr > b {
|
||||
margin-left: 25px;
|
||||
}
|
||||
|
||||
.portal-descr:nth-child(3) {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
@ -5,12 +5,14 @@
|
||||
<%@ 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">
|
||||
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head runat="server">
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<meta name="viewport" content="width=device-width" />
|
||||
<title>ONLYOFFICE</title>
|
||||
<!--
|
||||
*
|
||||
@ -68,7 +70,7 @@
|
||||
<a class="try-editor slide" data-type="slide">Presentation</a>
|
||||
</li>
|
||||
<li>
|
||||
<a class="try-editor form" data-type="docxf">Master form</a>
|
||||
<a class="try-editor form" data-type="docxf">Form template</a>
|
||||
</li>
|
||||
</ul>
|
||||
<label class="create-sample">
|
||||
@ -99,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>
|
||||
@ -140,12 +116,13 @@
|
||||
<td class="section">
|
||||
<% var storedFiles = GetStoredFiles(); %>
|
||||
<div class="main-panel">
|
||||
<div id="portal-info" style="display: <%= storedFiles.Any() ? "none" : "block" %>">
|
||||
<div id="portal-info" style="display: <%= storedFiles.Any() ? "none" : "table-cell" %>">
|
||||
<span class="portal-name">ONLYOFFICE Document Editors – Welcome!</span>
|
||||
<span class="portal-descr">
|
||||
Get started with a demo-sample of ONLYOFFICE Document Editors, the first html5-based editors.
|
||||
<br /> You may upload your own documents for testing using the "<b>Upload file</b>" button and <b>selecting</b> the necessary files on your PC.
|
||||
</span>
|
||||
<span class="portal-descr">Please do NOT use this integration example on your own server without proper code modifications, it is intended for testing purposes only. In case you enabled this test example, disable it before going for production.</span>
|
||||
<span class="portal-descr">You can open the same document using different users in different Web browser sessions, so you can check out multi-user editing functions.</span>
|
||||
<% foreach (User user in Users.getAllUsers())
|
||||
{ %>
|
||||
@ -223,9 +200,6 @@
|
||||
</a>
|
||||
</td>
|
||||
<% } %>
|
||||
<%if (docType != "word" && docType != "cell") { %>
|
||||
<td class="contentCells contentCells-icon contentCellsEmpty"></td>
|
||||
<% } %>
|
||||
<% if (docType == "word") { %>
|
||||
<td class="contentCells contentCells-icon">
|
||||
<a href="<%= editUrl + "&editorsType=desktop&editorsMode=blockcontent" %>" target="_blank">
|
||||
@ -329,10 +303,8 @@
|
||||
<span class="step-descr">They are loaded only once, they will be cached on your computer.</span>
|
||||
<input type="hidden" name="hiddenFileName" id="hiddenFileName" />
|
||||
<br />
|
||||
<br />
|
||||
<span class="progress-descr">Note the speed of all operations depends on your connection quality and server location.</span>
|
||||
<br />
|
||||
<br />
|
||||
<div class="error-message">
|
||||
<b>Upload error: </b><span></span>
|
||||
<br />
|
||||
@ -341,10 +313,12 @@
|
||||
</div>
|
||||
<iframe id="embeddedView" src="" height="345px" width="432px" frameborder="0" scrolling="no" allowtransparency></iframe>
|
||||
<br />
|
||||
<div id="beginEdit" class="button orange disable">Edit</div>
|
||||
<div id="beginView" class="button gray disable">View</div>
|
||||
<div id="beginEmbedded" class="button gray disable">Embedded view</div>
|
||||
<div id="cancelEdit" class="button gray">Cancel</div>
|
||||
<div class="buttonsMobile">
|
||||
<div id="beginEdit" class="button orange disable">Edit</div>
|
||||
<div id="beginView" class="button gray disable">View</div>
|
||||
<div id="beginEmbedded" class="button gray disable">Embedded view</div>
|
||||
<div id="cancelEdit" class="button gray">Cancel</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<span id="loadScripts" data-docs="<%= UrlPreloadScripts %>"></span>
|
||||
|
||||
@ -35,7 +35,7 @@ namespace OnlineEditorsExample
|
||||
// the spreadsheet extension list
|
||||
public static readonly List<string> ExtsSpreadsheet = new List<string>
|
||||
{
|
||||
".xls", ".xlsx", ".xlsm",
|
||||
".xls", ".xlsx", ".xlsm", ".xlsb",
|
||||
".xlt", ".xltx", ".xltm",
|
||||
".ods", ".fods", ".ots", ".csv"
|
||||
};
|
||||
@ -78,7 +78,9 @@ namespace OnlineEditorsExample
|
||||
{
|
||||
get
|
||||
{
|
||||
return
|
||||
return Path.IsPathRooted(WebConfigurationManager.AppSettings["storage-path"]) ?
|
||||
WebConfigurationManager.AppSettings["storage-path"] + "/"
|
||||
:
|
||||
HttpRuntime.AppDomainAppVirtualPath
|
||||
+ (HttpRuntime.AppDomainAppVirtualPath.EndsWith("/") ? "" : "/")
|
||||
+ WebConfigurationManager.AppSettings["storage-path"]
|
||||
@ -144,18 +146,52 @@ namespace OnlineEditorsExample
|
||||
// get the storage path of the given file
|
||||
public static string StoragePath(string fileName, string userAddress)
|
||||
{
|
||||
var directory = HttpRuntime.AppDomainAppPath + WebConfigurationManager.AppSettings["storage-path"] + CurUserHostAddress(userAddress) + "\\";
|
||||
var directory = "";
|
||||
if (Path.IsPathRooted(WebConfigurationManager.AppSettings["storage-path"]))
|
||||
{
|
||||
directory = WebConfigurationManager.AppSettings["storage-path"] + "\\";
|
||||
}
|
||||
else
|
||||
{
|
||||
directory = HttpRuntime.AppDomainAppPath + WebConfigurationManager.AppSettings["storage-path"] + CurUserHostAddress(userAddress) + "\\";
|
||||
}
|
||||
|
||||
if (!Directory.Exists(directory))
|
||||
{
|
||||
Directory.CreateDirectory(directory); // if the file directory doesn't exist, make it
|
||||
}
|
||||
return directory + Path.GetFileName(fileName);
|
||||
return directory + (fileName.Contains("\\") ? fileName : Path.GetFileName(fileName));
|
||||
}
|
||||
|
||||
// get the path to the history file version
|
||||
public static string HistoryPath(string fileName, string userAddress, string version, string file)
|
||||
{
|
||||
var directory = "";
|
||||
if (Path.IsPathRooted(WebConfigurationManager.AppSettings["storage-path"]))
|
||||
{
|
||||
directory = WebConfigurationManager.AppSettings["storage-path"] + "\\";
|
||||
}
|
||||
else
|
||||
{
|
||||
directory = HttpRuntime.AppDomainAppPath + WebConfigurationManager.AppSettings["storage-path"] + CurUserHostAddress(userAddress) + "\\";
|
||||
}
|
||||
var filepath = directory + Path.GetFileName(fileName) + "-hist" + "\\" + version + "\\" + file;
|
||||
return filepath;
|
||||
}
|
||||
|
||||
// get the path to the forcesaved file version
|
||||
public static string ForcesavePath(string fileName, string userAddress, Boolean create)
|
||||
{
|
||||
var directory = HttpRuntime.AppDomainAppPath + WebConfigurationManager.AppSettings["storage-path"] + CurUserHostAddress(userAddress) + "\\";
|
||||
var directory = "";
|
||||
if (Path.IsPathRooted(WebConfigurationManager.AppSettings["storage-path"]))
|
||||
{
|
||||
directory = WebConfigurationManager.AppSettings["storage-path"] + "\\";
|
||||
}
|
||||
else
|
||||
{
|
||||
directory = HttpRuntime.AppDomainAppPath + WebConfigurationManager.AppSettings["storage-path"] + CurUserHostAddress(userAddress) + "\\";
|
||||
}
|
||||
|
||||
if (!Directory.Exists(directory)) // the directory with host address doesn't exist
|
||||
{
|
||||
return "";
|
||||
@ -317,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
|
||||
{
|
||||
@ -384,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())
|
||||
{
|
||||
@ -472,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
|
||||
{
|
||||
@ -528,7 +552,16 @@ namespace OnlineEditorsExample
|
||||
// get all the stored files from the folder
|
||||
protected static List<FileInfo> GetStoredFiles()
|
||||
{
|
||||
var directory = HttpRuntime.AppDomainAppPath + WebConfigurationManager.AppSettings["storage-path"] + CurUserHostAddress(null) + "\\";
|
||||
var directory = "";
|
||||
if (Path.IsPathRooted(WebConfigurationManager.AppSettings["storage-path"]))
|
||||
{
|
||||
directory = WebConfigurationManager.AppSettings["storage-path"] + "\\";
|
||||
}
|
||||
else
|
||||
{
|
||||
directory = HttpRuntime.AppDomainAppPath + WebConfigurationManager.AppSettings["storage-path"] + CurUserHostAddress(null) + "\\";
|
||||
}
|
||||
|
||||
if (!Directory.Exists(directory)) return new List<FileInfo>();
|
||||
|
||||
var directoryInfo = new DirectoryInfo(directory); // read the user host directory contents
|
||||
@ -571,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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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,42 +207,53 @@
|
||||
"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;
|
||||
};
|
||||
|
||||
var сonnectEditor = function () {
|
||||
if ((config.document.fileType === "docxf" || config.document.fileType === "oform")
|
||||
&& DocsAPI.DocEditor.version().split(".")[0] < 7) {
|
||||
innerAlert("Please update ONLYOFFICE Docs to version 7.0 to work on fillable forms online.");
|
||||
return;
|
||||
}
|
||||
|
||||
docEditor = new DocsAPI.DocEditor("iframeEditor", config);
|
||||
};
|
||||
|
||||
|
||||
52
web/documentserver-example/csharp/DocEditor.aspx.cs
Normal file → Executable file
52
web/documentserver-example/csharp/DocEditor.aspx.cs
Normal file → Executable file
@ -41,7 +41,7 @@ namespace OnlineEditorsExample
|
||||
// get url to the original file for Document Server
|
||||
public static string FileUriUser
|
||||
{
|
||||
get { return _Default.FileUri(FileName, false); }
|
||||
get { return Path.IsPathRooted(WebConfigurationManager.AppSettings["storage-path"]) ? getDownloadUrl(FileName) + "&dmode=emb" : _Default.FileUri(FileName, false); }
|
||||
}
|
||||
|
||||
protected string Key
|
||||
@ -100,20 +100,17 @@ namespace OnlineEditorsExample
|
||||
}
|
||||
|
||||
// get url to download a file
|
||||
public static string getDownloadUrl
|
||||
public static string getDownloadUrl(string fileName)
|
||||
{
|
||||
get
|
||||
{
|
||||
var downloadUrl = new UriBuilder(_Default.GetServerUrl(true));
|
||||
var downloadUrl = new UriBuilder(_Default.GetServerUrl(true));
|
||||
downloadUrl.Path =
|
||||
HttpRuntime.AppDomainAppVirtualPath
|
||||
+ (HttpRuntime.AppDomainAppVirtualPath.EndsWith("/") ? "" : "/")
|
||||
+ "webeditor.ashx";
|
||||
downloadUrl.Query = "type=download"
|
||||
+ "&fileName=" + HttpUtility.UrlEncode(FileName)
|
||||
+ "&fileName=" + HttpUtility.UrlEncode(fileName)
|
||||
+ "&userAddress=" + HttpUtility.UrlEncode(HttpContext.Current.Request.UserHostAddress);
|
||||
return downloadUrl.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
// loading a page
|
||||
@ -195,7 +192,7 @@ namespace OnlineEditorsExample
|
||||
"document", new Dictionary<string, object>
|
||||
{
|
||||
{ "title", FileName },
|
||||
{ "url", getDownloadUrl },
|
||||
{ "url", getDownloadUrl(FileName) },
|
||||
{ "fileType", ext.Trim('.') },
|
||||
{ "key", Key },
|
||||
{
|
||||
@ -220,7 +217,8 @@ namespace OnlineEditorsExample
|
||||
{ "modifyContentControl", editorsMode != "blockcontent" },
|
||||
{ "review", canEdit && (editorsMode == "edit" || editorsMode == "review") },
|
||||
{ "reviewGroups", user.reviewGroups },
|
||||
{ "commentGroups", user.commentGroups }
|
||||
{ "commentGroups", user.commentGroups },
|
||||
{ "userInfoGroups", user.userInfoGroups }
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -238,7 +236,7 @@ namespace OnlineEditorsExample
|
||||
// the user currently viewing or editing the document
|
||||
"user", new Dictionary<string, object>
|
||||
{
|
||||
{ "id", user.id },
|
||||
{ "id", !user.id.Equals("uid-0") ? user.id : null },
|
||||
{ "name", user.name },
|
||||
{ "group", user.group }
|
||||
}
|
||||
@ -258,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
|
||||
@ -318,6 +317,7 @@ namespace OnlineEditorsExample
|
||||
// get the document history
|
||||
private void GetHistory(out Dictionary<string, object> history, out Dictionary<string, object> historyData)
|
||||
{
|
||||
var storagePath = WebConfigurationManager.AppSettings["storage-path"];
|
||||
var jss = new JavaScriptSerializer();
|
||||
var histDir = _Default.HistoryDir(_Default.StoragePath(FileName, null));
|
||||
|
||||
@ -355,8 +355,17 @@ namespace OnlineEditorsExample
|
||||
}
|
||||
}
|
||||
|
||||
var ext = Path.GetExtension(FileName).ToLower();
|
||||
dataObj.Add("fileType", ext.Replace(".", ""));
|
||||
dataObj.Add("key", key);
|
||||
dataObj.Add("url", i == currentVersion ? FileUri : MakePublicUrl(Directory.GetFiles(verDir, "prev.*")[0])); // write file url to the data object
|
||||
// write file url to the data object
|
||||
var prevFileUrl = i == currentVersion ? FileUri : MakePublicHistoryUrl(FileName, i.ToString(), "prev" + ext);
|
||||
if (Path.IsPathRooted(storagePath))
|
||||
{
|
||||
prevFileUrl = i == currentVersion ? getDownloadUrl(FileName) : getDownloadUrl(Directory.GetFiles(verDir, "prev.*")[0].Replace(storagePath + "\\", ""));
|
||||
}
|
||||
|
||||
dataObj.Add("url", prevFileUrl); // write file url to the data object
|
||||
dataObj.Add("version", i);
|
||||
if (i > 1) // check if the version number is greater than 1 (the file was modified)
|
||||
{
|
||||
@ -375,11 +384,13 @@ namespace OnlineEditorsExample
|
||||
|
||||
var prev = (Dictionary<string, object>)histData[(i - 2).ToString()]; // get the history data from the previous file version
|
||||
dataObj.Add("previous", new Dictionary<string, object>() { // write information about previous file version to the data object
|
||||
{ "fileType", prev["fileType"] },
|
||||
{ "key", prev["key"] }, // write key and url information about previous file version
|
||||
{ "url", prev["url"] },
|
||||
});
|
||||
// write the path to the diff.zip archive with differences in this file version
|
||||
dataObj.Add("changesUrl", MakePublicUrl(Path.Combine(_Default.VersionDir(histDir, i - 1), "diff.zip")));
|
||||
var changesUrl = MakePublicHistoryUrl(FileName, (i - 1).ToString(), "diff.zip");
|
||||
dataObj.Add("changesUrl", changesUrl);
|
||||
}
|
||||
if (JwtManager.Enabled)
|
||||
{
|
||||
@ -503,10 +514,25 @@ namespace OnlineEditorsExample
|
||||
// create the public url
|
||||
private string MakePublicUrl(string fullPath)
|
||||
{
|
||||
var root = HttpRuntime.AppDomainAppPath + WebConfigurationManager.AppSettings["storage-path"];
|
||||
var root = Path.IsPathRooted(WebConfigurationManager.AppSettings["storage-path"]) ? WebConfigurationManager.AppSettings["storage-path"]
|
||||
: HttpRuntime.AppDomainAppPath + WebConfigurationManager.AppSettings["storage-path"];
|
||||
return _Default.GetServerUrl(true) + fullPath.Substring(root.Length).Replace(Path.DirectorySeparatorChar, '/');
|
||||
}
|
||||
|
||||
|
||||
// create the public history url
|
||||
private string MakePublicHistoryUrl(string filename, string version, string file)
|
||||
{
|
||||
var fileUrl = new UriBuilder(_Default.GetServerUrl(true));
|
||||
fileUrl.Path = HttpRuntime.AppDomainAppVirtualPath
|
||||
+ (HttpRuntime.AppDomainAppVirtualPath.EndsWith("/") ? "" : "/")
|
||||
+ "webeditor.ashx";
|
||||
fileUrl.Query = "type=downloadhistory&fileName=" + HttpUtility.UrlEncode(filename)
|
||||
+ "&ver=" + version + "&file=" + file
|
||||
+ "&userAddress=" + HttpUtility.UrlEncode(HttpContext.Current.Request.UserHostAddress);
|
||||
return fileUrl.ToString();
|
||||
}
|
||||
|
||||
// create demo document
|
||||
private static void Try(string type, string sample, HttpRequest request)
|
||||
{
|
||||
|
||||
@ -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())
|
||||
|
||||
@ -11,7 +11,7 @@
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>OnlineEditorsExample</RootNamespace>
|
||||
<AssemblyName>OnlineEditorsExample</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
|
||||
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
|
||||
<FileUpgradeFlags>
|
||||
</FileUpgradeFlags>
|
||||
<UpgradeBackupLocation>
|
||||
|
||||
@ -2,11 +2,11 @@
|
||||
|
||||
This example will help you integrate ONLYOFFICE Docs into your web application written in .Net (C#).
|
||||
|
||||
It is aimed at testing the editors. Please, do not use it for production without proper modifications.
|
||||
**Please note**: It is intended for testing purposes and demonstrating functionality of the editors. Do NOT use this integration example on your own server without proper code modifications! In case you enabled the test example, disable it before going for production.
|
||||
|
||||
## Step 1. Install ONLYOFFICE Docs
|
||||
|
||||
Download and install ONLYOFFICE Docs (packaged as Document Server).
|
||||
Download and install ONLYOFFICE Docs (packaged as Document Server).
|
||||
|
||||
See the detailed guide to learn how to install Document Server [for Windows](https://helpcenter.onlyoffice.com/installation/docs-developer-install-windows.aspx), [for Linux](https://helpcenter.onlyoffice.com/installation/docs-developer-install-ubuntu.aspx), or [for Docker](https://helpcenter.onlyoffice.com/server/developer-edition/docker/docker-installation.aspx).
|
||||
|
||||
@ -14,11 +14,12 @@ See the detailed guide to learn how to install Document Server [for Windows](htt
|
||||
|
||||
Download the [.Net (C#) example](https://api.onlyoffice.com/editors/demopreview) from our site.
|
||||
|
||||
Connect the editors to your website by specifying the path to the editors installation in the *settings.config* file:
|
||||
To connect the editors to your website, specify the path to the editors installation and the path to the storage folder in the *settings.config* file:
|
||||
```
|
||||
<add key="storage-path" value=""/>
|
||||
<add key="files.docservice.url.site" value="https://documentserver/" />
|
||||
```
|
||||
where the **documentserver** is the name of the server with the ONLYOFFICE Document Server installed.
|
||||
where the **documentserver** is the name of the server with the ONLYOFFICE Document Server installed and the **storage-path** is the path where files will be created and stored. You can set an absolute path.
|
||||
|
||||
If you want to experiment with the editor configuration, modify the [parameters](https://api.onlyoffice.com/editors/advanced) in the *DocEditor.aspx* file.
|
||||
|
||||
@ -28,13 +29,23 @@ Check that your system meets the requirements:
|
||||
* **Microsoft .NET Framework**: version 4.5 (download it from the [official Microsoft website](https://www.microsoft.com/en-US/download/details.aspx?id=30653));
|
||||
* **Internet Information Services**: version 7 or later.
|
||||
|
||||
Configure the IIS components for the server to work correctly:
|
||||
1. Open Windows features:
|
||||
|
||||
**Start** -> **Control Panel** -> **Programs** -> **Programs and Features** -> **Turn Windows features on or off**
|
||||
|
||||
2. In the opened window, find **Internet Information Services** and choose all the necessary features. To do this, open the **World Wide Web Services** list and check the following components:
|
||||
* **Application Development Features**: .NET Extensibility 4.8, ASP.NET 4.8, ISAPI Extensions, ISAPI Filters,
|
||||
* **Common HTTP Features**: Default Document,
|
||||
* **Security**: Request Filtering.
|
||||
|
||||
## Step 4. Run your website with the editors
|
||||
1. Run the Internet Information Service (IIS) Manager:
|
||||
|
||||
**Start** -> **Control Panel** -> **System and Security** -> **Administrative Tools** -> **Internet Information Services (IIS) Manager**
|
||||
|
||||
2. Add your website in the IIS Manager.
|
||||
|
||||
|
||||
On the **Connections** panel right-click the **Sites** node in the tree, then click **Add Website**.
|
||||
|
||||

|
||||
@ -46,7 +57,7 @@ Check that your system meets the requirements:
|
||||
|
||||

|
||||
4. Check for the .NET platform version specified in IIS Manager for you website. Choose **v4.0.** version.
|
||||
|
||||
|
||||
**Application Pools** -> right-click the platform name -> **Set application Pool defaults** -> **.NET CLR version**
|
||||
|
||||

|
||||
@ -61,3 +72,12 @@ Check that your system meets the requirements:
|
||||
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.
|
||||
@ -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
|
||||
{
|
||||
@ -97,7 +99,11 @@ namespace OnlineEditorsExample
|
||||
}
|
||||
var downloadUri = (string)fileData["url"];
|
||||
var curExt = Path.GetExtension(fileName).ToLower(); // get current file extension
|
||||
var downloadExt = Path.GetExtension(downloadUri).ToLower() ?? ""; // get the extension of the downloaded file
|
||||
|
||||
var downloadExt = fileData.ContainsKey("filetype")
|
||||
? "." + (string)fileData["filetype"]
|
||||
: Path.GetExtension(downloadUri).ToLower() ?? ""; // TODO: Delete in version 7.0 or higher. Support for versions below 7.0
|
||||
|
||||
var newFileName = fileName;
|
||||
|
||||
// convert downloaded file to the file with the current extension if these extensions aren't equal
|
||||
@ -124,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
|
||||
@ -175,7 +177,11 @@ namespace OnlineEditorsExample
|
||||
var downloadUri = (string)fileData["url"];
|
||||
|
||||
string curExt = Path.GetExtension(fileName).ToLower(); // get current file extension
|
||||
string downloadExt = Path.GetExtension(downloadUri).ToLower(); // get the extension of the downloaded file
|
||||
|
||||
var downloadExt = fileData.ContainsKey("filetype")
|
||||
? "." + (string)fileData["filetype"]
|
||||
: Path.GetExtension(downloadUri).ToLower(); // TODO: Delete in version 7.0 or higher. Support for versions below 7.0
|
||||
|
||||
Boolean newFileName = false;
|
||||
|
||||
// convert downloaded file to the file with the current extension if these extensions aren't equal
|
||||
@ -201,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
|
||||
@ -250,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);
|
||||
@ -263,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
|
||||
|
||||
@ -29,7 +29,8 @@ namespace OnlineEditorsExample
|
||||
"Can review all the changes",
|
||||
"Can perform all actions with comments",
|
||||
"The file favorite state is undefined",
|
||||
"Can create files from templates using data from the editor"
|
||||
"Can create files from templates using data from the editor",
|
||||
"Can see the information about all users"
|
||||
};
|
||||
|
||||
static List<string> descr_user_2 = new List<string>()
|
||||
@ -38,19 +39,21 @@ namespace OnlineEditorsExample
|
||||
"Can review only his own changes or changes made by users with no group",
|
||||
"Can view comments, edit his own comments and comments left by users with no group. Can remove his own comments only",
|
||||
"This file is marked as favorite",
|
||||
"Can create new files from the editor"
|
||||
"Can create new files from the editor",
|
||||
"Can see the information about users from Group2 and users who don’t belong to any group"
|
||||
};
|
||||
|
||||
static List<string> descr_user_3 = new List<string>()
|
||||
{
|
||||
"Belongs to Group3",
|
||||
"Can review changes made by Group2 users",
|
||||
"Can view comments left by Group2 and Group3 users. Can edit comments left by Group2 users",
|
||||
"Can view comments left by Group2 and Group3 users. Can edit comments left by the Group2 users",
|
||||
"This file isn’t marked as favorite",
|
||||
"Can’t copy data from the file to clipboard",
|
||||
"Can’t download the file",
|
||||
"Can’t print the file",
|
||||
"Can create new files from the editor"
|
||||
"Can create new files from the editor",
|
||||
"Can see the information about Group2 users"
|
||||
};
|
||||
|
||||
static List<string> descr_user_0 = new List<string>()
|
||||
@ -61,7 +64,9 @@ namespace OnlineEditorsExample
|
||||
"Can perform all actions with comments",
|
||||
"The file favorite state is undefined",
|
||||
"Can't mention others in comments",
|
||||
"Can't create new files from the editor"
|
||||
"Can't create new files from the editor",
|
||||
"Can’t see anyone’s information",
|
||||
"Can't rename files from the editor"
|
||||
};
|
||||
|
||||
private static List<User> users = new List<User>() {
|
||||
@ -69,10 +74,11 @@ namespace OnlineEditorsExample
|
||||
"uid-1",
|
||||
"John Smith",
|
||||
"smith@example.com",
|
||||
null,
|
||||
"",
|
||||
null,
|
||||
new Dictionary<string, object>(),
|
||||
null,
|
||||
null,
|
||||
new List<string>(),
|
||||
descr_user_1,
|
||||
true
|
||||
@ -89,6 +95,7 @@ namespace OnlineEditorsExample
|
||||
{ "edit", new List<string>() { "group-2", "" } },
|
||||
{ "remove", new List<string>() { "group-2" } }
|
||||
},
|
||||
new List<string>() { "group-2", "" },
|
||||
true,
|
||||
new List<string>(),
|
||||
descr_user_2,
|
||||
@ -106,6 +113,7 @@ namespace OnlineEditorsExample
|
||||
{ "edit", new List<string>() { "group-2" } },
|
||||
{ "remove", new List<string>() { } }
|
||||
},
|
||||
new List<string>() { "group-2" },
|
||||
false,
|
||||
new List<string>() { "copy", "download", "print" },
|
||||
descr_user_3,
|
||||
@ -115,9 +123,10 @@ namespace OnlineEditorsExample
|
||||
"uid-0",
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
"",
|
||||
null,
|
||||
new Dictionary<string, object>(),
|
||||
new List<string>(),
|
||||
null,
|
||||
new List<string>(),
|
||||
descr_user_0,
|
||||
@ -173,8 +182,9 @@ namespace OnlineEditorsExample
|
||||
public List<string> deniedPermissions;
|
||||
public List<string> descriptions;
|
||||
public bool templates;
|
||||
public List<string> userInfoGroups;
|
||||
|
||||
public User(string id, string name, string email, string group, List<string> reviewGroups, Dictionary<string, object> commentGroups, bool? favorite, List<string> deniedPermissions, List<string> descriptions, bool templates)
|
||||
public User(string id, string name, string email, string group, List<string> reviewGroups, Dictionary<string, object> commentGroups, List<string> userInfoGroups, bool? favorite, List<string> deniedPermissions, List<string> descriptions, bool templates)
|
||||
{
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
@ -186,6 +196,7 @@ namespace OnlineEditorsExample
|
||||
this.deniedPermissions = deniedPermissions;
|
||||
this.descriptions = descriptions;
|
||||
this.templates = templates;
|
||||
this.userInfoGroups = userInfoGroups;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,26 +1,26 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<configuration>
|
||||
<appSettings configSource="settings.config"/>
|
||||
<appSettings configSource="settings.config" />
|
||||
<system.web>
|
||||
<httpRuntime maxRequestLength="51200"/>
|
||||
<compilation debug="true" targetFramework="4.5"/>
|
||||
<authentication mode="Windows"/>
|
||||
<pages controlRenderingCompatibilityVersion="3.5" clientIDMode="AutoID"/>
|
||||
<httpRuntime maxRequestLength="51200" />
|
||||
<compilation debug="true" targetFramework="4.5" />
|
||||
<authentication mode="Windows" />
|
||||
<pages controlRenderingCompatibilityVersion="3.5" clientIDMode="AutoID" />
|
||||
</system.web>
|
||||
<system.webServer>
|
||||
<httpProtocol>
|
||||
<customHeaders>
|
||||
<add name="Access-Control-Allow-Origin" value="*" />
|
||||
</customHeaders>
|
||||
</httpProtocol>
|
||||
<httpProtocol>
|
||||
<customHeaders>
|
||||
<add name="Access-Control-Allow-Origin" value="*" />
|
||||
</customHeaders>
|
||||
</httpProtocol>
|
||||
<security>
|
||||
<requestFiltering>
|
||||
<requestLimits maxAllowedContentLength="52428800"/>
|
||||
<requestLimits maxAllowedContentLength="52428800" />
|
||||
<denyUrlSequences>
|
||||
<add sequence=".."/>
|
||||
<add sequence=".." />
|
||||
</denyUrlSequences>
|
||||
<hiddenSegments>
|
||||
<remove segment="App_Data"/>
|
||||
<remove segment="App_Data" />
|
||||
</hiddenSegments>
|
||||
</requestFiltering>
|
||||
</security>
|
||||
|
||||
@ -44,6 +44,9 @@ namespace OnlineEditorsExample
|
||||
case "download":
|
||||
Download(context);
|
||||
break;
|
||||
case "downloadhistory":
|
||||
DownloadHistory(context);
|
||||
break;
|
||||
case "convert":
|
||||
Convert(context);
|
||||
break;
|
||||
@ -65,6 +68,9 @@ namespace OnlineEditorsExample
|
||||
case "saveas":
|
||||
SaveAs(context);
|
||||
break;
|
||||
case "rename":
|
||||
Rename(context);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -135,7 +141,7 @@ namespace OnlineEditorsExample
|
||||
var userAddress = context.Request["userAddress"];
|
||||
var fileName = Path.GetFileName(context.Request["fileName"]);
|
||||
var status = (TrackerStatus) (int) fileData["status"]; // get status from the request body
|
||||
var saved = 1; // editing
|
||||
var saved = 0;
|
||||
switch (status)
|
||||
{
|
||||
case TrackerStatus.Editing:
|
||||
@ -191,7 +197,7 @@ namespace OnlineEditorsExample
|
||||
context.Response.Write("{\"error\":" + saved + "}");
|
||||
return;
|
||||
}
|
||||
context.Response.Write("{\"error\":0}");
|
||||
context.Response.Write("{\"error\":" + saved + "}");
|
||||
}
|
||||
|
||||
// remove a file
|
||||
@ -271,10 +277,11 @@ namespace OnlineEditorsExample
|
||||
{
|
||||
try
|
||||
{
|
||||
var fileName = Path.GetFileName(context.Request["fileName"]);
|
||||
var fileName = Path.IsPathRooted(WebConfigurationManager.AppSettings["storage-path"]) ? context.Request["fileName"] : Path.GetFileName(context.Request["fileName"]);
|
||||
var userAddress = Path.GetFileName(context.Request["userAddress"]);
|
||||
var isEmbedded = context.Request["dmode"];
|
||||
|
||||
if (JwtManager.Enabled)
|
||||
if (JwtManager.Enabled && isEmbedded == null)
|
||||
{
|
||||
string JWTheader = WebConfigurationManager.AppSettings["files.docservice.header"].Equals("") ? "Authorization" : WebConfigurationManager.AppSettings["files.docservice.header"];
|
||||
|
||||
@ -321,5 +328,77 @@ namespace OnlineEditorsExample
|
||||
{
|
||||
get { return false; }
|
||||
}
|
||||
|
||||
private static void DownloadHistory(HttpContext context)
|
||||
{
|
||||
try
|
||||
{
|
||||
var fileName = Path.GetFileName(context.Request["fileName"]);
|
||||
var userAddress = Path.GetFileName(context.Request["userAddress"]);
|
||||
var version = Path.GetFileName(context.Request["ver"]);
|
||||
var file = Path.GetFileName(context.Request["file"]);
|
||||
|
||||
if (JwtManager.Enabled)
|
||||
{
|
||||
string JWTheader = WebConfigurationManager.AppSettings["files.docservice.header"].Equals("") ? "Authorization" : WebConfigurationManager.AppSettings["files.docservice.header"];
|
||||
|
||||
if (context.Request.Headers.AllKeys.Contains(JWTheader, StringComparer.InvariantCultureIgnoreCase))
|
||||
{
|
||||
var headerToken = context.Request.Headers.Get(JWTheader).Substring("Bearer ".Length);
|
||||
string token = JwtManager.Decode(headerToken);
|
||||
|
||||
if (token == null || token.Equals(""))
|
||||
{
|
||||
context.Response.StatusCode = (int)HttpStatusCode.Forbidden;
|
||||
context.Response.Write("JWT validation failed");
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
context.Response.StatusCode = (int)HttpStatusCode.Forbidden;
|
||||
context.Response.Write("JWT validation failed");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
var filePath = _Default.HistoryPath(fileName, userAddress, version, file); // get the path to the force saved document version
|
||||
|
||||
download(filePath, context);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
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\"}");
|
||||
}
|
||||
}
|
||||
}
|
||||
Submodule web/documentserver-example/csharp/assets updated: 589266f57f...1d601d84c4
@ -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.0.0"/>
|
||||
<add key="version" value="1.2.0"/>
|
||||
|
||||
<add key="filesize-max" value="52428800"/>
|
||||
<add key="storage-path" value=""/>
|
||||
@ -9,10 +9,13 @@
|
||||
<add key="files.docservice.fillform-docs" value=".oform|.docx"/>
|
||||
<add key="files.docservice.viewed-docs" value=".pdf|.djvu|.xps|.oxps"/>
|
||||
<add key="files.docservice.edited-docs" value=".docx|.xlsx|.csv|.pptx|.txt|.docxf"/>
|
||||
<add key="files.docservice.convert-docs" value=".docm|.dotx|.dotm|.dot|.doc|.odt|.fodt|.ott|.xlsm|.xltx|.xltm|.xlt|.xls|.ods|.fods|.ots|.pptm|.ppt|.ppsx|.ppsm|.pps|.potx|.potm|.pot|.odp|.fodp|.otp|.rtf|.mht|.html|.htm|.xml|.epub|.fb2"/>
|
||||
<add key="files.docservice.convert-docs" value=".docm|.dotx|.dotm|.dot|.doc|.odt|.fodt|.ott|.xlsm|.xlsb|.xltx|.xltm|.xlt|.xls|.ods|.fods|.ots|.pptm|.ppt|.ppsx|.ppsm|.pps|.potx|.potm|.pot|.odp|.fodp|.otp|.rtf|.mht|.html|.htm|.xml|.epub|.fb2"/>
|
||||
<add key="files.docservice.timeout" value="120000" />
|
||||
<add key="files.docservice.secret" value="" />
|
||||
<add key="files.docservice.header" value="Authorization" />
|
||||
<add key="files.docservice.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/"/>
|
||||
|
||||
|
||||
@ -1,17 +1,18 @@
|
||||
## Overview
|
||||
|
||||
This example will help you integrate ONLYOFFICE Docs into your web application written in Java
|
||||
with Spring Boot.
|
||||
with Spring Boot.
|
||||
|
||||
Spring Boot has a lot of functionality, but its most significant features are: dependency management,
|
||||
auto-configuration, and built-in servlet containers.
|
||||
|
||||
It is aimed at testing the editors. Please, do not use it for production without proper modifications.
|
||||
**Please note**: It is intended for testing purposes and demonstrating functionality of the editors. Do NOT use this integration example on your own server without proper code modifications! In case you enabled the test example, disable it before going for production.
|
||||
|
||||
## For Windows
|
||||
|
||||
### Step 1. Install ONLYOFFICE Docs
|
||||
|
||||
Download and install ONLYOFFICE Docs (packaged as Document Server).
|
||||
Download and install ONLYOFFICE Docs (packaged as Document Server).
|
||||
|
||||
See the detailed guide to learn how to install Document Server [for Windows](https://helpcenter.onlyoffice.com/installation/docs-developer-install-windows.aspx).
|
||||
|
||||
@ -19,16 +20,15 @@ See the detailed guide to learn how to install Document Server [for Windows](htt
|
||||
|
||||
Download the [Java-Spring example](https://api.onlyoffice.com/editors/demopreview) from our site.
|
||||
|
||||
To connect the editors to your website, specify the path to the editors installation, server address and port in the *\src\main\resources\application.properties* file:
|
||||
To connect the editors to your website, specify the path to the editors installation, server port and the path to the storage folder in the *\src\main\resources\application.properties* file:
|
||||
|
||||
```
|
||||
server.address=address
|
||||
files.storage=
|
||||
server.port=port
|
||||
files.docservice.url.site=https://documentserver/
|
||||
```
|
||||
|
||||
where the **documentserver** is the name of the server with the ONLYOFFICE Document Server installed.
|
||||
**address** is the address of the server or comment this line to use localhost, **port** is the any available port.
|
||||
where the **documentserver** is the name of the server with the ONLYOFFICE Docs installed, **port** is any available port and **files.storage** is the path where files will be created and stored (in the project folder by default). You can set an absolute path. For example, *D:\\\\folder*. Please note that on Windows OS the double backslash must be used as a separator.
|
||||
|
||||
If you want to experiment with the editor configuration, modify the [parameters](https://api.onlyoffice.com/editors/advanced) it the *\src\main\resources\editor.html* file.
|
||||
|
||||
@ -65,11 +65,11 @@ To run the Java example code, install the Java version 11 appropriate for your O
|
||||
```
|
||||
echo %JAVA_HOME%
|
||||
```
|
||||
|
||||
|
||||
2. Set the **MAVEN_HOME** environment variable:
|
||||
|
||||
|
||||
Unzip the downloaded archive with the maven to any directory, it will be something like this:
|
||||
|
||||
|
||||
```
|
||||
C:\apache-maven-3.8.1
|
||||
```
|
||||
@ -87,7 +87,7 @@ To run the Java example code, install the Java version 11 appropriate for your O
|
||||
|
||||
Add C:\apache-maven-3.8.1\bin to the PATH system variable:
|
||||
In system variables, find PATH, clicks on the Edit... button. In “Edit environment variable” dialog, clicks on the New button and add this C:\apache-maven-3.8.1\bin
|
||||
|
||||
|
||||
Check if the variable created successfully by **echo** command in the **Command Prompt**:
|
||||
|
||||
```
|
||||
@ -112,8 +112,6 @@ To run the Java example code, install the Java version 11 appropriate for your O
|
||||
```
|
||||
http://server.address:server.port/
|
||||
```
|
||||
|
||||
|
||||
|
||||
### Step 6. Check accessibility
|
||||
|
||||
@ -151,8 +149,8 @@ See the detailed guide to learn how to install Document Server [for Linux](https
|
||||
```
|
||||
git clone https://github.com/ONLYOFFICE/document-server-integration.git
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
3. Change the current directory for the project directory:
|
||||
|
||||
a) from archive
|
||||
@ -173,13 +171,13 @@ See the detailed guide to learn how to install Document Server [for Linux](https
|
||||
Edit the following lines:
|
||||
|
||||
```
|
||||
server.address=address
|
||||
files.storage=
|
||||
server.port=port
|
||||
files.docservice.url.site=https://documentserver/
|
||||
```
|
||||
|
||||
Where the **documentserver** is the name of the server with the ONLYOFFICE Document Server installed.
|
||||
**address** is the address of the server or comment this line to use localhost, **port** is the any available port.
|
||||
where the **documentserver** is the name of the server with the ONLYOFFICE Docs installed, **port** is any available port and **files.storage** is the path where files will be created and stored (in the project folder by default). You can set an absolute path.
|
||||
|
||||
|
||||
5. Install **Maven**:
|
||||
|
||||
@ -192,19 +190,18 @@ See the detailed guide to learn how to install Document Server [for Linux](https
|
||||
```
|
||||
mvn package
|
||||
```
|
||||
|
||||
|
||||
7. Start Java-Spring example:
|
||||
```
|
||||
./mvnw spring-boot:run
|
||||
```
|
||||
8. Open your browser using **server.address** and **server.port**:
|
||||
|
||||
|
||||
```
|
||||
http://server.address:server.port/
|
||||
```
|
||||
|
||||
|
||||
|
||||
### Step 3. Check accessibility
|
||||
|
||||
In case the example and Document Server are installed on different computers, make sure that your server with the example installed has access to the Document Server with the address which you specify instead of **documentserver** in the configuration files.
|
||||
@ -222,13 +219,12 @@ Make sure that the Document Server has access to the server with the example ins
|
||||
2. Edit the following lines:
|
||||
|
||||
```
|
||||
server.address=address
|
||||
files.storage=
|
||||
server.port=port
|
||||
files.docservice.url.site=https://documentserver/
|
||||
```
|
||||
|
||||
Where the **documentserver** is the name of the server with the ONLYOFFICE Document Server installed.
|
||||
**address** is the address of the server or comment this line to use localhost, **port** is the any available port.
|
||||
|
||||
where the **documentserver** is the name of the server with the ONLYOFFICE Docs installed, **port** is any available port and **files.storage** is the path where files will be created and stored (in the project folder by default). You can set an absolute path.
|
||||
|
||||
3. Run the next command in the java example directory:
|
||||
|
||||
@ -236,7 +232,16 @@ Make sure that the Document Server has access to the server with the example ins
|
||||
docker-compose up
|
||||
```
|
||||
4. Open your browser using **server.address** and **server.port**:
|
||||
|
||||
|
||||
```
|
||||
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.
|
||||
@ -7,7 +7,9 @@ services:
|
||||
image: maven:3.8.1
|
||||
working_dir: /java-spring
|
||||
volumes:
|
||||
- .:/java-spring
|
||||
- .:/java-spring
|
||||
ports:
|
||||
- 4000:4000
|
||||
command: mvn clean spring-boot:run
|
||||
|
||||
|
||||
@ -40,7 +40,9 @@ public class ExampleData {
|
||||
"Can perform all actions with comments",
|
||||
"The file favorite state is undefined",
|
||||
"Can't mention others in comments",
|
||||
"Can't create new files from the editor"
|
||||
"Can't create new files from the editor",
|
||||
"Can’t see anyone’s information",
|
||||
"Can't rename files from the editor"
|
||||
);
|
||||
List<String> description_user_1 = List.of( // the description for user 1
|
||||
"File author by default",
|
||||
@ -48,14 +50,16 @@ public class ExampleData {
|
||||
"He can review all the changes",
|
||||
"He can do everything with the comments",
|
||||
"The file favorite state is undefined",
|
||||
"Can create a file from a template with data from the editor"
|
||||
"Can create a file from a template with data from the editor",
|
||||
"Can see the information about all users"
|
||||
);
|
||||
List<String> description_user_2 = List.of( // the description for user 2
|
||||
"He belongs to Group2",
|
||||
"He can review only his own changes or the changes made by the users who don’t belong to any of the groups",
|
||||
"He can view every comment, edit his comments and the comments left by the users who don't belong to any of the groups and remove only his comments",
|
||||
"This file is favorite",
|
||||
"Can create a file from an editor"
|
||||
"Can create a file from an editor",
|
||||
"Can see the information about users from Group2 and users who don’t belong to any group"
|
||||
);
|
||||
List<String> description_user_3 = List.of( // the description for user 3
|
||||
"He belongs to Group3",
|
||||
@ -65,21 +69,24 @@ public class ExampleData {
|
||||
"He can’t copy data from the file into the clipboard",
|
||||
"He can’t download the file",
|
||||
"He can’t print the file",
|
||||
"Can create a file from an editor"
|
||||
"Can create a file from an editor",
|
||||
"Can see the information about Group2 users"
|
||||
);
|
||||
userService.createUser("John Smith", "smith@example.com", // create user 1 with the specified parameters
|
||||
description_user_1, null, List.of(FilterState.NULL.toString()),
|
||||
description_user_1, "", List.of(FilterState.NULL.toString()),
|
||||
List.of(FilterState.NULL.toString()),
|
||||
List.of(FilterState.NULL.toString()),
|
||||
List.of(FilterState.NULL.toString()), null);
|
||||
List.of(FilterState.NULL.toString()),
|
||||
List.of(FilterState.NULL.toString()),
|
||||
null);
|
||||
userService.createUser("Mark Pottato", "pottato@example.com", // create user 2 with the specified parameters
|
||||
description_user_2, "group-2", List.of("","group-2"), List.of(FilterState.NULL.toString()),
|
||||
List.of("group-2", ""), List.of("group-2"), true);
|
||||
List.of("group-2", ""), List.of("group-2"), List.of("group-2", ""), true);
|
||||
userService.createUser("Hamish Mitchell", "mitchell@example.com", // create user 3 with the specified parameters
|
||||
description_user_3, "group-3", List.of("group-2"), List.of("group-2", "group-3"),
|
||||
List.of("group-2"), new ArrayList<>(), false);
|
||||
List.of("group-2"), new ArrayList<>(), List.of("group-2"), false);
|
||||
userService.createUser("Anonymous",null, // create user 0 with the specified parameters
|
||||
description_user_0,null, List.of(FilterState.NULL.toString()), List.of(FilterState.NULL.toString()),
|
||||
List.of(FilterState.NULL.toString()), List.of(FilterState.NULL.toString()), null);
|
||||
description_user_0,"", List.of(FilterState.NULL.toString()), List.of(FilterState.NULL.toString()),
|
||||
List.of(FilterState.NULL.toString()), List.of(FilterState.NULL.toString()), new ArrayList<>(),null);
|
||||
}
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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) {
|
||||
@ -104,6 +113,18 @@ public class FileController {
|
||||
.body(resource);
|
||||
}
|
||||
|
||||
// download data from the specified history file
|
||||
private ResponseEntity<Resource> downloadFileHistory(String fileName, String version, String file){
|
||||
Resource resource = storageMutator.loadFileAsResourceHistory(fileName,version,file); // load the specified file as a resource
|
||||
String contentType = "application/octet-stream";
|
||||
|
||||
// create a response with the content type, header and body with the file data
|
||||
return ResponseEntity.ok()
|
||||
.contentType(MediaType.parseMediaType(contentType))
|
||||
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + resource.getFilename() + "\"")
|
||||
.body(resource);
|
||||
}
|
||||
|
||||
@PostMapping("/upload")
|
||||
@ResponseBody
|
||||
public String upload(@RequestParam("file") MultipartFile file, // upload a file
|
||||
@ -202,6 +223,29 @@ public class FileController {
|
||||
}
|
||||
}
|
||||
|
||||
@GetMapping("/downloadhistory")
|
||||
public ResponseEntity<Resource> downloadHistory(HttpServletRequest request,// download a file
|
||||
@RequestParam("fileName") String fileName,
|
||||
@RequestParam("ver") String version,
|
||||
@RequestParam("file") String file){ // history file
|
||||
try{
|
||||
// check if a token is enabled or not
|
||||
if(jwtManager.tokenEnabled()){
|
||||
String header = request.getHeader(documentJwtHeader == null // get the document JWT header
|
||||
|| documentJwtHeader.isEmpty() ? "Authorization" : documentJwtHeader);
|
||||
if(header != null && !header.isEmpty()){
|
||||
String token = header.replace("Bearer ", ""); // token is the header without the Bearer prefix
|
||||
jwtManager.readToken(token); // read the token
|
||||
}else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return downloadFileHistory(fileName,version,file); // download data from the specified file
|
||||
} catch(Exception e){
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@GetMapping(path = "${url.download}")
|
||||
public ResponseEntity<Resource> download(HttpServletRequest request, // download a file
|
||||
@RequestParam("fileName") String fileName){
|
||||
@ -321,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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -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";
|
||||
}
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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
|
||||
}
|
||||
|
||||
@ -94,7 +94,10 @@ public class DefaultCallbackManager implements CallbackManager {
|
||||
String newFileName = fileName;
|
||||
|
||||
String curExt = fileUtility.getFileExtension(fileName); // get current file extension
|
||||
String downloadExt = fileUtility.getFileExtension(downloadUri); // get an extension of the downloaded file
|
||||
String downloadExt = "." + body.getFiletype(); // get an extension of the downloaded file
|
||||
|
||||
// Todo [Delete in version 7.0 or higher]
|
||||
if (downloadExt != "." + null) downloadExt = fileUtility.getFileExtension(downloadUri); // Support for versions below 7.0
|
||||
|
||||
//TODO: Refactoring
|
||||
if (!curExt.equals(downloadExt)) { // convert downloaded file to the file with the current extension if these extensions aren't equal
|
||||
@ -150,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
|
||||
{
|
||||
@ -212,7 +219,11 @@ public class DefaultCallbackManager implements CallbackManager {
|
||||
String downloadUri = body.getUrl();
|
||||
|
||||
String curExt = fileUtility.getFileExtension(fileName); // get current file extension
|
||||
String downloadExt = fileUtility.getFileExtension(downloadUri); // get an extension of the downloaded file
|
||||
String downloadExt = "."+body.getFiletype(); // get an extension of the downloaded file
|
||||
|
||||
// Todo [Delete in version 7.0 or higher]
|
||||
if (downloadExt != "."+null) downloadExt = fileUtility.getFileExtension(downloadUri); // Support for versions below 7.0
|
||||
|
||||
Boolean newFileName = false;
|
||||
|
||||
// convert downloaded file to the file with the current extension if these extensions aren't equal
|
||||
|
||||
@ -45,6 +45,8 @@ public class DefaultDocumentManager implements DocumentManager {
|
||||
|
||||
@Value("${files.storage.folder}")
|
||||
private String storageFolder;
|
||||
@Value("${files.storage}")
|
||||
private String filesStorage;
|
||||
@Value("${url.track}")
|
||||
private String trackUrl;
|
||||
@Value("${url.download}")
|
||||
@ -93,6 +95,9 @@ public class DefaultDocumentManager implements DocumentManager {
|
||||
String hostAddress = storagePathBuilder.getStorageLocation(); // get the storage directory
|
||||
String filePathDownload = !fileName.contains(InetAddress.getLocalHost().getHostAddress()) ? fileName
|
||||
: fileName.substring(fileName.indexOf(InetAddress.getLocalHost().getHostAddress()) + InetAddress.getLocalHost().getHostAddress().length() + 1);
|
||||
if (!filesStorage.isEmpty() && filePathDownload.contains(filesStorage)) {
|
||||
filePathDownload = filePathDownload.substring(filesStorage.length() + 1);
|
||||
}
|
||||
|
||||
String filePath = serverPath + "/download?fileName=" + URLEncoder.encode(filePathDownload, java.nio.charset.StandardCharsets.UTF_8.toString())
|
||||
+ "&userAddress" + URLEncoder.encode(hostAddress, java.nio.charset.StandardCharsets.UTF_8.toString());
|
||||
@ -104,6 +109,27 @@ public class DefaultDocumentManager implements DocumentManager {
|
||||
}
|
||||
}
|
||||
|
||||
// get file URL
|
||||
public String getHistoryFileUrl(String fileName, Integer version, String file, Boolean forDocumentServer)
|
||||
{
|
||||
try
|
||||
{
|
||||
String serverPath = storagePathBuilder.getServerUrl(forDocumentServer); // get server URL
|
||||
String hostAddress = storagePathBuilder.getStorageLocation(); // get the storage directory
|
||||
String filePathDownload = !fileName.contains(InetAddress.getLocalHost().getHostAddress()) ? fileName
|
||||
: fileName.substring(fileName.indexOf(InetAddress.getLocalHost().getHostAddress()) + InetAddress.getLocalHost().getHostAddress().length() + 1);
|
||||
|
||||
String filePath = serverPath + "/downloadhistory?fileName=" + URLEncoder.encode(filePathDownload, java.nio.charset.StandardCharsets.UTF_8.toString())
|
||||
+ "&ver=" + version + "&file="+file
|
||||
+ "&userAddress" + URLEncoder.encode(hostAddress, java.nio.charset.StandardCharsets.UTF_8.toString());
|
||||
return filePath;
|
||||
}
|
||||
catch (UnsupportedEncodingException | UnknownHostException e)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
// get the callback URL
|
||||
public String getCallback(String fileName)
|
||||
{
|
||||
|
||||
@ -25,6 +25,7 @@ import java.util.Map;
|
||||
public interface DocumentManager {
|
||||
String getCorrectName(String fileName); // get a file name with an index if the file with such a name already exists
|
||||
String getFileUri(String fileName, Boolean forDocumentServer); // get file URL
|
||||
String getHistoryFileUrl(String fileName, Integer version, String file, Boolean forDocumentServer); // get file URL
|
||||
String getCallback(String fileName); // get the callback URL
|
||||
String getDownloadUrl(String fileName); // get URL to download a file
|
||||
ArrayList<Map<String, Object>> getFilesInfo(); // get file information
|
||||
|
||||
@ -87,9 +87,10 @@ public class DefaultHistoryManager implements HistoryManager {
|
||||
obj.put("user", user);
|
||||
}
|
||||
|
||||
dataObj.put("fileType", fileUtility.getFileExtension(document.getTitle()).replace(".", ""));
|
||||
dataObj.put("key", key);
|
||||
dataObj.put("url", i == curVer ? document.getUrl() :
|
||||
documentManager.getFileUri(documentManager.versionDir(histDir, i, true) + File.separator + "prev" + fileUtility.getFileExtension(document.getTitle()), true));
|
||||
documentManager.getHistoryFileUrl(document.getTitle(), i, "prev" + fileUtility.getFileExtension(document.getTitle()), true));
|
||||
dataObj.put("version", i);
|
||||
|
||||
if (i > 1) { //check if the version number is greater than 1
|
||||
@ -105,11 +106,13 @@ public class DefaultHistoryManager implements HistoryManager {
|
||||
|
||||
Map<String, Object> prev = (Map<String, Object>) histData.get(Integer.toString(i - 2)); // get the history data from the previous file version
|
||||
Map<String, Object> prevInfo = new HashMap<String, Object>();
|
||||
prevInfo.put("fileType", prev.get("fileType"));
|
||||
prevInfo.put("key", prev.get("key")); // write key and URL information about previous file version
|
||||
prevInfo.put("url", prev.get("url"));
|
||||
dataObj.put("previous", prevInfo); // write information about previous file version to the data object
|
||||
// write the path to the diff.zip archive with differences in this file version
|
||||
dataObj.put("changesUrl", documentManager.getFileUri(documentManager.versionDir(histDir, i - 1, true) + File.separator + "diff.zip", true));
|
||||
Integer verdiff = i - 1;
|
||||
dataObj.put("changesUrl", documentManager.getHistoryFileUrl(document.getTitle(), verdiff, "diff.zip", true));
|
||||
}
|
||||
|
||||
if (jwtManager.tokenEnabled()) dataObj.put("token", jwtManager.createToken(dataObj));
|
||||
|
||||
@ -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)
|
||||
@ -44,4 +43,6 @@ public class Customization { // the parameters which allow to customize the edi
|
||||
private Boolean hideRightMenu = false; // if the right menu is displayed or hidden on first loading
|
||||
private Boolean hideRulers = false; // if the editor rulers are displayed or hidden
|
||||
private Boolean submitForm = false; // if the Submit form button is displayed or hidden
|
||||
private Boolean about = true;
|
||||
private Boolean feedback =true;
|
||||
}
|
||||
|
||||
@ -20,7 +20,6 @@ package com.onlyoffice.integration.documentserver.models.configurations;
|
||||
|
||||
import com.onlyoffice.integration.documentserver.storage.FileStoragePathBuilder;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.annotation.Scope;
|
||||
@ -30,8 +29,6 @@ import javax.annotation.PostConstruct;
|
||||
|
||||
@Component
|
||||
@Scope("prototype")
|
||||
@Getter
|
||||
@Setter
|
||||
public class Goback { // the settings for the Open file location menu button and upper right corner button
|
||||
|
||||
@Autowired
|
||||
@ -39,10 +36,12 @@ public class Goback { // the settings for the Open file location menu button an
|
||||
|
||||
@Value("${url.index}")
|
||||
private String indexMapping;
|
||||
|
||||
@Getter
|
||||
private String url; // the absolute URL to the website address which will be opened when clicking the Open file location menu button
|
||||
|
||||
@PostConstruct
|
||||
private void init(){
|
||||
this.url = storagePathBuilder.getServerUrl(false)+indexMapping;
|
||||
private void init() {
|
||||
this.url = storagePathBuilder.getServerUrl(false) + indexMapping;
|
||||
}
|
||||
}
|
||||
|
||||
@ -49,5 +49,7 @@ public enum Language {
|
||||
es,
|
||||
tr,
|
||||
uk,
|
||||
vi
|
||||
vi,
|
||||
gl,
|
||||
az
|
||||
}
|
||||
|
||||
@ -47,4 +47,6 @@ public class Permission extends AbstractModel { // the permission for the docum
|
||||
private List<String> reviewGroups; // the groups whose changes the user can accept/reject
|
||||
@Autowired
|
||||
private CommentGroup commentGroups; // the groups whose comments the user can edit, remove and/or view
|
||||
@JsonInclude(value = JsonInclude.Include.CUSTOM, valueFilter = SerializerFilter.class)
|
||||
private List<String> userInfoGroups;
|
||||
}
|
||||
|
||||
@ -16,6 +16,7 @@ public interface FileStorageMutator {
|
||||
boolean writeToFile(String pathName, String payload); // write the payload to the file
|
||||
boolean moveFile(Path source, Path destination); // move a file to the specified destination
|
||||
Resource loadFileAsResource(String fileName); // load file as a resource
|
||||
Resource loadFileAsResourceHistory(String fileName,String version,String file); // load file as a resource
|
||||
File[] getStoredFiles(); // get a collection of all the stored files
|
||||
void createMeta(String fileName, String uid, String uname); // create the file meta information
|
||||
boolean createOrUpdateFile(Path path, InputStream stream); // create or update a file
|
||||
|
||||
@ -85,10 +85,18 @@ public class LocalFileStorage implements FileStorageMutator, FileStoragePathBuil
|
||||
// get the storage directory
|
||||
public String getStorageLocation(){
|
||||
String serverPath = System.getProperty("user.dir"); // get the path to the server
|
||||
String directory = serverPath // create the storage directory
|
||||
+ File.separator + storageFolder
|
||||
+ File.separator + this.storageAddress
|
||||
+ File.separator;
|
||||
String directory; // create the storage directory
|
||||
if (Paths.get(this.storageAddress).isAbsolute()) {
|
||||
directory = this.storageAddress + File.separator;
|
||||
} else {
|
||||
directory = serverPath
|
||||
+ File.separator + storageFolder
|
||||
+ File.separator + this.storageAddress
|
||||
+ File.separator;
|
||||
}
|
||||
if (!Files.exists(Paths.get(directory))) {
|
||||
createDirectory(Paths.get(directory));
|
||||
}
|
||||
|
||||
return directory;
|
||||
}
|
||||
@ -238,6 +246,20 @@ public class LocalFileStorage implements FileStorageMutator, FileStoragePathBuil
|
||||
return null;
|
||||
}
|
||||
|
||||
public Resource loadFileAsResourceHistory(String fileName,String version,String file){
|
||||
|
||||
String fileLocation = getStorageLocation() + fileName + "-hist" + File.separator + version + File.separator + file; // get it by the file name
|
||||
|
||||
try {
|
||||
Path filePath = Paths.get(fileLocation); // get the path to the file location
|
||||
Resource resource = new UrlResource(filePath.toUri()); // convert the file path to URL
|
||||
if(resource.exists()) return resource;
|
||||
} catch (MalformedURLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// get a collection of all the stored files
|
||||
public File[] getStoredFiles()
|
||||
{
|
||||
|
||||
@ -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());
|
||||
}
|
||||
|
||||
}
|
||||
@ -59,7 +59,7 @@ public class DefaultFileUtility implements FileUtility {
|
||||
|
||||
// spreadsheet extensions
|
||||
private List<String> ExtsSpreadsheet = Arrays.asList(
|
||||
".xls", ".xlsx", ".xlsm",
|
||||
".xls", ".xlsx", ".xlsm", ".xlsb",
|
||||
".xlt", ".xltx", ".xltm",
|
||||
".ods", ".fods", ".ots", ".csv");
|
||||
|
||||
|
||||
@ -47,4 +47,6 @@ public class Permission extends AbstractEntity {
|
||||
private List<Group> commentsEditGroups;
|
||||
@ManyToMany
|
||||
private List<Group> commentsRemoveGroups;
|
||||
@ManyToMany
|
||||
private List<Group> userInfoGroups;
|
||||
}
|
||||
|
||||
@ -54,5 +54,6 @@ public class PermissionsMapper extends AbstractMapper<Permission, com.onlyoffice
|
||||
source.getCommentsRemoveGroups().stream().map(g -> g.getName()).collect(Collectors.toList())
|
||||
)
|
||||
);
|
||||
destination.setUserInfoGroups(source.getUserInfoGroups().stream().map(g -> g.getName()).collect(Collectors.toList()));
|
||||
}
|
||||
}
|
||||
|
||||
@ -36,13 +36,15 @@ public class PermissionServices {
|
||||
public Permission createPermission(List<Group> reviewGroups,
|
||||
List<Group> commentViewGroups,
|
||||
List<Group> commentEditGroups,
|
||||
List<Group> commentRemoveGroups){
|
||||
List<Group> commentRemoveGroups,
|
||||
List<Group> userInfoGroups){
|
||||
|
||||
Permission permission = new Permission();
|
||||
permission.setReviewGroups(reviewGroups); // define the groups whose changes the user can accept/reject
|
||||
permission.setCommentsViewGroups(commentViewGroups); // defines the groups whose comments the user can view
|
||||
permission.setCommentsEditGroups(commentEditGroups); // defines the groups whose comments the user can edit
|
||||
permission.setCommentsRemoveGroups(commentRemoveGroups); // defines the groups whose comments the user can remove
|
||||
permission.setUserInfoGroups(userInfoGroups);
|
||||
|
||||
permissionRepository.save(permission); // save new permissions
|
||||
|
||||
|
||||
@ -56,7 +56,7 @@ public class UserServices {
|
||||
List<String> reviewGroups,
|
||||
List<String> viewGroups,
|
||||
List<String> editGroups,
|
||||
List<String> removeGroups, Boolean favoriteDoc){
|
||||
List<String> removeGroups, List<String> userInfoGroups, Boolean favoriteDoc){
|
||||
User newUser = new User();
|
||||
newUser.setName(name); // set the user name
|
||||
newUser.setEmail(email); // set the user email
|
||||
@ -68,9 +68,10 @@ public class UserServices {
|
||||
List<Group> commentGroupsView = groupServices.createGroups(viewGroups); // defines the groups whose comments the user can view
|
||||
List<Group> commentGroupsEdit = groupServices.createGroups(editGroups); // defines the groups whose comments the user can edit
|
||||
List<Group> commentGroupsRemove = groupServices.createGroups(removeGroups); // defines the groups whose comments the user can remove
|
||||
List<Group> usInfoGroups = groupServices.createGroups(userInfoGroups);
|
||||
|
||||
Permission permission = permissionService
|
||||
.createPermission(groupsReview, commentGroupsView, commentGroupsEdit, commentGroupsRemove); // specify permissions for the current user
|
||||
.createPermission(groupsReview, commentGroupsView, commentGroupsEdit, commentGroupsRemove, usInfoGroups); // specify permissions for the current user
|
||||
newUser.setPermissions(permission);
|
||||
|
||||
userRepository.save(newUser); // save a new user
|
||||
|
||||
@ -85,7 +85,7 @@ public class DefaultEditorConfigConfigurer implements EditorConfigConfigurer<Def
|
||||
|
||||
defaultCustomizationConfigurer.configure(config.getCustomization(), DefaultCustomizationWrapper.builder() // define the customization configurer
|
||||
.action(action)
|
||||
.user(wrapper.getUser())
|
||||
.user(userIsAnon ? null : wrapper.getUser())
|
||||
.build());
|
||||
config.setMode(canEdit && !action.equals(Action.view) ? Mode.edit : Mode.view);
|
||||
config.setUser(mapper.toModel(wrapper.getUser()));
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
server.version=1.0.0
|
||||
server.version=1.2.0
|
||||
|
||||
server.address=127.0.0.1
|
||||
server.address=
|
||||
server.port=4000
|
||||
|
||||
filesize-max=5242880
|
||||
@ -11,7 +11,7 @@ files.storage.folder=documents
|
||||
files.docservice.fillforms-docs=.oform|.docx
|
||||
files.docservice.viewed-docs=.pdf|.djvu|.xps|.oxps
|
||||
files.docservice.edited-docs=.docx|.xlsx|.csv|.pptx|.txt|.docxf
|
||||
files.docservice.convert-docs=.docm|.dotx|.dotm|.dot|.doc|.odt|.fodt|.ott|.xlsm|.xltx|.xltm|.xlt|.xls|.ods|.fods|.ots|.pptm|.ppt|.ppsx|.ppsm|.pps|.potx|.potm|.pot|.odp|.fodp|.otp|.rtf|.mht|.html|.htm|.xml|.epub|.fb2
|
||||
files.docservice.convert-docs=.docm|.dotx|.dotm|.dot|.doc|.odt|.fodt|.ott|.xlsm|.xlsb|.xltx|.xltm|.xlt|.xls|.ods|.fods|.ots|.pptm|.ppt|.ppsx|.ppsm|.pps|.potx|.potm|.pot|.odp|.fodp|.otp|.rtf|.mht|.html|.htm|.xml|.epub|.fb2
|
||||
files.docservice.timeout=120000
|
||||
files.docservice.history.postfix=-hist
|
||||
|
||||
@ -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
|
||||
|
||||
@ -129,6 +129,10 @@
|
||||
height: 80px;
|
||||
}
|
||||
|
||||
.main {
|
||||
height: calc(100% - 128px);
|
||||
}
|
||||
|
||||
.left-panel {
|
||||
width: 90%;
|
||||
}
|
||||
@ -367,6 +371,10 @@
|
||||
height: 80px;
|
||||
}
|
||||
|
||||
.main {
|
||||
height: calc(100% - 128px);
|
||||
}
|
||||
|
||||
.copy {
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
@ -440,6 +448,58 @@
|
||||
display: none;
|
||||
width: 1%;
|
||||
}
|
||||
/* Mobile Upload*/
|
||||
.blockUI.blockMsg.blockPage.ui-dialog.ui-widget.ui-corner-all.ui-widget-content.ui-draggable {
|
||||
width: 344px !important;
|
||||
box-shadow: 0px 7px 15px rgba(85, 85, 85, 0.1);
|
||||
border-radius: 2px;
|
||||
top: 10% !important;
|
||||
margin-left: -172px !important;
|
||||
}
|
||||
|
||||
.ui-dialog .ui-dialog-titlebar {
|
||||
padding: 0;
|
||||
}
|
||||
.ui-dialog .ui-dialog-content {
|
||||
padding: 0 !important;
|
||||
}
|
||||
#mainProgress {
|
||||
margin: 24px 16px 0 !important;
|
||||
}
|
||||
.blockTitle {
|
||||
padding: 10px 10px 6px 16px !important;
|
||||
font-size: 14px !important;
|
||||
}
|
||||
#mainProgress .describeUpload {
|
||||
padding: 8px 0 !important;
|
||||
}
|
||||
.dialog-close {
|
||||
margin: 0 !important;
|
||||
}
|
||||
.step-descr{
|
||||
line-height: 150%;
|
||||
}
|
||||
.step {
|
||||
line-height: 160%;
|
||||
}
|
||||
.buttonsMobile{
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
.button.gray{
|
||||
margin: 0;
|
||||
}
|
||||
.button, .button:hover{
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
padding: 0 !important;
|
||||
width: 144px;
|
||||
height: 56px;
|
||||
margin-bottom: 24px !important;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 560px) and (min-width: 510px) {
|
||||
|
||||
@ -22,7 +22,7 @@ html {
|
||||
}
|
||||
|
||||
body {
|
||||
display: inline-table;
|
||||
display: block;
|
||||
background: #FFFFFF;
|
||||
color: #333333;
|
||||
font-family: Open Sans;
|
||||
@ -98,6 +98,10 @@ header img {
|
||||
width: 896px;
|
||||
}
|
||||
|
||||
#portal-info {
|
||||
max-width: 65vw;
|
||||
}
|
||||
|
||||
.portal-name {
|
||||
color: #FF6F3D;
|
||||
font-size: 24px;
|
||||
@ -740,12 +744,9 @@ html {
|
||||
width: 30vw;
|
||||
min-width: 200px;
|
||||
max-width: 400px;
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.user-descr > b {
|
||||
margin-left: 25px;
|
||||
}
|
||||
|
||||
.portal-descr:nth-child(3) {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
@ -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) {
|
||||
@ -195,6 +217,12 @@
|
||||
};
|
||||
|
||||
var сonnectEditor = function () {
|
||||
if ((config.document.fileType === "docxf" || config.document.fileType === "oform")
|
||||
&& DocsAPI.DocEditor.version().split(".")[0] < 7) {
|
||||
innerAlert("Please update ONLYOFFICE Docs to version 7.0 to work on fillable forms online.");
|
||||
return;
|
||||
}
|
||||
|
||||
docEditor = new DocsAPI.DocEditor("iframeEditor", config);
|
||||
};
|
||||
|
||||
|
||||
@ -2,6 +2,7 @@
|
||||
<html xmlns:th="http://www.thymeleaf.org">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||
<meta name="viewport" content="width=device-width" />
|
||||
<!--
|
||||
*
|
||||
* (c) Copyright Ascensio System SIA 2021
|
||||
@ -55,7 +56,7 @@
|
||||
<a class="try-editor slide" data-type="pptx">Presentation</a>
|
||||
</li>
|
||||
<li>
|
||||
<a class="try-editor form" data-type="docxf">Master form</a>
|
||||
<a class="try-editor form" data-type="docxf">Form template</a>
|
||||
</li>
|
||||
</ul>
|
||||
<label class="create-sample">
|
||||
@ -86,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>
|
||||
@ -127,12 +100,13 @@
|
||||
</td>
|
||||
<td class="section">
|
||||
<div class="main-panel">
|
||||
<div id="portal-info" th:attr="tooltip=${tooltip}" th:style="${not #lists.isEmpty(files)} ? 'display: none' : 'display: block' ">
|
||||
<div id="portal-info" th:attr="tooltip=${tooltip}" th:style="${not #lists.isEmpty(files)} ? 'display: none' : 'display: table-cell' ">
|
||||
<span class="portal-name">ONLYOFFICE Document Editors – Welcome!</span>
|
||||
<span class="portal-descr">
|
||||
Get started with a demo-sample of ONLYOFFICE Document Editors, the first html5-based editors.
|
||||
<br /> You may upload your own documents for testing using the "<b>Upload file</b>" button and <b>selecting</b> the necessary files on your PC.
|
||||
</span>
|
||||
<span class="portal-descr">Please do NOT use this integration example on your own server without proper code modifications, it is intended for testing purposes only. In case you enabled this test example, disable it before going for production.</span>
|
||||
<span class="portal-descr">You can open the same document using different users in different Web browser sessions, so you can check out multi-user editing functions.</span>
|
||||
</div>
|
||||
<th:block th:if="${not #lists.isEmpty(files)}">
|
||||
@ -189,9 +163,6 @@
|
||||
</a>
|
||||
</td>
|
||||
</div>
|
||||
<div th:if="${docTypes[iState.index]} eq 'slide'">
|
||||
<td class="contentCells contentCells-icon contentCellsEmpty"></td>
|
||||
</div>
|
||||
<div th:if="${docTypes[iState.index]} eq 'word'">
|
||||
<td class="contentCells contentCells-icon">
|
||||
<a th:href="@{/editor(fileName=${files[iState.index].getName()},type='desktop',action='blockcontent')}" target="_blank">
|
||||
@ -298,10 +269,8 @@
|
||||
<span class="step-descr">They are loaded only once, they will be cached on your computer.</span>
|
||||
<input type="hidden" name="hiddenFileName" id="hiddenFileName" />
|
||||
<br />
|
||||
<br />
|
||||
<span class="progress-descr">Note the speed of all operations depends on your connection quality and server location.</span>
|
||||
<br />
|
||||
<br />
|
||||
<div class="error-message">
|
||||
<b>Upload error: </b><span></span>
|
||||
<br />
|
||||
@ -310,10 +279,12 @@
|
||||
</div>
|
||||
<iframe id="embeddedView" src="" height="345px" width="432px" frameborder="0" scrolling="no" allowtransparency></iframe>
|
||||
<br />
|
||||
<div id="beginEdit" class="button orange disable">Edit</div>
|
||||
<div id="beginView" class="button gray disable">View</div>
|
||||
<div id="beginEmbedded" class="button gray disable">Embedded view</div>
|
||||
<div id="cancelEdit" class="button gray">Cancel</div>
|
||||
<div class="buttonsMobile">
|
||||
<div id="beginEdit" class="button orange disable">Edit</div>
|
||||
<div id="beginView" class="button gray disable">View</div>
|
||||
<div id="beginEmbedded" class="button gray disable">Embedded view</div>
|
||||
<div id="cancelEdit" class="button gray">Cancel</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<span id="loadScripts" th:attr="data-docs=${datadocs}"></span>
|
||||
@ -346,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>
|
||||
9
web/documentserver-example/java/Dockerfile
Normal file
9
web/documentserver-example/java/Dockerfile
Normal file
@ -0,0 +1,9 @@
|
||||
FROM maven:3.6.1-jdk-8-alpine AS MVN_BLDR
|
||||
COPY pom.xml /tmp/
|
||||
COPY src /tmp/src/
|
||||
WORKDIR /tmp/
|
||||
RUN mvn package
|
||||
|
||||
FROM tomcat:alpine
|
||||
RUN rm -fr /usr/local/tomcat/webapps/ROOT
|
||||
COPY --from=MVN_BLDR /tmp/target/*.war $CATALINA_HOME/webapps/ROOT.war
|
||||
@ -1,14 +1,14 @@
|
||||
## Overview
|
||||
|
||||
This example will help you integrate ONLYOFFICE Docs into your web application written in Java.
|
||||
This example will help you integrate ONLYOFFICE Docs into your web application written in Java.
|
||||
|
||||
It is aimed at testing the editors. Please, do not use it for production without proper modifications.
|
||||
**Please note**: It is intended for testing purposes and demonstrating functionality of the editors. Do NOT use this integration example on your own server without proper code modifications! In case you enabled the test example, disable it before going for production.
|
||||
|
||||
## For Windows
|
||||
|
||||
### Step 1. Install ONLYOFFICE Docs
|
||||
|
||||
Download and install ONLYOFFICE Docs (packaged as Document Server).
|
||||
Download and install ONLYOFFICE Docs (packaged as Document Server).
|
||||
|
||||
See the detailed guide to learn how to [install Document Server for Windows](https://helpcenter.onlyoffice.com/installation/docs-developer-install-windows.aspx).
|
||||
|
||||
@ -16,13 +16,14 @@ See the detailed guide to learn how to [install Document Server for Windows](htt
|
||||
|
||||
Download the [Java example](https://api.onlyoffice.com/editors/demopreview) from our site.
|
||||
|
||||
To connect the editors to your website, specify the path to the editors installation in the *\src\main\resources\settings.properties* file:
|
||||
To connect the editors to your website, specify the path to the editors installation and the path to the storage folder in the *\src\main\resources\settings.properties* file:
|
||||
|
||||
```
|
||||
storage-folder = app_data
|
||||
files.docservice.url.site=https://documentserver/
|
||||
```
|
||||
|
||||
where the **documentserver** is the name of the server with the ONLYOFFICE Document Server installed.
|
||||
where the **documentserver** is the name of the server with the ONLYOFFICE Document Server installed and the **storage-folder** is the path where files will be created and stored. You can set an absolute path. For example, *D:\\\\folder*. Please note that on Windows OS the double backslash must be used as a separator.
|
||||
|
||||
If you want to experiment with the editor configuration, modify the [parameters](https://api.onlyoffice.com/editors/advanced) in the *\src\main\webapp\editor.jsp* file.
|
||||
|
||||
@ -96,7 +97,7 @@ To run the Java example code, install the Java version appropriate for your OS a
|
||||
2. Tomcat Web Application Manager will request the **username** and the **password:**
|
||||
|
||||

|
||||
|
||||
|
||||
|
||||
Specify user data in *tomcat-users.xml* file in the Apache Tomcat installation folder. Define the **manager-gui** user role, specify the **user name** and **password** values:
|
||||
|
||||
@ -106,18 +107,22 @@ To run the Java example code, install the Java version appropriate for your OS a
|
||||
<user username="tomcat" password="tomcat" roles="manager-gui"/>
|
||||
</tomcat-users>
|
||||
```
|
||||
|
||||
3. Upload the Java project in Tomcat Web Application Manager. For that click **Choose File** in the **WAR file to deploy** section and find the *.war* file in the Java project folder, then click **Deploy**.
|
||||
3. Build the project using the following commands
|
||||
```
|
||||
mvn clean
|
||||
mvn package
|
||||
```
|
||||
4. Upload the Java project in Tomcat Web Application Manager. For that click **Choose File** in the **WAR file to deploy** section and find the *.war* file in the Java project folder, then click **Deploy**.
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
4. You will see the project in the **Application List**:
|
||||
|
||||
5. You will see the project in the **Application List**:
|
||||
|
||||

|
||||
|
||||
5. Click the link with the application name to run it.
|
||||
|
||||
6. Click the link with the application name to run it.
|
||||
|
||||
### Step 6. Check accessibility
|
||||
|
||||
@ -163,13 +168,17 @@ See the detailed guide to learn how to [install Document Server for Linux](https
|
||||
nano src/main/resources/settings.properties
|
||||
```
|
||||
|
||||
Edit the following line:
|
||||
Edit the following lines:
|
||||
|
||||
```
|
||||
storage-folder = app_data
|
||||
files.docservice.url.site=https://documentserver/
|
||||
```
|
||||
|
||||
where the **documentserver** is the name of the server with the ONLYOFFICE Document Server installed.
|
||||
where the **documentserver** is the name of the server with the ONLYOFFICE Document Server installed and the **storage-folder** is the path where files will be created and stored. Please note that you must have read and write permissions to the folder. If you do not have them, please use the next command:
|
||||
```
|
||||
sudo chmod -R ugo+rw /{path}
|
||||
```
|
||||
|
||||
5. Install **Maven**:
|
||||
|
||||
@ -238,13 +247,14 @@ Make sure that the Document Server has access to the server with the example ins
|
||||
nano src/main/resources/settings.properties
|
||||
```
|
||||
|
||||
2. Edit the following line:
|
||||
2. Edit the following lines:
|
||||
|
||||
```
|
||||
storage-folder = app_data
|
||||
files.docservice.url.site=https://documentserver/
|
||||
```
|
||||
|
||||
where the **documentserver** is the name of the server with the ONLYOFFICE Document Server installed.
|
||||
where the **documentserver** is the name of the server with the ONLYOFFICE Document Server installed and the **storage-folder** is the path where files will be created and stored.
|
||||
|
||||
3. Run the next command in the Java example directory:
|
||||
|
||||
@ -253,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.
|
||||
@ -1,7 +1,9 @@
|
||||
version: '3'
|
||||
services:
|
||||
build:
|
||||
image: maven:3.6
|
||||
volumes:
|
||||
- .:/java
|
||||
command: mvn -f /java package
|
||||
java-intg-ex:
|
||||
build:
|
||||
context: ./
|
||||
dockerfile: Dockerfile
|
||||
ports:
|
||||
- 8080:8080
|
||||
|
||||
|
||||
@ -45,8 +45,8 @@
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.1</version>
|
||||
<configuration>
|
||||
<source>1.7</source>
|
||||
<target>1.7</target>
|
||||
<source>8</source>
|
||||
<target>8</target>
|
||||
<compilerArguments>
|
||||
<endorseddirs>${endorsed.dir}</endorseddirs>
|
||||
</compilerArguments>
|
||||
|
||||
@ -72,7 +72,7 @@ public class EditorServlet extends HttpServlet
|
||||
// create file model (get all the necessary parameters from cookies)
|
||||
FileModel file = new FileModel(fileName, cm.getCookie("ulang"), request.getParameter("actionLink"), user);
|
||||
// change type parameter if needed
|
||||
file.changeType(request.getParameter("mode"), request.getParameter("type"), user);
|
||||
file.changeType(request.getParameter("mode"), request.getParameter("type"), user, fileName);
|
||||
|
||||
// an image that will be inserted into the document
|
||||
Map<String, Object> dataInsertImage = new HashMap<>();
|
||||
|
||||
@ -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()
|
||||
|
||||
81
web/documentserver-example/java/src/main/java/controllers/IndexServlet.java
Normal file → Executable file
81
web/documentserver-example/java/src/main/java/controllers/IndexServlet.java
Normal file → Executable 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
|
||||
@ -72,6 +77,10 @@ public class IndexServlet extends HttpServlet
|
||||
break;
|
||||
case "download":
|
||||
Download(request, response, writer);
|
||||
break;
|
||||
case "downloadhistory":
|
||||
DownloadHistory(request, response, writer);
|
||||
break;
|
||||
case "convert":
|
||||
Convert(request, response, writer);
|
||||
break;
|
||||
@ -93,6 +102,9 @@ public class IndexServlet extends HttpServlet
|
||||
case "saveas":
|
||||
SaveAs(request, response, writer);
|
||||
break;
|
||||
case "rename":
|
||||
Rename(request, response, writer);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -317,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();
|
||||
}
|
||||
@ -430,14 +442,53 @@ public class IndexServlet extends HttpServlet
|
||||
download(filePath.toString(), response, writer);
|
||||
}
|
||||
|
||||
// download a file from history
|
||||
private static void DownloadHistory(HttpServletRequest request, HttpServletResponse response, PrintWriter writer)
|
||||
{
|
||||
try {
|
||||
if (DocumentManager.TokenEnabled()) {
|
||||
|
||||
String DocumentJwtHeader = ConfigManager.GetProperty("files.docservice.header");
|
||||
|
||||
String header = (String) request.getHeader(DocumentJwtHeader == null || DocumentJwtHeader.isEmpty() ? "Authorization" : DocumentJwtHeader);
|
||||
if (header != null && !header.isEmpty()) {
|
||||
String token = header.startsWith("Bearer ") ? header.substring(7) : header;
|
||||
try {
|
||||
Verifier verifier = HMACVerifier.newVerifier(DocumentManager.GetTokenSecret());
|
||||
JWT jwt = JWT.getDecoder().decode(token, verifier);
|
||||
} catch (Exception e) {
|
||||
response.sendError(403, "JWT validation failed");
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
response.sendError(403, "JWT validation failed");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
String fileName = FileUtility.GetFileName(request.getParameter("fileName"));
|
||||
String userAddress = request.getParameter("userAddress");
|
||||
|
||||
String ver = request.getParameter("ver"); // Document version
|
||||
String file = request.getParameter("file"); // File. If not defined, then Prev.*
|
||||
|
||||
String filePath = DocumentManager.HistoryPath(fileName, userAddress, ver, file);
|
||||
|
||||
download(filePath, response, writer);
|
||||
} catch (Exception e) {
|
||||
writer.write("{ \"error\": \"File not found\"}");
|
||||
}
|
||||
}
|
||||
|
||||
// download a file
|
||||
private static void Download(HttpServletRequest request, HttpServletResponse response, PrintWriter writer)
|
||||
{
|
||||
try {
|
||||
String fileName = FileUtility.GetFileName(request.getParameter("fileName"));
|
||||
String userAddress = request.getParameter("userAddress");
|
||||
String isEmbedded = request.getParameter("dmode");
|
||||
|
||||
if (DocumentManager.TokenEnabled()) {
|
||||
if (DocumentManager.TokenEnabled() && isEmbedded == null) {
|
||||
|
||||
String DocumentJwtHeader = ConfigManager.GetProperty("files.docservice.header");
|
||||
|
||||
@ -508,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
|
||||
|
||||
@ -20,16 +20,14 @@ package entities;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
import helpers.DocumentManager;
|
||||
import helpers.FileUtility;
|
||||
import helpers.ServiceConverter;
|
||||
import helpers.Users;
|
||||
import helpers.*;
|
||||
import org.json.simple.JSONArray;
|
||||
import org.json.simple.JSONObject;
|
||||
import org.json.simple.parser.JSONParser;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.*;
|
||||
|
||||
public class FileModel
|
||||
@ -54,7 +52,6 @@ public class FileModel
|
||||
document = new Document();
|
||||
document.title = fileName;
|
||||
document.url = DocumentManager.GetDownloadUrl(fileName); // get file url
|
||||
document.urlUser = DocumentManager.GetFileUri(fileName, false);
|
||||
document.fileType = FileUtility.GetFileExtension(fileName).replace(".", ""); // get file extension from the file name
|
||||
// generate document key
|
||||
document.key = ServiceConverter.GenerateRevisionId(DocumentManager.CurUserHostAddress(null) + "/" + fileName + "/" + Long.toString(new File(DocumentManager.StoragePath(fileName, null)).lastModified()));
|
||||
@ -87,18 +84,18 @@ public class FileModel
|
||||
editorConfig.templates = user.templates ? templates : null;
|
||||
|
||||
// write user information to the config (id, name and group)
|
||||
editorConfig.user.id = user.id;
|
||||
editorConfig.user.id = !user.id.equals("uid-0") ? user.id : null;
|
||||
editorConfig.user.name = user.name;
|
||||
editorConfig.user.group = user.group;
|
||||
|
||||
// write the absolute URL to the file location
|
||||
editorConfig.customization.goback.url = DocumentManager.GetServerUrl(false) + "/IndexServlet";
|
||||
|
||||
changeType(mode, type, user);
|
||||
changeType(mode, type, user, fileName);
|
||||
}
|
||||
|
||||
// change the document type
|
||||
public void changeType(String _mode, String _type, User user)
|
||||
public void changeType(String _mode, String _type, User user, String fileName)
|
||||
{
|
||||
if (_mode != null) mode = _mode;
|
||||
if (_type != null) type = _type;
|
||||
@ -119,12 +116,12 @@ public class FileModel
|
||||
// set document permissions
|
||||
document.permissions = new Permissions(mode, type, canEdit, user);
|
||||
|
||||
if (type.equals("embedded")) InitDesktop(); // set parameters for the embedded document
|
||||
if (type.equals("embedded")) InitDesktop(fileName); // set parameters for the embedded document
|
||||
}
|
||||
|
||||
public void InitDesktop()
|
||||
public void InitDesktop(String fileName)
|
||||
{
|
||||
editorConfig.InitDesktop(document.urlUser);
|
||||
editorConfig.InitDesktop(DocumentManager.GetDownloadUrl(fileName) + "&dmode=emb");
|
||||
}
|
||||
|
||||
// generate document token
|
||||
@ -167,7 +164,7 @@ public class FileModel
|
||||
obj.put("version", i);
|
||||
|
||||
if (i == 1) { // check if the version number is equal to 1
|
||||
String createdInfo = readFileToEnd(new File(histDir + File.separator + "createdInfo.json")); // get file with meta data
|
||||
String createdInfo = readFileToEnd(new File(histDir + File.separator + "createdInfo.json")); // get file with meta data
|
||||
JSONObject json = (JSONObject) parser.parse(createdInfo); // and turn it into json object
|
||||
|
||||
// write meta information to the object (user information and creation date)
|
||||
@ -178,8 +175,9 @@ public class FileModel
|
||||
obj.put("user", user);
|
||||
}
|
||||
|
||||
dataObj.put("fileType", FileUtility.GetFileExtension(document.title).substring(1));
|
||||
dataObj.put("key", key);
|
||||
dataObj.put("url", i == curVer ? document.url : DocumentManager.GetPathUri(verDir + File.separator + "prev" + FileUtility.GetFileExtension(document.title)));
|
||||
dataObj.put("url", i == curVer ? document.url : DocumentManager.GetDownloadHistoryUrl(document.title, i, "prev" + FileUtility.GetFileExtension(document.title)));
|
||||
dataObj.put("version", i);
|
||||
|
||||
if (i > 1) { //check if the version number is greater than 1
|
||||
@ -195,11 +193,14 @@ public class FileModel
|
||||
|
||||
Map<String, Object> prev = (Map<String, Object>) histData.get(Integer.toString(i - 2)); // get the history data from the previous file version
|
||||
Map<String, Object> prevInfo = new HashMap<String, Object>();
|
||||
prevInfo.put("fileType", prev.get("fileType"));
|
||||
prevInfo.put("key", prev.get("key")); // write key and url information about previous file version
|
||||
prevInfo.put("url", prev.get("url"));
|
||||
dataObj.put("previous", prevInfo); // write information about previous file version to the data object
|
||||
// write the path to the diff.zip archive with differences in this file version
|
||||
dataObj.put("changesUrl", DocumentManager.GetPathUri(DocumentManager.VersionDir(histDir, i - 1) + File.separator + "diff.zip"));
|
||||
Integer verdiff = i - 1;
|
||||
String changesUrl = DocumentManager.GetDownloadHistoryUrl(document.title, verdiff, "diff.zip");
|
||||
dataObj.put("changesUrl", changesUrl);
|
||||
}
|
||||
|
||||
if (DocumentManager.TokenEnabled())
|
||||
@ -246,7 +247,6 @@ public class FileModel
|
||||
{
|
||||
public String title;
|
||||
public String url;
|
||||
public String urlUser;
|
||||
public String fileType;
|
||||
public String key;
|
||||
public Info info;
|
||||
@ -267,6 +267,7 @@ public class FileModel
|
||||
public Boolean review;
|
||||
public List<String> reviewGroups;
|
||||
public CommentGroups commentGroups;
|
||||
public List<String> userInfoGroups;
|
||||
|
||||
// defines what can be done with a document
|
||||
public Permissions(String mode, String type, Boolean canEdit, User user)
|
||||
@ -282,13 +283,21 @@ public class FileModel
|
||||
review = canEdit && (mode.equals("edit") || mode.equals("review"));
|
||||
reviewGroups = user.reviewGroups;
|
||||
commentGroups = user.commentGroups;
|
||||
userInfoGroups = user.userInfoGroups;
|
||||
}
|
||||
}
|
||||
|
||||
// the Favorite icon state
|
||||
public class Info
|
||||
{
|
||||
public String owner = "Me";
|
||||
public Boolean favorite;
|
||||
public String uploaded = getDate();
|
||||
|
||||
private String getDate() {
|
||||
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("EEE MMM dd yyyy", Locale.US);
|
||||
return simpleDateFormat.format(new Date());
|
||||
}
|
||||
}
|
||||
// the editor config parameters
|
||||
public class EditorConfig
|
||||
@ -338,9 +347,15 @@ public class FileModel
|
||||
public Goback goback;
|
||||
public Boolean forcesave;
|
||||
public Boolean submitForm;
|
||||
public Boolean about;
|
||||
public Boolean comments;
|
||||
public Boolean feedback;
|
||||
|
||||
public Customization()
|
||||
{
|
||||
about = true;
|
||||
comments = true;
|
||||
feedback = true;
|
||||
forcesave = false;
|
||||
goback = new Goback();
|
||||
}
|
||||
|
||||
@ -31,8 +31,9 @@ public class User {
|
||||
public List<String> deniedPermissions;
|
||||
public List<String> descriptions;
|
||||
public Boolean templates;
|
||||
public List<String> userInfoGroups;
|
||||
|
||||
public User(String id, String name, String email, String group, List<String> reviewGroups, CommentGroups commentGroups,
|
||||
public User(String id, String name, String email, String group, List<String> reviewGroups, CommentGroups commentGroups, List<String> userInfoGroups,
|
||||
Boolean favorite, List<String> deniedPermissions, List<String> descriptions, Boolean templates) {
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
@ -44,5 +45,6 @@ public class User {
|
||||
this.deniedPermissions = deniedPermissions;
|
||||
this.descriptions = descriptions;
|
||||
this.templates = templates;
|
||||
this.userInfoGroups = userInfoGroups;
|
||||
}
|
||||
}
|
||||
72
web/documentserver-example/java/src/main/java/helpers/DocumentManager.java
Normal file → Executable file
72
web/documentserver-example/java/src/main/java/helpers/DocumentManager.java
Normal file → Executable file
@ -130,7 +130,20 @@ public class DocumentManager
|
||||
String hostAddress = CurUserHostAddress(userAddress); // get current user host address
|
||||
String serverPath = request.getSession().getServletContext().getRealPath(""); // get the server url
|
||||
String storagePath = ConfigManager.GetProperty("storage-folder"); // get the storage directory
|
||||
String directory = serverPath + storagePath + File.separator + hostAddress + File.separator;
|
||||
File f = new File(storagePath);
|
||||
|
||||
if (f.isAbsolute()) {
|
||||
if (!f.exists()) {
|
||||
if (Files.isWritable(Paths.get(storagePath.substring(0, storagePath.lastIndexOf(File.separator))))) {
|
||||
f.mkdirs();
|
||||
} else {
|
||||
throw new SecurityException("No write permission to path: " + f.toPath());
|
||||
}
|
||||
} else if (f.exists() && f.isFile()) {
|
||||
throw new SecurityException("The path to the file is specified instead of the folder");
|
||||
}
|
||||
}
|
||||
String directory = !f.isAbsolute() ? serverPath + storagePath + File.separator + hostAddress + File.separator : storagePath + File.separator;
|
||||
|
||||
File file = new File(directory);
|
||||
|
||||
@ -151,6 +164,22 @@ public class DocumentManager
|
||||
return directory + FileUtility.GetFileName(fileName);
|
||||
}
|
||||
|
||||
// get the path to history file
|
||||
public static String HistoryPath(String fileName, String userAddress, String version, String file)
|
||||
{
|
||||
String hostAddress = CurUserHostAddress(userAddress);
|
||||
String serverPath = request.getSession().getServletContext().getRealPath("");
|
||||
String storagePath = ConfigManager.GetProperty("storage-folder");
|
||||
String directory = serverPath + storagePath + File.separator + hostAddress + File.separator;
|
||||
if (new File(storagePath).isAbsolute()) {
|
||||
directory = FilesRootPath(userAddress);
|
||||
}
|
||||
|
||||
directory = directory + fileName + "-hist" + File.separator + version + File.separator + file;
|
||||
|
||||
return directory;
|
||||
}
|
||||
|
||||
// get the path to the forcesaved file version
|
||||
public static String ForcesavePath(String fileName, String userAddress, Boolean create)
|
||||
{
|
||||
@ -320,13 +349,20 @@ public class DocumentManager
|
||||
{
|
||||
String serverPath = GetServerUrl(forDocumentServer);
|
||||
String storagePath = ConfigManager.GetProperty("storage-folder");
|
||||
File f = new File(storagePath);
|
||||
String hostAddress = CurUserHostAddress(null);
|
||||
|
||||
String filePath = serverPath + "/" + storagePath + "/" + hostAddress + "/" + URLEncoder.encode(fileName, java.nio.charset.StandardCharsets.UTF_8.toString()).replace("+", "%20");
|
||||
if (f.isAbsolute() && f.isFile()) {
|
||||
filePath = GetDownloadUrl(fileName);
|
||||
if (!Files.isWritable(f.toPath())) {
|
||||
throw new SecurityException("No write permission to path: " + f.toPath());
|
||||
}
|
||||
}
|
||||
|
||||
return filePath;
|
||||
}
|
||||
catch (UnsupportedEncodingException e)
|
||||
catch (Exception e)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
@ -429,6 +465,23 @@ public class DocumentManager
|
||||
}
|
||||
}
|
||||
|
||||
// get url to download a file to History prev.*
|
||||
public static String GetDownloadHistoryUrl(String fileName, Integer version, String file) {
|
||||
String serverPath = GetServerUrl(true);
|
||||
String hostAddress = CurUserHostAddress(null);
|
||||
try
|
||||
{
|
||||
String query = "?type=downloadhistory&fileName=" + URLEncoder.encode(fileName, java.nio.charset.StandardCharsets.UTF_8.toString()) + "&userAddress=" + URLEncoder.encode(hostAddress, java.nio.charset.StandardCharsets.UTF_8.toString());
|
||||
query = query + "&ver=" + version + "&file=" + URLEncoder.encode(file, java.nio.charset.StandardCharsets.UTF_8.toString());
|
||||
|
||||
return serverPath + "/IndexServlet" + query;
|
||||
}
|
||||
catch (UnsupportedEncodingException e)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
// get an editor internal extension
|
||||
public static String GetInternalExtension(FileType fileType)
|
||||
{
|
||||
@ -515,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;
|
||||
}
|
||||
}
|
||||
@ -63,7 +63,7 @@ public class FileUtility
|
||||
// spreadsheet extensions
|
||||
public static List<String> ExtsSpreadsheet = Arrays.asList
|
||||
(
|
||||
".xls", ".xlsx", ".xlsm",
|
||||
".xls", ".xlsx", ".xlsm", ".xlsb",
|
||||
".xlt", ".xltx", ".xltm",
|
||||
".ods", ".fods", ".ots", ".csv"
|
||||
);
|
||||
|
||||
19
web/documentserver-example/java/src/main/java/helpers/TrackManager.java
Normal file → Executable file
19
web/documentserver-example/java/src/main/java/helpers/TrackManager.java
Normal file → Executable file
@ -127,7 +127,10 @@ public class TrackManager {
|
||||
String newFileName = fileName;
|
||||
|
||||
String curExt = FileUtility.GetFileExtension(fileName); // get current file extension
|
||||
String downloadExt = FileUtility.GetFileExtension(downloadUri); // get the extension of the downloaded file
|
||||
String downloadExt = "." + (String) body.get("filetype"); // get the extension of the downloaded file
|
||||
|
||||
// Todo [Delete in version 7.0 or higher]
|
||||
if (downloadExt == "." + null) downloadExt = FileUtility.GetFileExtension(downloadUri); // Support for versions below 7.0
|
||||
|
||||
// convert downloaded file to the file with the current extension if these extensions aren't equal
|
||||
if (!curExt.equals(downloadExt)) {
|
||||
@ -188,7 +191,11 @@ public class TrackManager {
|
||||
String downloadUri = (String) body.get("url");
|
||||
|
||||
String curExt = FileUtility.GetFileExtension(fileName); // get current file extension
|
||||
String downloadExt = FileUtility.GetFileExtension(downloadUri); // get the extension of the downloaded file
|
||||
String downloadExt = "."+(String) body.get("filetype"); // get the extension of the downloaded file
|
||||
|
||||
// Todo [Delete in version 7.0 or higher]
|
||||
if (downloadExt == "."+null) downloadExt = FileUtility.GetFileExtension(downloadUri); // Support for versions below 7.0
|
||||
|
||||
Boolean newFileName = false;
|
||||
|
||||
// convert downloaded file to the file with the current extension if these extensions aren't equal
|
||||
@ -270,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);
|
||||
@ -280,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
|
||||
{
|
||||
@ -307,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");
|
||||
|
||||
@ -31,6 +31,7 @@ public class Users {
|
||||
add("Can perform all actions with comments");
|
||||
add("The file favorite state is undefined");
|
||||
add("Can create files from templates using data from the editor");
|
||||
add("Can see the information about all users");
|
||||
}};
|
||||
|
||||
static List<String> descr_user_2 = new ArrayList<String>() {{
|
||||
@ -39,17 +40,19 @@ public class Users {
|
||||
add("Can view comments, edit his own comments and comments left by users with no group. Can remove his own comments only");
|
||||
add("This file is marked as favorite");
|
||||
add("Can create new files from the editor");
|
||||
add("Can see the information about users from Group2 and users who don’t belong to any group");
|
||||
}};
|
||||
|
||||
static List<String> descr_user_3 = new ArrayList<String>() {{
|
||||
add("Belongs to Group3");
|
||||
add("Can review changes made by Group2 users");
|
||||
add("Can view comments left by Group2 and Group3 users. Can edit comments left by Group2 users");
|
||||
add("Can view comments left by Group2 and Group3 users. Can edit comments left by the Group2 users");
|
||||
add("This file isn’t marked as favorite");
|
||||
add("Can’t copy data from the file to clipboard");
|
||||
add("Can’t download the file");
|
||||
add("Can’t print the file");
|
||||
add("Can create new files from the editor");
|
||||
add("Can see the information about Group2 users");
|
||||
}};
|
||||
|
||||
static List<String> descr_user_0 = new ArrayList<String>() {{
|
||||
@ -60,20 +63,22 @@ public class Users {
|
||||
add("The file favorite state is undefined");
|
||||
add("Can't mention others in comments");
|
||||
add("Can't create new files from the editor");
|
||||
add("Can’t see anyone’s information");
|
||||
add("Can't rename files from the editor");
|
||||
}};
|
||||
|
||||
private static List<User> users = new ArrayList<User>() {{
|
||||
add(new User("uid-1", "John Smith", "smith@example.com",
|
||||
null, null, new CommentGroups(),
|
||||
"", null, new CommentGroups(), null,
|
||||
null, new ArrayList<String>(), descr_user_1, true));
|
||||
add(new User("uid-2", "Mark Pottato", "pottato@example.com",
|
||||
"group-2", Arrays.asList("group-2", ""), new CommentGroups(null, Arrays.asList("group-2", ""), Arrays.asList("group-2")),
|
||||
"group-2", Arrays.asList("group-2", ""), new CommentGroups(null, Arrays.asList("group-2", ""), Arrays.asList("group-2")), Arrays.asList("group-2", ""),
|
||||
true, new ArrayList<String>(), descr_user_2, false));
|
||||
add(new User("uid-3", "Hamish Mitchell", "mitchell@example.com",
|
||||
"group-3", Arrays.asList("group-2"), new CommentGroups(Arrays.asList("group-3", "group-2"), Arrays.asList("group-2"), new ArrayList<String>()),
|
||||
"group-3", Arrays.asList("group-2"), new CommentGroups(Arrays.asList("group-3", "group-2"), Arrays.asList("group-2"), new ArrayList<String>()), Arrays.asList("group-2"),
|
||||
false, Arrays.asList("copy", "download", "print"), descr_user_3, false));
|
||||
add(new User("uid-0", null, null,
|
||||
null, null, new CommentGroups(),
|
||||
"", null, new CommentGroups(), new ArrayList<String>(),
|
||||
null, new ArrayList<String>(), descr_user_0, false));
|
||||
}};
|
||||
|
||||
|
||||
Submodule web/documentserver-example/java/src/main/resources/assets updated: 589266f57f...1d601d84c4
@ -1,4 +1,4 @@
|
||||
version=1.0.0
|
||||
version=1.2.0
|
||||
|
||||
filesize-max=5242880
|
||||
storage-folder=app_data
|
||||
@ -6,7 +6,7 @@ storage-folder=app_data
|
||||
files.docservice.fill-docs=.oform|.docx
|
||||
files.docservice.viewed-docs=.pdf|.djvu|.xps|.oxps
|
||||
files.docservice.edited-docs=.docx|.xlsx|.csv|.pptx|.txt|.docxf
|
||||
files.docservice.convert-docs=.docm|.dotx|.dotm|.dot|.doc|.odt|.fodt|.ott|.xlsm|.xltx|.xltm|.xlt|.xls|.ods|.fods|.ots|.pptm|.ppt|.ppsx|.ppsm|.pps|.potx|.potm|.pot|.odp|.fodp|.otp|.rtf|.mht|.html|.htm|.xml|.epub|.fb2
|
||||
files.docservice.convert-docs=.docm|.dotx|.dotm|.dot|.doc|.odt|.fodt|.ott|.xlsm|.xlsb|.xltx|.xltm|.xlt|.xls|.ods|.fods|.ots|.pptm|.ppt|.ppsx|.ppsm|.pps|.potx|.potm|.pot|.odp|.fodp|.otp|.rtf|.mht|.html|.htm|.xml|.epub|.fb2
|
||||
files.docservice.timeout=120000
|
||||
|
||||
files.docservice.url.site=http://documentserver/
|
||||
@ -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
|
||||
@ -86,10 +86,6 @@
|
||||
}
|
||||
|
||||
@media (max-width: 1008px) {
|
||||
#portal-info {
|
||||
width: 65vw;
|
||||
}
|
||||
|
||||
.left-panel {
|
||||
margin-left: 0;
|
||||
}
|
||||
@ -127,6 +123,10 @@
|
||||
height: 80px;
|
||||
}
|
||||
|
||||
.main {
|
||||
height: calc(100% - 128px);
|
||||
}
|
||||
|
||||
.main-panel {
|
||||
left: 0;
|
||||
padding: 48px 18px 24px;
|
||||
@ -299,6 +299,9 @@
|
||||
.tableRow td:first-child {
|
||||
max-width: 17%;
|
||||
}
|
||||
#portal-info {
|
||||
max-width: 60vw;
|
||||
}
|
||||
}
|
||||
|
||||
.downloadContentCellShift:after {
|
||||
@ -353,6 +356,10 @@
|
||||
height: 80px;
|
||||
}
|
||||
|
||||
.main {
|
||||
height: calc(100% - 128px);
|
||||
}
|
||||
|
||||
.copy {
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
@ -422,6 +429,58 @@
|
||||
display: none;
|
||||
width: 1%;
|
||||
}
|
||||
/* Mobile Upload*/
|
||||
.blockUI.blockMsg.blockPage.ui-dialog.ui-widget.ui-corner-all.ui-widget-content.ui-draggable {
|
||||
width: 344px !important;
|
||||
box-shadow: 0px 7px 15px rgba(85, 85, 85, 0.1);
|
||||
border-radius: 2px;
|
||||
top: 10% !important;
|
||||
margin-left: -172px !important;
|
||||
}
|
||||
|
||||
.ui-dialog .ui-dialog-titlebar {
|
||||
padding: 0;
|
||||
}
|
||||
.ui-dialog .ui-dialog-content {
|
||||
padding: 0 !important;
|
||||
}
|
||||
#mainProgress {
|
||||
margin: 24px 16px 0 !important;
|
||||
}
|
||||
.blockTitle {
|
||||
padding: 10px 10px 6px 16px !important;
|
||||
font-size: 14px !important;
|
||||
}
|
||||
#mainProgress .describeUpload {
|
||||
padding: 8px 0 !important;
|
||||
}
|
||||
.dialog-close {
|
||||
margin: 0 !important;
|
||||
}
|
||||
.step-descr{
|
||||
line-height: 150%;
|
||||
}
|
||||
.step {
|
||||
line-height: 160%;
|
||||
}
|
||||
.buttonsMobile{
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
.button.gray{
|
||||
margin: 0;
|
||||
}
|
||||
.button, .button:hover{
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
padding: 0 !important;
|
||||
width: 144px;
|
||||
height: 56px;
|
||||
margin-bottom: 24px !important;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 560px) and (min-width: 510px) {
|
||||
|
||||
@ -22,6 +22,7 @@ html {
|
||||
}
|
||||
|
||||
body {
|
||||
display: block;
|
||||
background: #FFFFFF;
|
||||
color: #333333;
|
||||
font-family: Open Sans;
|
||||
@ -71,6 +72,7 @@ header img {
|
||||
}
|
||||
|
||||
.main{
|
||||
display: table;
|
||||
height: calc(100% - 112px);
|
||||
min-height: 536px;
|
||||
}
|
||||
@ -97,6 +99,10 @@ header img {
|
||||
width: 896px;
|
||||
}
|
||||
|
||||
#portal-info {
|
||||
max-width: 65vw;
|
||||
}
|
||||
|
||||
.portal-name {
|
||||
color: #FF6F3D;
|
||||
font-size: 24px;
|
||||
@ -735,12 +741,9 @@ html {
|
||||
width: 30vw;
|
||||
min-width: 200px;
|
||||
max-width: 400px;
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.user-descr > b {
|
||||
margin-left: 25px;
|
||||
}
|
||||
|
||||
.portal-descr:nth-child(3) {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
@ -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,43 +183,50 @@
|
||||
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;
|
||||
};
|
||||
|
||||
var сonnectEditor = function () {
|
||||
if ((config.document.fileType === "docxf" || config.document.fileType === "oform")
|
||||
&& DocsAPI.DocEditor.version().split(".")[0] < 7) {
|
||||
innerAlert("Please update ONLYOFFICE Docs to version 7.0 to work on fillable forms online.");
|
||||
return;
|
||||
}
|
||||
|
||||
docEditor = new DocsAPI.DocEditor("iframeEditor", config);
|
||||
};
|
||||
|
||||
|
||||
65
web/documentserver-example/java/src/main/webapp/index.jsp
Normal file → Executable file
65
web/documentserver-example/java/src/main/webapp/index.jsp
Normal file → Executable 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"%>
|
||||
|
||||
@ -13,6 +15,7 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||
<meta name="viewport" content="width=device-width" />
|
||||
<!--
|
||||
*
|
||||
* (c) Copyright Ascensio System SIA 2021
|
||||
@ -65,7 +68,7 @@
|
||||
<a class="try-editor slide" data-type="pptx">Presentation</a>
|
||||
</li>
|
||||
<li>
|
||||
<a class="try-editor form" data-type="docxf">Master form</a>
|
||||
<a class="try-editor form" data-type="docxf">Form template</a>
|
||||
</li>
|
||||
</ul>
|
||||
<label class="create-sample">
|
||||
@ -96,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>
|
||||
@ -139,12 +115,13 @@
|
||||
<% DocumentManager.Init(request, response); %>
|
||||
<% File[] files = DocumentManager.GetStoredFiles(null); %>
|
||||
<div class="main-panel">
|
||||
<div id="portal-info" style="display: <%= files.length > 0 ? "none" : "block" %>">
|
||||
<div id="portal-info" style="display: <%= files.length > 0 ? "none" : "table-cell" %>">
|
||||
<span class="portal-name">ONLYOFFICE Document Editors – Welcome!</span>
|
||||
<span class="portal-descr">
|
||||
Get started with a demo-sample of ONLYOFFICE Document Editors, the first html5-based editors.
|
||||
<br /> You may upload your own documents for testing using the "<b>Upload file</b>" button and <b>selecting</b> the necessary files on your PC.
|
||||
</span>
|
||||
<span class="portal-descr">Please do NOT use this integration example on your own server without proper code modifications, it is intended for testing purposes only. In case you enabled this test example, disable it before going for production.</span>
|
||||
<span class="portal-descr">You can open the same document using different users in different Web browser sessions, so you can check out multi-user editing functions.</span>
|
||||
<% for (User user : Users.getAllUsers()) { %>
|
||||
<div class="user-descr">
|
||||
@ -180,7 +157,7 @@
|
||||
Boolean canEdit = DocumentManager.GetEditedExts().contains(FileUtility.GetFileExtension(files[i].getName()));
|
||||
String version=" ["+DocumentManager.GetFileVersion(DocumentManager.HistoryDir(DocumentManager.StoragePath(files[i].getName(), null)))+"]";
|
||||
%>
|
||||
<tr class="tableRow" title="<%= files[i].getName() %> [<%= version %>]">
|
||||
<tr class="tableRow" title="<%= files[i].getName() %><%= version %>">
|
||||
<td class="contentCells">
|
||||
<a class="stored-edit <%= docType %>" href="EditorServlet?fileName=<%= URLEncoder.encode(files[i].getName(), "UTF-8") %>" target="_blank">
|
||||
<span><%= files[i].getName() %></span>
|
||||
@ -215,9 +192,6 @@
|
||||
</a>
|
||||
</td>
|
||||
<% } %>
|
||||
<% if (!docType.equals("cell") && !docType.equals("word")) { %>
|
||||
<td class="contentCells contentCells-icon contentCellsEmpty"></td>
|
||||
<% } %>
|
||||
<% if (docType.equals("word")) { %>
|
||||
<td class="contentCells contentCells-icon">
|
||||
<a href="EditorServlet?fileName=<%= URLEncoder.encode(files[i].getName(), "UTF-8") %>&type=desktop&mode=blockcontent" target="_blank">
|
||||
@ -320,10 +294,8 @@
|
||||
<span class="step-descr">They are loaded only once, they will be cached on your computer.</span>
|
||||
<input type="hidden" name="hiddenFileName" id="hiddenFileName" />
|
||||
<br />
|
||||
<br />
|
||||
<span class="progress-descr">Note the speed of all operations depends on your connection quality and server location.</span>
|
||||
<br />
|
||||
<br />
|
||||
<div class="error-message">
|
||||
<b>Upload error: </b><span></span>
|
||||
<br />
|
||||
@ -332,10 +304,12 @@
|
||||
</div>
|
||||
<iframe id="embeddedView" src="" height="345px" width="432px" frameborder="0" scrolling="no" allowtransparency></iframe>
|
||||
<br />
|
||||
<div id="beginEdit" class="button orange disable">Edit</div>
|
||||
<div id="beginView" class="button gray disable">View</div>
|
||||
<div id="beginEmbedded" class="button gray disable">Embedded view</div>
|
||||
<div id="cancelEdit" class="button gray">Cancel</div>
|
||||
<div class="buttonsMobile">
|
||||
<div id="beginEdit" class="button orange disable">Edit</div>
|
||||
<div id="beginView" class="button gray disable">View</div>
|
||||
<div id="beginEmbedded" class="button gray disable">Embedded view</div>
|
||||
<div id="cancelEdit" class="button gray">Cancel</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<span id="loadScripts" data-docs="<%= ConfigManager.GetProperty("files.docservice.url.site") + ConfigManager.GetProperty("files.docservice.url.preloader") %>"></span>
|
||||
@ -374,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>
|
||||
|
||||
@ -66,7 +66,7 @@ function key(k) {
|
||||
|
||||
var getDocumentType = function (ext) {
|
||||
if (".doc.docx.docm.dot.dotx.dotm.odt.fodt.ott.rtf.txt.html.htm.mht.xml.pdf.djvu.fb2.epub.xps.oxps".indexOf(ext) != -1) return "text";
|
||||
if (".xls.xlsx.xlsm.xlt.xltx.xltm.ods.fods.ots.csv".indexOf(ext) != -1) return "spreadsheet";
|
||||
if (".xls.xlsx.xlsm.xlsb.xlt.xltx.xltm.ods.fods.ots.csv".indexOf(ext) != -1) return "spreadsheet";
|
||||
if (".pps.ppsx.ppsm.ppt.pptx.pptm.pot.potx.potm.odp.fodp.otp".indexOf(ext) != -1) return "presentation";
|
||||
return null;
|
||||
};
|
||||
@ -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
|
||||
@ -2,13 +2,13 @@
|
||||
|
||||
This example will help you integrate ONLYOFFICE Docs into your web application on Node.js.
|
||||
|
||||
It is aimed at testing the editors. Please, do not use it for production without proper modifications.
|
||||
**Please note**: It is intended for testing purposes and demonstrating functionality of the editors. Do NOT use this integration example on your own server without proper code modifications! In case you enabled the test example, disable it before going for production.
|
||||
|
||||
## For Windows
|
||||
|
||||
### Step 1. Install ONLYOFFICE Docs
|
||||
|
||||
Download and install ONLYOFFICE Docs (packaged as Document Server).
|
||||
Download and install ONLYOFFICE Docs (packaged as Document Server).
|
||||
|
||||
See the detailed guide to learn how to [install Document Server for Windows](https://helpcenter.onlyoffice.com/installation/docs-developer-install-windows.aspx).
|
||||
|
||||
@ -16,13 +16,15 @@ See the detailed guide to learn how to [install Document Server for Windows](htt
|
||||
|
||||
Download the [Node.js example](https://api.onlyoffice.com/editors/demopreview) from our site.
|
||||
|
||||
You need to connect the editors to your website. Specify the path to the editors installation in the *config/default.json* file:
|
||||
To connect the editors to your website, specify the path to the editors installation and the path to the storage folder in the *config/default.json* file:
|
||||
|
||||
```
|
||||
"storageFolder": "./files"
|
||||
"storagePath": "/files"
|
||||
"siteUrl": "https://documentserver/"
|
||||
```
|
||||
|
||||
where the **documentserver** is the name of the server with the ONLYOFFICE Document Server installed.
|
||||
where the **documentserver** is the name of the server with the ONLYOFFICE Document Server installed, the **storageFolder** and **storagePath** are the paths where files will be created and stored. You can set an absolute path. For example, *D:\\\\folder*. Please note that on Windows OS the double backslash must be used as a separator.
|
||||
|
||||
If you want to experiment with the editor configuration, modify the [parameters](https://api.onlyoffice.com/editors/advanced) in the *\views\editor.ejs* file.
|
||||
|
||||
@ -114,13 +116,18 @@ See the detailed guide to learn how to [install Document Server for Linux](https
|
||||
nano config/default.json
|
||||
```
|
||||
|
||||
Edit the following line:
|
||||
Edit the following lines:
|
||||
|
||||
```
|
||||
"storageFolder": "./files"
|
||||
"storagePath": "/files"
|
||||
"siteUrl": "https://documentserver/"
|
||||
```
|
||||
|
||||
where the **documentserver** is the name of the server with the ONLYOFFICE Document Server installed.
|
||||
where the **documentserver** is the name of the server with the ONLYOFFICE Document Server installed, the **storageFolder** and **storagePath** are the paths where files will be created and stored. Please note that you must have read and write permissions to the folder. If you do not have them, please use the next command:
|
||||
```
|
||||
sudo chmod -R ugo+rw /{path}
|
||||
```
|
||||
|
||||
6. Run the project with Node.js:
|
||||
|
||||
@ -139,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.
|
||||
303
web/documentserver-example/nodejs/app.js
Normal file → Executable file
303
web/documentserver-example/nodejs/app.js
Normal file → Executable 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
|
||||
|
||||
@ -97,17 +100,18 @@ app.use(bodyParser.urlencoded({ extended: false })); // connect middleware that
|
||||
app.get("/", function (req, res) { // define a handler for default page
|
||||
try {
|
||||
|
||||
docManager.init(storageFolder, req, res);
|
||||
req.docManager = new docManager(req, res);
|
||||
|
||||
res.render("index", { // render index template with the parameters specified
|
||||
preloaderUrl: siteUrl + configServer.get('preloaderUrl'),
|
||||
convertExts: configServer.get('convertedDocs').join(","),
|
||||
editedExts: configServer.get('editedDocs').join(","),
|
||||
fillExts: configServer.get("fillDocs").join(","),
|
||||
storedFiles: docManager.getStoredFiles(),
|
||||
params: docManager.getCustomParams(),
|
||||
convertExts: configServer.get('convertedDocs'),
|
||||
editedExts: configServer.get('editedDocs'),
|
||||
fillExts: configServer.get("fillDocs"),
|
||||
storedFiles: req.docManager.getStoredFiles(),
|
||||
params: req.docManager.getCustomParams(),
|
||||
users: users,
|
||||
serverUrl: docManager.getServerUrl(),
|
||||
serverUrl: req.docManager.getServerUrl(),
|
||||
languages: configServer.get('languages'),
|
||||
});
|
||||
|
||||
}
|
||||
@ -120,12 +124,13 @@ app.get("/", function (req, res) { // define a handler for default page
|
||||
});
|
||||
|
||||
app.get("/download", function(req, res) { // define a handler for downloading files
|
||||
docManager.init(storageFolder, req, res);
|
||||
req.docManager = new docManager(req, res);
|
||||
|
||||
var fileName = fileUtility.getFileName(req.query.fileName);
|
||||
var userAddress = req.query.useraddress;
|
||||
var isEmbedded = req.query.dmode;
|
||||
|
||||
if (cfgSignatureEnable && cfgSignatureUseForRequest) {
|
||||
if ((cfgSignatureEnable && cfgSignatureUseForRequest) && isEmbedded == null ) {
|
||||
var authorization = req.get(cfgSignatureAuthorizationHeader);
|
||||
if (authorization && authorization.startsWith(cfgSignatureAuthorizationHeaderPrefix)) {
|
||||
var token = authorization.substring(cfgSignatureAuthorizationHeaderPrefix.length);
|
||||
@ -139,9 +144,9 @@ app.get("/download", function(req, res) { // define a handler for downloading f
|
||||
}
|
||||
}
|
||||
|
||||
var path = docManager.forcesavePath(fileName, userAddress, false); // get the path to the force saved document version
|
||||
var path = req.docManager.forcesavePath(fileName, userAddress, false); // get the path to the force saved document version
|
||||
if (path == "") {
|
||||
path = docManager.storagePath(fileName, userAddress); // or to the original document
|
||||
path = req.docManager.storagePath(fileName, userAddress); // or to the original document
|
||||
}
|
||||
|
||||
res.setHeader("Content-Length", fileSystem.statSync(path).size); // add headers to the response to specify the page parameters
|
||||
@ -153,15 +158,56 @@ app.get("/download", function(req, res) { // define a handler for downloading f
|
||||
filestream.pipe(res); // send file information to the response by streams
|
||||
});
|
||||
|
||||
app.get("/history", function (req, res) {
|
||||
req.docManager = new docManager(req, res);
|
||||
if (cfgSignatureEnable && cfgSignatureUseForRequest) {
|
||||
var authorization = req.get(cfgSignatureAuthorizationHeader);
|
||||
if (authorization && authorization.startsWith(cfgSignatureAuthorizationHeaderPrefix)) {
|
||||
var token = authorization.substring(cfgSignatureAuthorizationHeaderPrefix.length);
|
||||
try {
|
||||
var decoded = jwt.verify(token, cfgSignatureSecret);
|
||||
} catch (err) {
|
||||
console.log('checkJwtHeader error: name = ' + err.name + ' message = ' + err.message + ' token = ' + token);
|
||||
res.sendStatus(403);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
res.sendStatus(403);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
var fileName = req.query.fileName;
|
||||
var userAddress = req.query.useraddress;
|
||||
var ver = req.query.ver;
|
||||
var file = req.query.file;
|
||||
|
||||
if (file.includes("diff")) {
|
||||
var Path = req.docManager.diffPath(fileName, userAddress, ver);
|
||||
} else if (file.includes("prev")) {
|
||||
var Path = req.docManager.prevFilePath(fileName, userAddress, ver);
|
||||
} else {
|
||||
res.sendStatus(403);
|
||||
return;
|
||||
}
|
||||
|
||||
res.setHeader("Content-Length", fileSystem.statSync(Path).size); // add headers to the response to specify the page parameters
|
||||
res.setHeader("Content-Type", mime.getType(Path));
|
||||
res.setHeader("Content-Disposition", "attachment; filename*=UTF-8\'\'" + encodeURIComponent(file));
|
||||
|
||||
var filestream = fileSystem.createReadStream(Path);
|
||||
filestream.pipe(res); // send file information to the response by streams
|
||||
})
|
||||
|
||||
app.post("/upload", function (req, res) { // define a handler for uploading files
|
||||
|
||||
docManager.init(storageFolder, req, res);
|
||||
docManager.storagePath(""); // mkdir if not exist
|
||||
req.docManager = new docManager(req, res);
|
||||
req.docManager.storagePath(""); // mkdir if not exist
|
||||
|
||||
const userIp = docManager.curUserHostAddress(); // get the path to the user host
|
||||
const uploadDir = path.join(storageFolder, userIp);
|
||||
const userIp = req.docManager.curUserHostAddress(); // get the path to the user host
|
||||
const uploadDir = req.docManager.storageRootPath(userIp);
|
||||
const uploadDirTmp = path.join(uploadDir, 'tmp'); // and create directory for temporary files if it doesn't exist
|
||||
docManager.createDirectory(uploadDirTmp);
|
||||
req.docManager.createDirectory(uploadDirTmp);
|
||||
|
||||
const form = new formidable.IncomingForm(); // create a new incoming form
|
||||
form.uploadDir = uploadDirTmp; // and write there all the necessary parameters
|
||||
@ -170,7 +216,7 @@ app.post("/upload", function (req, res) { // define a handler for uploading fil
|
||||
|
||||
form.parse(req, function (err, fields, files) { // parse this form
|
||||
if (err) { // if an error occurs
|
||||
docManager.cleanFolderRecursive(uploadDirTmp, true); // clean the folder with temporary files
|
||||
//docManager.cleanFolderRecursive(uploadDirTmp, true); // clean the folder with temporary files
|
||||
res.writeHead(200, { "Content-Type": "text/plain" }); // and write the error status and message to the response
|
||||
res.write("{ \"error\": \"" + err.message + "\"}");
|
||||
res.end();
|
||||
@ -186,10 +232,10 @@ app.post("/upload", function (req, res) { // define a handler for uploading fil
|
||||
return;
|
||||
}
|
||||
|
||||
file.name = docManager.getCorrectName(file.name);
|
||||
file.name = req.docManager.getCorrectName(file.name);
|
||||
|
||||
if (configServer.get('maxFileSize') < file.size || file.size <= 0) { // check if the file size exceeds the maximum file size
|
||||
docManager.cleanFolderRecursive(uploadDirTmp, true); // clean the folder with temporary files
|
||||
//docManager.cleanFolderRecursive(uploadDirTmp, true); // clean the folder with temporary files
|
||||
res.writeHead(200, { "Content-Type": "text/plain" });
|
||||
res.write("{ \"error\": \"File size is incorrect\"}");
|
||||
res.end();
|
||||
@ -201,7 +247,7 @@ app.post("/upload", function (req, res) { // define a handler for uploading fil
|
||||
const documentType = fileUtility.getFileType(file.name);
|
||||
|
||||
if (exts.indexOf(curExt) == -1) { // check if the file extension is supported
|
||||
docManager.cleanFolderRecursive(uploadDirTmp, true); // if not, clean the folder with temporary files
|
||||
//docManager.cleanFolderRecursive(uploadDirTmp, true); // if not, clean the folder with temporary files
|
||||
res.writeHead(200, { "Content-Type": "text/plain" }); // and write the error status and message to the response
|
||||
res.write("{ \"error\": \"File type is not supported\"}");
|
||||
res.end();
|
||||
@ -209,7 +255,7 @@ app.post("/upload", function (req, res) { // define a handler for uploading fil
|
||||
}
|
||||
|
||||
fileSystem.rename(file.path, uploadDir + "/" + file.name, function (err) { // rename a file
|
||||
docManager.cleanFolderRecursive(uploadDirTmp, true); // clean the folder with temporary files
|
||||
//docManager.cleanFolderRecursive(uploadDirTmp, true); // clean the folder with temporary files
|
||||
res.writeHead(200, { "Content-Type": "text/plain" });
|
||||
if (err) { // if an error occurs
|
||||
res.write("{ \"error\": \"" + err + "\"}"); // write an error message to the response
|
||||
@ -218,7 +264,7 @@ app.post("/upload", function (req, res) { // define a handler for uploading fil
|
||||
|
||||
var user = users.getUser(req.query.userid); // get user id and name parameters or set them to the default values
|
||||
|
||||
docManager.saveFileData(file.name, user.id, user.name);
|
||||
req.docManager.saveFileData(file.name, user.id, user.name);
|
||||
}
|
||||
res.end();
|
||||
});
|
||||
@ -230,12 +276,12 @@ app.post("/create", function (req, res) {
|
||||
var fileUrl = req.body.url;
|
||||
|
||||
try {
|
||||
docManager.init(storageFolder, req, res);
|
||||
docManager.storagePath(""); // mkdir if not exist
|
||||
req.docManager = new docManager(req, res);
|
||||
req.docManager.storagePath(""); // mkdir if not exist
|
||||
|
||||
var fileName = docManager.getCorrectName(title);
|
||||
var userAddress = docManager.curUserHostAddress();
|
||||
docManager.historyPath(fileName, userAddress, true);
|
||||
var fileName = req.docManager.getCorrectName(title);
|
||||
var userAddress = req.docManager.curUserHostAddress();
|
||||
req.docManager.historyPath(fileName, userAddress, true);
|
||||
|
||||
urllib.request(fileUrl, {method: "GET"},function(err, data) {
|
||||
if (configServer.get("maxFileSize") < data.length || data.length <= 0) { // check if the file size exceeds the maximum file size
|
||||
@ -255,7 +301,7 @@ app.post("/create", function (req, res) {
|
||||
return;
|
||||
}
|
||||
|
||||
fileSystem.writeFileSync(docManager.storagePath(fileName), data);
|
||||
fileSystem.writeFileSync(req.docManager.storagePath(fileName), data);
|
||||
|
||||
res.writeHead(200, { "Content-Type": "application/json" });
|
||||
res.write(JSON.stringify({ "file" : fileName }));
|
||||
@ -274,14 +320,15 @@ app.post("/create", function (req, res) {
|
||||
});
|
||||
|
||||
app.post("/convert", function (req, res) { // define a handler for converting files
|
||||
req.docManager = new docManager(req, res);
|
||||
|
||||
var fileName = fileUtility.getFileName(req.body.filename);
|
||||
var filePass = req.body.filePass ? req.body.filePass : null;
|
||||
var lang = req.body.lang ? req.body.lang : null;
|
||||
var fileUri = docManager.getFileUri(fileName);
|
||||
var fileUri = req.docManager.getFileUri(fileName);
|
||||
var fileExt = fileUtility.getFileExtension(fileName);
|
||||
var fileType = fileUtility.getFileType(fileName);
|
||||
var internalFileExt = docManager.getInternalExtension(fileType);
|
||||
var internalFileExt = req.docManager.getInternalExtension(fileType);
|
||||
var response = res;
|
||||
|
||||
var writeResult = function (filename, step, error) {
|
||||
@ -322,17 +369,17 @@ app.post("/convert", function (req, res) { // define a handler for converting f
|
||||
return;
|
||||
}
|
||||
|
||||
var correctName = docManager.getCorrectName(fileUtility.getFileName(fileName, true) + internalFileExt); // get the file name with a new extension
|
||||
var correctName = req.docManager.getCorrectName(fileUtility.getFileName(fileName, true) + internalFileExt); // get the file name with a new extension
|
||||
|
||||
urllib.request(newFileUri, {method: "GET"},function(err, data) {
|
||||
fileSystem.writeFileSync(docManager.storagePath(correctName), data); // write a file with a new extension, but with the content from the origin file
|
||||
fileSystem.writeFileSync(req.docManager.storagePath(correctName), data); // write a file with a new extension, but with the content from the origin file
|
||||
});
|
||||
|
||||
fileSystem.unlinkSync(docManager.storagePath(fileName)); // remove file with the origin extension
|
||||
fileSystem.unlinkSync(req.docManager.storagePath(fileName)); // remove file with the origin extension
|
||||
|
||||
var userAddress = docManager.curUserHostAddress();
|
||||
var historyPath = docManager.historyPath(fileName, userAddress, true);
|
||||
var correctHistoryPath = docManager.historyPath(correctName, userAddress, true); // get the history path to the file with a new extension
|
||||
var userAddress = req.docManager.curUserHostAddress();
|
||||
var historyPath = req.docManager.historyPath(fileName, userAddress, true);
|
||||
var correctHistoryPath = req.docManager.historyPath(correctName, userAddress, true); // get the history path to the file with a new extension
|
||||
|
||||
fileSystem.renameSync(historyPath, correctHistoryPath); // change the previous history path
|
||||
|
||||
@ -347,7 +394,7 @@ app.post("/convert", function (req, res) { // define a handler for converting f
|
||||
|
||||
try {
|
||||
if (configServer.get('convertedDocs').indexOf(fileExt) != -1) { // check if the file with such an extension can be converted
|
||||
let storagePath = docManager.storagePath(fileName);
|
||||
let storagePath = req.docManager.storagePath(fileName);
|
||||
const stat = fileSystem.statSync(storagePath);
|
||||
let key = fileUri + stat.mtime.getTime();
|
||||
|
||||
@ -364,8 +411,8 @@ app.post("/convert", function (req, res) { // define a handler for converting f
|
||||
|
||||
app.get("/files", function(req, res) { // define a handler for getting files information
|
||||
try {
|
||||
docManager.init(storageFolder, req, res);
|
||||
const filesInDirectoryInfo = docManager.getFilesInfo(); // get the information about the files from the storage path
|
||||
req.docManager = new docManager(req, res);
|
||||
const filesInDirectoryInfo = req.docManager.getFilesInfo(); // get the information about the files from the storage path
|
||||
res.setHeader("Content-Type", "application/json");
|
||||
res.write(JSON.stringify(filesInDirectoryInfo)); // transform files information into the json string
|
||||
} catch (ex) {
|
||||
@ -377,9 +424,9 @@ app.get("/files", function(req, res) { // define a handler for getting files in
|
||||
|
||||
app.get("/files/file/:fileId", function(req, res) { // define a handler for getting file information by its id
|
||||
try {
|
||||
docManager.init(storageFolder, req, res);
|
||||
req.docManager = new docManager(req, res);
|
||||
const fileId = req.params.fileId;
|
||||
const fileInfoById = docManager.getFilesInfo(fileId); // get the information about the file specified by a file id
|
||||
const fileInfoById = req.docManager.getFilesInfo(fileId); // get the information about the file specified by a file id
|
||||
res.setHeader("Content-Type", "application/json");
|
||||
res.write(JSON.stringify(fileInfoById));
|
||||
} catch (ex) {
|
||||
@ -391,19 +438,14 @@ app.get("/files/file/:fileId", function(req, res) { // define a handler for get
|
||||
|
||||
app.delete("/file", function (req, res) { // define a handler for removing file
|
||||
try {
|
||||
docManager.init(storageFolder, req, res);
|
||||
req.docManager = new docManager(req, res);
|
||||
let fileName = req.query.filename;
|
||||
if (fileName) { // if the file name is defined
|
||||
fileName = fileUtility.getFileName(fileName); // get its part without an extension
|
||||
|
||||
const filePath = docManager.storagePath(fileName); // get the path to this file
|
||||
fileSystem.unlinkSync(filePath); // and delete it
|
||||
|
||||
const userAddress = docManager.curUserHostAddress();
|
||||
const historyPath = docManager.historyPath(fileName, userAddress, true);
|
||||
docManager.cleanFolderRecursive(historyPath, true); // clean all the files from the history folder
|
||||
req.docManager.fileRemove(fileName); // delete file and his history
|
||||
} else {
|
||||
docManager.cleanFolderRecursive(docManager.storagePath(''), false); // if the file name is undefined, clean the storage folder
|
||||
req.docManager.cleanFolderRecursive(req.docManager.storagePath(''), false); // if the file name is undefined, clean the storage folder
|
||||
}
|
||||
|
||||
res.write("{\"success\":true}");
|
||||
@ -429,7 +471,7 @@ app.get("/csv", function (req, res) { // define a handler for downloading csv f
|
||||
|
||||
app.post("/track", function (req, res) { // define a handler for tracking file changes
|
||||
|
||||
docManager.init(storageFolder, req, res);
|
||||
req.docManager = new docManager(req, res);
|
||||
|
||||
var userAddress = req.query.useraddress;
|
||||
var fileName = fileUtility.getFileName(req.query.filename);
|
||||
@ -441,22 +483,22 @@ app.post("/track", function (req, res) { // define a handler for tracking file
|
||||
// callback file saving process
|
||||
var callbackProcessSave = function (downloadUri, body, fileName, userAddress, newFileName) {
|
||||
try {
|
||||
var storagePath = docManager.storagePath(newFileName, userAddress);
|
||||
var storagePath = req.docManager.storagePath(newFileName, userAddress);
|
||||
|
||||
var historyPath = docManager.historyPath(newFileName, userAddress); // get the path to the history data
|
||||
var historyPath = req.docManager.historyPath(newFileName, userAddress); // get the path to the history data
|
||||
if (historyPath == "") { // if the history path doesn't exist
|
||||
historyPath = docManager.historyPath(newFileName, userAddress, true); // create it
|
||||
docManager.createDirectory(historyPath); // and create a directory for the history data
|
||||
historyPath = req.docManager.historyPath(newFileName, userAddress, true); // create it
|
||||
req.docManager.createDirectory(historyPath); // and create a directory for the history data
|
||||
}
|
||||
|
||||
var count_version = docManager.countVersion(historyPath); // get the next file version number
|
||||
var count_version = req.docManager.countVersion(historyPath); // get the next file version number
|
||||
version = count_version + 1;
|
||||
var versionPath = docManager.versionPath(newFileName, userAddress, version); // get the path to the specified file version
|
||||
docManager.createDirectory(versionPath); // create a directory to the specified file version
|
||||
var versionPath = req.docManager.versionPath(newFileName, userAddress, version); // get the path to the specified file version
|
||||
req.docManager.createDirectory(versionPath); // create a directory to the specified file version
|
||||
|
||||
var downloadZip = body.changesurl;
|
||||
if (downloadZip) {
|
||||
var path_changes = docManager.diffPath(newFileName, userAddress, version); // get the path to the file with document versions differences
|
||||
var path_changes = req.docManager.diffPath(newFileName, userAddress, version); // get the path to the file with document versions differences
|
||||
urllib.request(downloadZip, {method: "GET"},function(err, data) {
|
||||
fileSystem.writeFileSync(path_changes, data); // write the document version differences to the archive
|
||||
});
|
||||
@ -464,21 +506,21 @@ app.post("/track", function (req, res) { // define a handler for tracking file
|
||||
|
||||
var changeshistory = body.changeshistory || JSON.stringify(body.history);
|
||||
if (changeshistory) {
|
||||
var path_changes_json = docManager.changesPath(newFileName, userAddress, version); // get the path to the file with document changes
|
||||
var path_changes_json = req.docManager.changesPath(newFileName, userAddress, version); // get the path to the file with document changes
|
||||
fileSystem.writeFileSync(path_changes_json, changeshistory); // and write this data to the path in json format
|
||||
}
|
||||
|
||||
var path_key = docManager.keyPath(newFileName, userAddress, version); // get the path to the key.txt file
|
||||
var path_key = req.docManager.keyPath(newFileName, userAddress, version); // get the path to the key.txt file
|
||||
fileSystem.writeFileSync(path_key, body.key); // write the key value to the key.txt file
|
||||
|
||||
var path_prev = path.join(versionPath, "prev" + fileUtility.getFileExtension(fileName)); // get the path to the previous file version
|
||||
fileSystem.renameSync(docManager.storagePath(fileName, userAddress), path_prev); // and write it to the current path
|
||||
fileSystem.renameSync(req.docManager.storagePath(fileName, userAddress), path_prev); // and write it to the current path
|
||||
|
||||
urllib.request(downloadUri, {method: "GET"},function(err, data) {
|
||||
fileSystem.writeFileSync(storagePath, data);
|
||||
});
|
||||
|
||||
var forcesavePath = docManager.forcesavePath(newFileName, userAddress, false); // get the path to the forcesaved file
|
||||
var forcesavePath = req.docManager.forcesavePath(newFileName, userAddress, false); // get the path to the forcesaved file
|
||||
if (forcesavePath != "") { // if this path is empty
|
||||
fileSystem.unlinkSync(forcesavePath); // remove it
|
||||
}
|
||||
@ -503,13 +545,17 @@ app.post("/track", function (req, res) { // define a handler for tracking file
|
||||
}
|
||||
|
||||
var curExt = fileUtility.getFileExtension(fileName); // get current file extension
|
||||
var downloadExt = fileUtility.getFileExtension(downloadUri); // get the extension of the downloaded file
|
||||
var downloadExt = "." + body.filetype; // get the extension of the downloaded file
|
||||
|
||||
// TODO [Delete in version 7.0 or higher]
|
||||
if (downloadExt == ".") downloadExt = fileUtility.getFileExtension(downloadUri); // Support for versions below 7.0
|
||||
|
||||
var newFileName = fileName;
|
||||
|
||||
// convert downloaded file to the file with the current extension if these extensions aren't equal
|
||||
if (downloadExt != curExt) {
|
||||
var key = documentService.generateRevisionId(downloadUri);
|
||||
newFileName = docManager.getCorrectName(fileUtility.getFileName(fileName, true) + downloadExt, userAddress); // get the correct file name if it already exists
|
||||
newFileName = req.docManager.getCorrectName(fileUtility.getFileName(fileName, true) + downloadExt, userAddress); // get the correct file name if it already exists
|
||||
try {
|
||||
documentService.getConvertedUriSync(downloadUri, downloadExt, curExt, key, function (err, data) {
|
||||
if (err) {
|
||||
@ -537,26 +583,30 @@ app.post("/track", function (req, res) { // define a handler for tracking file
|
||||
// callback file force saving process
|
||||
var callbackProcessForceSave = function (downloadUri, body, fileName, userAddress, newFileName = false){
|
||||
try {
|
||||
var downloadExt = fileUtility.getFileExtension(downloadUri);
|
||||
var downloadExt = "." + body.fileType;
|
||||
|
||||
/// TODO [Delete in version 7.0 or higher]
|
||||
if (downloadExt == ".") downloadExt = fileUtility.getFileExtension(downloadUri); // Support for versions below 7.0
|
||||
|
||||
var isSubmitForm = body.forcesavetype === 3; // SubmitForm
|
||||
|
||||
if (isSubmitForm) {
|
||||
// new file
|
||||
if (newFileName){
|
||||
fileName = docManager.getCorrectName(fileUtility.getFileName(fileName, true) + "-form" + downloadExt, userAddress);
|
||||
fileName = req.docManager.getCorrectName(fileUtility.getFileName(fileName, true) + "-form" + downloadExt, userAddress);
|
||||
} else {
|
||||
var ext = fileUtility.getFileExtension(fileName);
|
||||
fileName = docManager.getCorrectName(fileUtility.getFileName(fileName, true) + "-form" + ext, userAddress);
|
||||
fileName = req.docManager.getCorrectName(fileUtility.getFileName(fileName, true) + "-form" + ext, userAddress);
|
||||
}
|
||||
var forcesavePath = docManager.storagePath(fileName, userAddress);
|
||||
var forcesavePath = req.docManager.storagePath(fileName, userAddress);
|
||||
} else {
|
||||
if (newFileName){
|
||||
fileName = docManager.getCorrectName(fileUtility.getFileName(fileName, true) + downloadExt, userAddress);
|
||||
fileName = req.docManager.getCorrectName(fileUtility.getFileName(fileName, true) + downloadExt, userAddress);
|
||||
}
|
||||
// create forcesave path if it doesn't exist
|
||||
forcesavePath = docManager.forcesavePath(fileName, userAddress, false);
|
||||
forcesavePath = req.docManager.forcesavePath(fileName, userAddress, false);
|
||||
if (forcesavePath == "") {
|
||||
forcesavePath = docManager.forcesavePath(fileName, userAddress, true);
|
||||
forcesavePath = req.docManager.forcesavePath(fileName, userAddress, true);
|
||||
}
|
||||
}
|
||||
|
||||
@ -566,7 +616,7 @@ app.post("/track", function (req, res) { // define a handler for tracking file
|
||||
|
||||
if (isSubmitForm) {
|
||||
var uid =body.actions[0].userid
|
||||
docManager.saveFileData(fileName, uid, "Filling Form", userAddress);
|
||||
req.docManager.saveFileData(fileName, uid, "Filling Form", userAddress);
|
||||
}
|
||||
} catch (ex) {
|
||||
response.write("{\"error\":1}");
|
||||
@ -588,7 +638,10 @@ app.post("/track", function (req, res) { // define a handler for tracking file
|
||||
}
|
||||
|
||||
var curExt = fileUtility.getFileExtension(fileName);
|
||||
var downloadExt = fileUtility.getFileExtension(downloadUri);
|
||||
var downloadExt = "." + body.filetype;
|
||||
|
||||
// TODO [Delete in version 7.0 or higher]
|
||||
if (downloadExt == ".") downloadExt = fileUtility.getFileExtension(downloadUri); // Support for versions below 7.0
|
||||
|
||||
// convert downloaded file to the file with the current extension if these extensions aren't equal
|
||||
if (downloadExt != curExt) {
|
||||
@ -695,21 +748,30 @@ app.post("/track", function (req, res) { // define a handler for tracking file
|
||||
app.get("/editor", function (req, res) { // define a handler for editing document
|
||||
try {
|
||||
|
||||
docManager.init(storageFolder, req, res);
|
||||
req.docManager = new docManager(req, res);
|
||||
|
||||
var fileName = fileUtility.getFileName(req.query.fileName);
|
||||
var fileExt = req.query.fileExt;
|
||||
var history = [];
|
||||
var historyData = [];
|
||||
var lang = docManager.getLang();
|
||||
var lang = req.docManager.getLang();
|
||||
var user = users.getUser(req.query.userid);
|
||||
|
||||
var userid = user.id;
|
||||
var name = user.name;
|
||||
var actionData = req.query.action ? req.query.action : "null";
|
||||
|
||||
var templatesImageUrl = docManager.getTemplateImageUrl(fileUtility.getFileType(fileName));
|
||||
var createUrl = docManager.getCreateUrl(fileUtility.getFileType(fileName), userid, type, lang);
|
||||
var actionData = "null";
|
||||
if (req.query.action){
|
||||
try {
|
||||
actionData = JSON.stringify(JSON.parse(req.query.action));
|
||||
}
|
||||
catch (ex) {
|
||||
console.log(ex);
|
||||
}
|
||||
}
|
||||
|
||||
var templatesImageUrl = req.docManager.getTemplateImageUrl(fileUtility.getFileType(fileName));
|
||||
var createUrl = req.docManager.getCreateUrl(fileUtility.getFileType(fileName), userid, type, lang);
|
||||
var templates = [
|
||||
{
|
||||
"image": "",
|
||||
@ -726,81 +788,92 @@ app.get("/editor", function (req, res) { // define a handler for editing docume
|
||||
var userGroup = user.group;
|
||||
var reviewGroups = user.reviewGroups;
|
||||
var commentGroups = user.commentGroups;
|
||||
var userInfoGroups = user.userInfoGroups;
|
||||
|
||||
if (fileExt != null) {
|
||||
var fileName = docManager.createDemo(!!req.query.sample, fileExt, userid, name); // create demo document of a given extension
|
||||
var fileName = req.docManager.createDemo(!!req.query.sample, fileExt, userid, name, false); // create demo document of a given extension
|
||||
|
||||
// get the redirect path
|
||||
var redirectPath = docManager.getServerUrl() + "/editor?fileName=" + encodeURIComponent(fileName) + docManager.getCustomParams();
|
||||
var redirectPath = req.docManager.getServerUrl() + "/editor?fileName=" + encodeURIComponent(fileName) + req.docManager.getCustomParams();
|
||||
res.redirect(redirectPath);
|
||||
return;
|
||||
}
|
||||
fileExt = fileUtility.getFileExtension(fileName);
|
||||
|
||||
var userAddress = docManager.curUserHostAddress();
|
||||
if (!docManager.existsSync(docManager.storagePath(fileName, userAddress))) { // if the file with a given name doesn't exist
|
||||
var userAddress = req.docManager.curUserHostAddress();
|
||||
if (!req.docManager.existsSync(req.docManager.storagePath(fileName, userAddress))) { // if the file with a given name doesn't exist
|
||||
throw {
|
||||
"message": "File not found: " + fileName // display error message
|
||||
};
|
||||
}
|
||||
var key = docManager.getKey(fileName);
|
||||
var url = docManager.getDownloadUrl(fileName);
|
||||
var urlUser = docManager.getlocalFileUri(fileName, 0, false)
|
||||
var key = req.docManager.getKey(fileName);
|
||||
var url = req.docManager.getDownloadUrl(fileName);
|
||||
var urlUser = path.isAbsolute(storageFolder) ? req.docManager.getDownloadUrl(fileName) + "&dmode=emb" : req.docManager.getlocalFileUri(fileName, 0, false);
|
||||
var mode = req.query.mode || "edit"; // mode: view/edit/review/comment/fillForms/embedded
|
||||
|
||||
var type = req.query.type || ""; // type: embedded/mobile/desktop
|
||||
if (type == "") {
|
||||
type = new RegExp(configServer.get("mobileRegEx"), "i").test(req.get('User-Agent')) ? "mobile" : "desktop";
|
||||
}
|
||||
type = new RegExp(configServer.get("mobileRegEx"), "i").test(req.get('User-Agent')) ? "mobile" : "desktop";
|
||||
} else if (type != "mobile"
|
||||
&& type != "embedded") {
|
||||
type = "desktop";
|
||||
}
|
||||
|
||||
var canEdit = configServer.get('editedDocs').indexOf(fileExt) != -1; // check if this file can be edited
|
||||
if ((!canEdit && mode == "edit" || mode == "fillForms") && configServer.get('fillDocs').indexOf(fileExt) != -1) {
|
||||
mode = "fillForms";
|
||||
canEdit = true;
|
||||
}
|
||||
if (!canEdit && mode == "edit") {
|
||||
mode = "view";
|
||||
}
|
||||
var submitForm = mode == "fillForms" && userid == "uid-1" && !1;
|
||||
|
||||
var countVersion = 1;
|
||||
|
||||
var historyPath = docManager.historyPath(fileName, userAddress);
|
||||
var historyPath = req.docManager.historyPath(fileName, userAddress);
|
||||
var changes = null;
|
||||
var keyVersion = key;
|
||||
|
||||
if (historyPath != '') {
|
||||
|
||||
countVersion = docManager.countVersion(historyPath) + 1; // get the number of file versions
|
||||
countVersion = req.docManager.countVersion(historyPath) + 1; // get the number of file versions
|
||||
for (var i = 1; i <= countVersion; i++) { // get keys to all the file versions
|
||||
if (i < countVersion) {
|
||||
var keyPath = docManager.keyPath(fileName, userAddress, i);
|
||||
var keyPath = req.docManager.keyPath(fileName, userAddress, i);
|
||||
if (!fileSystem.existsSync(keyPath)) continue;
|
||||
keyVersion = "" + fileSystem.readFileSync(keyPath);
|
||||
} else {
|
||||
keyVersion = key;
|
||||
}
|
||||
history.push(docManager.getHistory(fileName, changes, keyVersion, i)); // write all the file history information
|
||||
history.push(req.docManager.getHistory(fileName, changes, keyVersion, i)); // write all the file history information
|
||||
|
||||
var historyD = {
|
||||
fileType: fileExt.slice(1),
|
||||
version: i,
|
||||
key: keyVersion,
|
||||
url: i == countVersion ? url : (docManager.getlocalFileUri(fileName, i, true) + "/prev" + fileExt),
|
||||
url: i == countVersion ? url : (`${req.docManager.getServerUrl(false)}/history?fileName=${encodeURIComponent(fileName)}&file=prev${fileExt}&ver=${i}&useraddress=${userAddress}`),
|
||||
};
|
||||
|
||||
if (i > 1 && docManager.existsSync(docManager.diffPath(fileName, userAddress, i-1))) { // check if the path to the file with document versions differences exists
|
||||
if (i > 1 && req.docManager.existsSync(req.docManager.diffPath(fileName, userAddress, i-1))) { // check if the path to the file with document versions differences exists
|
||||
historyD.previous = { // write information about previous file version
|
||||
fileType: historyData[i-2].fileType,
|
||||
key: historyData[i-2].key,
|
||||
url: historyData[i-2].url,
|
||||
};
|
||||
historyD.changesUrl = docManager.getlocalFileUri(fileName, i-1) + "/diff.zip"; // get the path to the diff.zip file and write it to the history object
|
||||
let changesUrl = `${req.docManager.getServerUrl(false)}/history?fileName=${encodeURIComponent(fileName)}&file=diff.zip&ver=${i-1}&useraddress=${userAddress}`;
|
||||
historyD.changesUrl = changesUrl; // get the path to the diff.zip file and write it to the history object
|
||||
}
|
||||
|
||||
historyData.push(historyD);
|
||||
|
||||
if (i < countVersion) {
|
||||
var changesFile = docManager.changesPath(fileName, userAddress, i); // get the path to the file with document changes
|
||||
changes = docManager.getChanges(changesFile); // get changes made in the file
|
||||
var changesFile = req.docManager.changesPath(fileName, userAddress, i); // get the path to the file with document changes
|
||||
changes = req.docManager.getChanges(changesFile); // get changes made in the file
|
||||
}
|
||||
}
|
||||
} else { // if history path is empty
|
||||
history.push(docManager.getHistory(fileName, changes, keyVersion, countVersion)); // write the history information about the last file version
|
||||
history.push(req.docManager.getHistory(fileName, changes, keyVersion, countVersion)); // write the history information about the last file version
|
||||
historyData.push({
|
||||
version: countVersion,
|
||||
key: key,
|
||||
@ -831,7 +904,7 @@ app.get("/editor", function (req, res) { // define a handler for editing docume
|
||||
documentType: fileUtility.getFileType(fileName),
|
||||
key: key,
|
||||
token: "",
|
||||
callbackUrl: docManager.getCallback(fileName),
|
||||
callbackUrl: req.docManager.getCallback(fileName),
|
||||
createUrl: userid != "uid-0" ? createUrl : null,
|
||||
templates: user.templates ? templates : null,
|
||||
isEdit: canEdit && (mode == "edit" || mode == "view" || mode == "filter" || mode == "blockcontent"),
|
||||
@ -843,16 +916,17 @@ app.get("/editor", function (req, res) { // define a handler for editing docume
|
||||
copy: !user.deniedPermissions.includes("copy"),
|
||||
download: !user.deniedPermissions.includes("download"),
|
||||
print: !user.deniedPermissions.includes("print"),
|
||||
mode: canEdit && mode != "view" ? "edit" : "view",
|
||||
mode: mode != "view" ? "edit" : "view",
|
||||
canBackToFolder: type != "embedded",
|
||||
backUrl: docManager.getServerUrl() + "/",
|
||||
curUserHostAddress: docManager.curUserHostAddress(),
|
||||
backUrl: req.docManager.getServerUrl() + "/",
|
||||
curUserHostAddress: req.docManager.curUserHostAddress(),
|
||||
lang: lang,
|
||||
userid: userid,
|
||||
userid: userid != "uid-0" ? userid : null,
|
||||
name: name,
|
||||
userGroup: userGroup,
|
||||
reviewGroups: JSON.stringify(reviewGroups),
|
||||
commentGroups: JSON.stringify(commentGroups),
|
||||
userInfoGroups: JSON.stringify(userInfoGroups),
|
||||
fileChoiceUrl: fileChoiceUrl,
|
||||
submitForm: submitForm,
|
||||
plugins: JSON.stringify(plugins),
|
||||
@ -862,15 +936,15 @@ app.get("/editor", function (req, res) { // define a handler for editing docume
|
||||
historyData: historyData,
|
||||
dataInsertImage: {
|
||||
fileType: "png",
|
||||
url: docManager.getServerUrl(true) + "/images/logo.png"
|
||||
url: req.docManager.getServerUrl(true) + "/images/logo.png"
|
||||
},
|
||||
dataCompareFile: {
|
||||
fileType: "docx",
|
||||
url: docManager.getServerUrl(true) + "/assets/sample/sample.docx"
|
||||
url: req.docManager.getServerUrl(true) + "/assets/sample/sample.docx"
|
||||
},
|
||||
dataMailMergeRecipients: {
|
||||
fileType: "csv",
|
||||
url: docManager.getServerUrl(true) + "/csv"
|
||||
url: req.docManager.getServerUrl(true) + "/csv"
|
||||
},
|
||||
usersForMentions: user.id != "uid-0" ? users.getUsersForMentions(user.id) : null,
|
||||
};
|
||||
@ -899,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
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
{
|
||||
"version": "1.0.0",
|
||||
"version": "1.2.0",
|
||||
"log": {
|
||||
"appenders": [
|
||||
{
|
||||
@ -25,7 +25,7 @@
|
||||
"viewedDocs": [".pdf", ".djvu", ".xps", ".oxps"],
|
||||
"editedDocs": [".docx", ".xlsx", ".csv", ".pptx", ".txt", ".docxf"],
|
||||
"fillDocs": [".docx", ".oform"],
|
||||
"convertedDocs": [".docm", ".doc", ".dotx", ".dotm", ".dot", ".odt", ".fodt", ".ott", ".xlsm", ".xls", ".xltx", ".xltm", ".xlt", ".ods", ".fods", ".ots", ".pptm", ".ppt", ".ppsx", ".ppsm", ".pps", ".potx", ".potm", ".pot", ".odp", ".fodp", ".otp", ".rtf", ".mht", ".html", ".htm", ".xml", ".epub", ".fb2"],
|
||||
"convertedDocs": [".docm", ".doc", ".dotx", ".dotm", ".dot", ".odt", ".fodt", ".ott", ".xlsm", ".xlsb", ".xls", ".xltx", ".xltm", ".xlt", ".ods", ".fods", ".ots", ".pptm", ".ppt", ".ppsx", ".ppsm", ".pps", ".potx", ".potm", ".pot", ".odp", ".fodp", ".otp", ".rtf", ".mht", ".html", ".htm", ".xml", ".epub", ".fb2"],
|
||||
"storageFolder": "./files",
|
||||
"storagePath": "/files",
|
||||
"maxFileSize": 1073741824,
|
||||
@ -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": {
|
||||
|
||||
@ -21,19 +21,16 @@ const path = require("path");
|
||||
const fileSystem = require("fs");
|
||||
const fileUtility = require("./fileUtility");
|
||||
const documentService = require("./documentService");
|
||||
const cacheManager = require("./cacheManager");
|
||||
const guidManager = require("./guidManager");
|
||||
const configServer = require('config').get('server');
|
||||
const os = require("os");
|
||||
const storageConfigFolder = configServer.get("storageFolder");
|
||||
|
||||
let docManager = {};
|
||||
|
||||
docManager.dir = null;
|
||||
docManager.req = null;
|
||||
docManager.res = null;
|
||||
function docManager(req, res) {
|
||||
this.req = req;
|
||||
this.res = res;
|
||||
}
|
||||
|
||||
// check if the path exists or not
|
||||
docManager.existsSync = function(path) {
|
||||
docManager.prototype.existsSync = function(path) {
|
||||
let res = true;
|
||||
try {
|
||||
fileSystem.accessSync(path, fileSystem.F_OK); // synchronously test the user's permissions for the directory specified by path; the directory is visible to the calling process
|
||||
@ -44,57 +41,51 @@ docManager.existsSync = function(path) {
|
||||
};
|
||||
|
||||
// create a new directory if it doesn't exist
|
||||
docManager.createDirectory = function(path) {
|
||||
docManager.prototype.createDirectory = function(path) {
|
||||
if (!this.existsSync(path)) {
|
||||
fileSystem.mkdirSync(path);
|
||||
}
|
||||
};
|
||||
|
||||
docManager.init = function (dir, req, res) {
|
||||
docManager.dir = dir;
|
||||
docManager.req = req;
|
||||
docManager.res = res;
|
||||
};
|
||||
|
||||
// get the language from the request
|
||||
docManager.getLang = function () {
|
||||
if (docManager.req.query.lang) {
|
||||
return docManager.req.query.lang;
|
||||
docManager.prototype.getLang = function () {
|
||||
if (new RegExp("^[a-z]{2}(-[A-Z]{2})?$", "i").test(this.req.query.lang)) {
|
||||
return this.req.query.lang;
|
||||
} else { // the default language value is English
|
||||
return "en"
|
||||
}
|
||||
};
|
||||
|
||||
// get customization parameters
|
||||
docManager.getCustomParams = function () {
|
||||
docManager.prototype.getCustomParams = function () {
|
||||
let params = "";
|
||||
|
||||
const userid = docManager.req.query.userid; // user id
|
||||
const userid = this.req.query.userid; // user id
|
||||
params += (userid ? "&userid=" + userid : "");
|
||||
|
||||
const lang = docManager.req.query.lang; // language
|
||||
params += (lang ? "&lang=" + docManager.getLang() : "");
|
||||
const lang = this.req.query.lang; // language
|
||||
params += (lang ? "&lang=" + this.getLang() : "");
|
||||
|
||||
const fileName = docManager.req.query.fileName; // file name
|
||||
const fileName = this.req.query.fileName; // file name
|
||||
params += (fileName ? "&fileName=" + fileName : "");
|
||||
|
||||
const mode = docManager.req.query.mode; // mode: view/edit/review/comment/fillForms/embedded
|
||||
const mode = this.req.query.mode; // mode: view/edit/review/comment/fillForms/embedded
|
||||
params += (mode ? "&mode=" + mode : "");
|
||||
|
||||
const type = docManager.req.query.type; // type: embedded/mobile/desktop
|
||||
const type = this.req.query.type; // type: embedded/mobile/desktop
|
||||
params += (type ? "&type=" + type : "");
|
||||
|
||||
return params;
|
||||
};
|
||||
|
||||
// get the correct file name if such a name already exists
|
||||
docManager.getCorrectName = function (fileName, userAddress) {
|
||||
docManager.prototype.getCorrectName = function (fileName, userAddress) {
|
||||
const baseName = fileUtility.getFileName(fileName, true); // get file name from the url without extension
|
||||
const ext = fileUtility.getFileExtension(fileName); // get file extension from the url
|
||||
let name = baseName + ext; // get full file name
|
||||
let index = 1;
|
||||
|
||||
while (this.existsSync(docManager.storagePath(name, userAddress))) { // if the file with such a name already exists in this directory
|
||||
while (this.existsSync(this.storagePath(name, userAddress))) { // if the file with such a name already exists in this directory
|
||||
name = baseName + " (" + index + ")" + ext; // add an index after its base name
|
||||
index++;
|
||||
}
|
||||
@ -102,39 +93,69 @@ docManager.getCorrectName = function (fileName, userAddress) {
|
||||
return name;
|
||||
};
|
||||
|
||||
// processes a request editnew
|
||||
docManager.prototype.RequestEditnew = function (req, fileName, user) {
|
||||
if (req.params['id'] != fileName){ // processes a repeated request editnew
|
||||
this.fileRemove(req.params['id']);
|
||||
fileName = this.getCorrectName(req.params['id']);
|
||||
}
|
||||
this.fileSizeZero(fileName);
|
||||
this.saveFileData(fileName, user.id, user.name);
|
||||
|
||||
return fileName;
|
||||
}
|
||||
|
||||
// delete a file with its history
|
||||
docManager.prototype.fileRemove = function (fileName) {
|
||||
const filePath = this.storagePath(fileName); // get the path to this file
|
||||
fileSystem.unlinkSync(filePath); // and delete it
|
||||
|
||||
const userAddress = this.curUserHostAddress();
|
||||
const historyPath = this.historyPath(fileName, userAddress, true);
|
||||
this.cleanFolderRecursive(historyPath, true); // clean all the files from the history folder
|
||||
}
|
||||
|
||||
// create a zero-size file
|
||||
docManager.prototype.fileSizeZero = function (fileName) {
|
||||
var path = this.storagePath(fileName);
|
||||
var fh = fileSystem.openSync(path, 'w');
|
||||
fileSystem.closeSync(fh);
|
||||
}
|
||||
|
||||
// create demo document
|
||||
docManager.createDemo = function (isSample, fileExt, userid, username) {
|
||||
docManager.prototype.createDemo = function (isSample, fileExt, userid, username, wopi) {
|
||||
|
||||
const demoName = (isSample ? "sample" : "new") + "." + fileExt;
|
||||
const fileName = docManager.getCorrectName(demoName); // get the correct file name if such a name already exists
|
||||
const fileName = this.getCorrectName(demoName); // get the correct file name if such a name already exists
|
||||
|
||||
docManager.copyFile(path.join(__dirname, "..","public", "assets", isSample ? "sample" : "new", demoName), docManager.storagePath(fileName)); // copy sample document of a necessary extension to the storage path
|
||||
this.copyFile(path.join(__dirname, "..","public", "assets", isSample ? "sample" : "new", demoName), this.storagePath(fileName)); // copy sample document of a necessary extension to the storage path
|
||||
|
||||
docManager.saveFileData(fileName, userid, username); // save file data to the file
|
||||
this.saveFileData(fileName, userid, username); // save file data to the file
|
||||
|
||||
return fileName;
|
||||
};
|
||||
|
||||
// save file data to the file
|
||||
docManager.saveFileData = function (fileName, userid, username, userAddress) {
|
||||
docManager.prototype.saveFileData = function (fileName, userid, username, userAddress) {
|
||||
if (!userAddress) {
|
||||
userAddress = docManager.curUserHostAddress(); // get current user host address
|
||||
userAddress = this.curUserHostAddress(); // get current user host address
|
||||
}
|
||||
// get full creation date of the document
|
||||
const date_create = fileSystem.statSync(docManager.storagePath(fileName, userAddress)).mtime;
|
||||
const date_create = fileSystem.statSync(this.storagePath(fileName, userAddress)).mtime;
|
||||
const minutes = (date_create.getMinutes() < 10 ? '0' : '') + date_create.getMinutes().toString();
|
||||
const month = (date_create.getMonth() < 10 ? '0' : '') + (parseInt(date_create.getMonth().toString()) + 1);
|
||||
const sec = (date_create.getSeconds() < 10 ? '0' : '') + date_create.getSeconds().toString();
|
||||
const date_format = date_create.getFullYear() + "-" + month + "-" + date_create.getDate() + " " + date_create.getHours() + ":" + minutes + ":" + sec;
|
||||
|
||||
const file_info = docManager.historyPath(fileName, userAddress, true); // get file history information
|
||||
const file_info = this.historyPath(fileName, userAddress, true); // get file history information
|
||||
this.createDirectory(file_info); // create a new history directory if it doesn't exist
|
||||
|
||||
fileSystem.writeFileSync(path.join(file_info, fileName + ".txt"), date_format + "," + userid + "," + username); // write all the file information to a new txt file
|
||||
};
|
||||
|
||||
// get file data
|
||||
docManager.getFileData = function (fileName, userAddress) {
|
||||
const history = path.join(docManager.historyPath(fileName, userAddress, true), fileName + ".txt"); // get the path to the file with file information
|
||||
docManager.prototype.getFileData = function (fileName, userAddress) {
|
||||
const history = path.join(this.historyPath(fileName, userAddress, true), fileName + ".txt"); // get the path to the file with file information
|
||||
if (!this.existsSync(history)) { // if such a file doesn't exist
|
||||
return ["2017-01-01", "uid-1", "John Smith"]; // return default information
|
||||
}
|
||||
@ -143,15 +164,15 @@ docManager.getFileData = function (fileName, userAddress) {
|
||||
};
|
||||
|
||||
// get url to the original file
|
||||
docManager.getFileUri = function (fileName) {
|
||||
return docManager.getlocalFileUri(fileName, 0, true);
|
||||
docManager.prototype.getFileUri = function (fileName) {
|
||||
return this.getlocalFileUri(fileName, 0, true);
|
||||
};
|
||||
|
||||
// get local file url
|
||||
docManager.getlocalFileUri = function (fileName, version, forDocumentServer) {
|
||||
const serverPath = docManager.getServerUrl(forDocumentServer);
|
||||
const hostAddress = docManager.curUserHostAddress();
|
||||
const url = serverPath + configServer.get("storagePath") + "/" + hostAddress + "/" + encodeURIComponent(fileName); // get full url address to the file
|
||||
docManager.prototype.getlocalFileUri = function (fileName, version, forDocumentServer) {
|
||||
const serverPath = this.getServerUrl(forDocumentServer);
|
||||
const hostAddress = this.curUserHostAddress();
|
||||
let url = serverPath + configServer.get("storagePath") + "/" + hostAddress + "/" + encodeURIComponent(fileName); // get full url address to the file
|
||||
if (!version) {
|
||||
return url;
|
||||
}
|
||||
@ -159,63 +180,67 @@ docManager.getlocalFileUri = function (fileName, version, forDocumentServer) {
|
||||
};
|
||||
|
||||
// get server url
|
||||
docManager.getServerUrl = function (forDocumentServer) {
|
||||
return (forDocumentServer && !!configServer.get("exampleUrl")) ? configServer.get("exampleUrl") : docManager.getServerPath();
|
||||
docManager.prototype.getServerUrl = function (forDocumentServer) {
|
||||
return (forDocumentServer && !!configServer.get("exampleUrl")) ? configServer.get("exampleUrl") : this.getServerPath();
|
||||
};
|
||||
|
||||
// get server address from the request
|
||||
docManager.getServerPath = function () {
|
||||
return docManager.getServerHost() + (docManager.req.headers["x-forwarded-path"] || docManager.req.baseUrl);
|
||||
docManager.prototype.getServerPath = function () {
|
||||
return this.getServerHost() + (this.req.headers["x-forwarded-path"] || this.req.baseUrl);
|
||||
};
|
||||
|
||||
// get host address from the request
|
||||
docManager.getServerHost = function () {
|
||||
return docManager.getProtocol() + "://" + (docManager.req.headers["x-forwarded-host"] || docManager.req.headers["host"]);
|
||||
docManager.prototype.getServerHost = function () {
|
||||
return this.getProtocol() + "://" + (this.req.headers["x-forwarded-host"] || this.req.headers["host"]);
|
||||
};
|
||||
|
||||
// get protocol from the request
|
||||
docManager.getProtocol = function () {
|
||||
return docManager.req.headers["x-forwarded-proto"] || docManager.req.protocol;
|
||||
docManager.prototype.getProtocol = function () {
|
||||
return this.req.headers["x-forwarded-proto"] || this.req.protocol;
|
||||
};
|
||||
|
||||
// get callback url
|
||||
docManager.getCallback = function (fileName) {
|
||||
const server = docManager.getServerUrl(true);
|
||||
const hostAddress = docManager.curUserHostAddress();
|
||||
docManager.prototype.getCallback = function (fileName) {
|
||||
const server = this.getServerUrl(true);
|
||||
const hostAddress = this.curUserHostAddress();
|
||||
const handler = "/track?filename=" + encodeURIComponent(fileName) + "&useraddress=" + encodeURIComponent(hostAddress); // get callback handler
|
||||
|
||||
return server + handler;
|
||||
};
|
||||
|
||||
// get url to the created file
|
||||
docManager.getCreateUrl = function (docType, userid, type, lang) {
|
||||
const server = docManager.getServerUrl();
|
||||
var ext = docManager.getInternalExtension(docType).replace(".", "");
|
||||
docManager.prototype.getCreateUrl = function (docType, userid, type, lang) {
|
||||
const server = this.getServerUrl();
|
||||
var ext = this.getInternalExtension(docType).replace(".", "");
|
||||
const handler = "/editor?fileExt=" + ext + "&userid=" + userid + "&type=" + type + "&lang=" + lang;
|
||||
|
||||
return server + handler;
|
||||
}
|
||||
|
||||
// get url to download a file
|
||||
docManager.getDownloadUrl = function (fileName) {
|
||||
const server = docManager.getServerUrl(true);
|
||||
const hostAddress = docManager.curUserHostAddress();
|
||||
docManager.prototype.getDownloadUrl = function (fileName) {
|
||||
const server = this.getServerUrl(true);
|
||||
const hostAddress = this.curUserHostAddress();
|
||||
const handler = "/download?fileName=" + encodeURIComponent(fileName) + "&useraddress=" + encodeURIComponent(hostAddress);
|
||||
|
||||
return server + handler;
|
||||
};
|
||||
|
||||
docManager.prototype.storageRootPath = function (userAddress) {
|
||||
return path.join(storageConfigFolder, this.curUserHostAddress(userAddress)); // get the path to the directory for the host address
|
||||
}
|
||||
|
||||
// get the storage path of the given file
|
||||
docManager.storagePath = function (fileName, userAddress) {
|
||||
docManager.prototype.storagePath = function (fileName, userAddress) {
|
||||
fileName = fileUtility.getFileName(fileName); // get the file name with extension
|
||||
const directory = path.join(docManager.dir, docManager.curUserHostAddress(userAddress)); // get the path to the directory for the host address
|
||||
const directory = this.storageRootPath(userAddress);
|
||||
this.createDirectory(directory); // create a new directory if it doesn't exist
|
||||
return path.join(directory, fileName); // put the given file to this directory
|
||||
};
|
||||
|
||||
// get the path to the forcesaved file version
|
||||
docManager.forcesavePath = function (fileName, userAddress, create) {
|
||||
let directory = path.join(docManager.dir, docManager.curUserHostAddress(userAddress));
|
||||
docManager.prototype.forcesavePath = function (fileName, userAddress, create) {
|
||||
let directory = this.storageRootPath(userAddress);
|
||||
if (!this.existsSync(directory)) { // the directory with host address doesn't exist
|
||||
return "";
|
||||
}
|
||||
@ -232,8 +257,8 @@ docManager.forcesavePath = function (fileName, userAddress, create) {
|
||||
};
|
||||
|
||||
// create the path to the file history
|
||||
docManager.historyPath = function (fileName, userAddress, create) {
|
||||
let directory = path.join(docManager.dir, docManager.curUserHostAddress(userAddress));
|
||||
docManager.prototype.historyPath = function (fileName, userAddress, create) {
|
||||
let directory = this.storageRootPath(userAddress);
|
||||
if (!this.existsSync(directory)) {
|
||||
return "";
|
||||
}
|
||||
@ -245,40 +270,40 @@ docManager.historyPath = function (fileName, userAddress, create) {
|
||||
};
|
||||
|
||||
// get the path to the specified file version
|
||||
docManager.versionPath = function (fileName, userAddress, version) {
|
||||
const historyPath = docManager.historyPath(fileName, userAddress, true); // get the path to the history of a given file or create it if it doesn't exist
|
||||
docManager.prototype.versionPath = function (fileName, userAddress, version) {
|
||||
const historyPath = this.historyPath(fileName, userAddress, true); // get the path to the history of a given file or create it if it doesn't exist
|
||||
return path.join(historyPath, "" + version);
|
||||
};
|
||||
|
||||
// get the path to the previous file version
|
||||
docManager.prevFilePath = function (fileName, userAddress, version) {
|
||||
return path.join(docManager.versionPath(fileName, userAddress, version), "prev" + fileUtility.getFileExtension(fileName));
|
||||
docManager.prototype.prevFilePath = function (fileName, userAddress, version) {
|
||||
return path.join(this.versionPath(fileName, userAddress, version), "prev" + fileUtility.getFileExtension(fileName));
|
||||
};
|
||||
|
||||
// get the path to the file with document versions differences
|
||||
docManager.diffPath = function (fileName, userAddress, version) {
|
||||
return path.join(docManager.versionPath(fileName, userAddress, version), "diff.zip");
|
||||
docManager.prototype.diffPath = function (fileName, userAddress, version) {
|
||||
return path.join(this.versionPath(fileName, userAddress, version), "diff.zip");
|
||||
};
|
||||
|
||||
// get the path to the file with document changes
|
||||
docManager.changesPath = function (fileName, userAddress, version) {
|
||||
return path.join(docManager.versionPath(fileName, userAddress, version), "changes.txt");
|
||||
docManager.prototype.changesPath = function (fileName, userAddress, version) {
|
||||
return path.join(this.versionPath(fileName, userAddress, version), "changes.txt");
|
||||
};
|
||||
|
||||
// get the path to the file with key value in it
|
||||
docManager.keyPath = function (fileName, userAddress, version) {
|
||||
return path.join(docManager.versionPath(fileName, userAddress, version), "key.txt");
|
||||
docManager.prototype.keyPath = function (fileName, userAddress, version) {
|
||||
return path.join(this.versionPath(fileName, userAddress, version), "key.txt");
|
||||
};
|
||||
|
||||
// get the path to the file with the user information
|
||||
docManager.changesUser = function (fileName, userAddress, version) {
|
||||
return path.join(docManager.versionPath(fileName, userAddress, version), "user.txt");
|
||||
docManager.prototype.changesUser = function (fileName, userAddress, version) {
|
||||
return path.join(this.versionPath(fileName, userAddress, version), "user.txt");
|
||||
};
|
||||
|
||||
// get all the stored files
|
||||
docManager.getStoredFiles = function () {
|
||||
const userAddress = docManager.curUserHostAddress();
|
||||
const directory = path.join(docManager.dir, userAddress);
|
||||
docManager.prototype.getStoredFiles = function () {
|
||||
const userAddress = this.curUserHostAddress();
|
||||
const directory = this.storageRootPath(userAddress);
|
||||
this.createDirectory(directory);
|
||||
const result = [];
|
||||
const storedFiles = fileSystem.readdirSync(directory); // read the user host directory contents
|
||||
@ -286,10 +311,10 @@ docManager.getStoredFiles = function () {
|
||||
const stats = fileSystem.lstatSync(path.join(directory, storedFiles[i])); // save element parameters
|
||||
|
||||
if (!stats.isDirectory()) { // if the element isn't a directory
|
||||
let historyPath = docManager.historyPath(storedFiles[i], userAddress); // get the path to the file history
|
||||
let historyPath = this.historyPath(storedFiles[i], userAddress); // get the path to the file history
|
||||
let version = 0;
|
||||
if (historyPath != "") { // if the history path exists
|
||||
version = docManager.countVersion(historyPath); // get the last file version
|
||||
version = this.countVersion(historyPath); // get the last file version
|
||||
}
|
||||
|
||||
const time = stats.mtime.getTime(); // get the time of element modification
|
||||
@ -318,20 +343,20 @@ docManager.getStoredFiles = function () {
|
||||
};
|
||||
|
||||
// get current user host address
|
||||
docManager.curUserHostAddress = function (userAddress) {
|
||||
docManager.prototype.curUserHostAddress = function (userAddress) {
|
||||
if (!userAddress) // if user address isn't passed to the function
|
||||
userAddress = docManager.req.headers["x-forwarded-for"] || docManager.req.connection.remoteAddress; // take it from the header or use the remote address
|
||||
userAddress = this.req.headers["x-forwarded-for"] || this.req.connection.remoteAddress; // take it from the header or use the remote address
|
||||
|
||||
return userAddress.replace(new RegExp("[^0-9a-zA-Z.=]", "g"), "_");
|
||||
};
|
||||
|
||||
// copy file
|
||||
docManager.copyFile = function (exist, target) {
|
||||
docManager.prototype.copyFile = function (exist, target) {
|
||||
fileSystem.writeFileSync(target, fileSystem.readFileSync(exist));
|
||||
};
|
||||
|
||||
// get an internal extension
|
||||
docManager.getInternalExtension = function (fileType) {
|
||||
docManager.prototype.getInternalExtension = function (fileType) {
|
||||
if (fileType == fileUtility.fileType.word) // .docx for word type
|
||||
return ".docx";
|
||||
|
||||
@ -345,8 +370,8 @@ docManager.getInternalExtension = function (fileType) {
|
||||
};
|
||||
|
||||
// get the template image url
|
||||
docManager.getTemplateImageUrl = function (fileType) {
|
||||
let path = docManager.getServerUrl(true);
|
||||
docManager.prototype.getTemplateImageUrl = function (fileType) {
|
||||
let path = this.getServerUrl(true);
|
||||
if (fileType == fileUtility.fileType.word) // for word type
|
||||
return path + "/images/file_docx.svg";
|
||||
|
||||
@ -360,16 +385,16 @@ docManager.getTemplateImageUrl = function (fileType) {
|
||||
}
|
||||
|
||||
// get document key
|
||||
docManager.getKey = function (fileName) {
|
||||
const userAddress = docManager.curUserHostAddress();
|
||||
let key = userAddress + docManager.getlocalFileUri(fileName); // get document key by adding local file url to the current user host address
|
||||
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 = docManager.historyPath(fileName, userAddress); // get the path to the file history
|
||||
let historyPath = this.historyPath(fileName, userAddress); // get the path to the file history
|
||||
if (historyPath != ""){ // if the path to the file history exists
|
||||
key += docManager.countVersion(historyPath); // add file version number to the document key
|
||||
key += this.countVersion(historyPath); // add file version number to the document key
|
||||
}
|
||||
|
||||
let storagePath = docManager.storagePath(fileName, userAddress); // get the storage path to the given file
|
||||
let storagePath = this.storagePath(fileName, userAddress); // get the storage path to the given file
|
||||
const stat = fileSystem.statSync(storagePath); // get file information
|
||||
key += stat.mtime.getTime(); // and add creation time to the document key
|
||||
|
||||
@ -377,13 +402,13 @@ docManager.getKey = function (fileName) {
|
||||
};
|
||||
|
||||
// get current date
|
||||
docManager.getDate = function (date) {
|
||||
docManager.prototype.getDate = function (date) {
|
||||
const minutes = (date.getMinutes() < 10 ? '0' : '') + date.getMinutes().toString();
|
||||
return date.getMonth() + "/" + date.getDate() + "/" + date.getFullYear() + " " + date.getHours() + ":" + minutes;
|
||||
};
|
||||
|
||||
// get changes made in the file
|
||||
docManager.getChanges = function (fileName) {
|
||||
docManager.prototype.getChanges = function (fileName) {
|
||||
if (this.existsSync(fileName)) { // if the directory with such a file exists
|
||||
return JSON.parse(fileSystem.readFileSync(fileName)); // read this file and parse it
|
||||
}
|
||||
@ -391,7 +416,7 @@ docManager.getChanges = function (fileName) {
|
||||
};
|
||||
|
||||
// get the last file version
|
||||
docManager.countVersion = function(directory) {
|
||||
docManager.prototype.countVersion = function(directory) {
|
||||
let i = 0;
|
||||
while (this.existsSync(path.join(directory, '' + (i + 1)))) { // run through all the file versions
|
||||
i++; // and count them
|
||||
@ -400,7 +425,7 @@ docManager.countVersion = function(directory) {
|
||||
};
|
||||
|
||||
// get file history information
|
||||
docManager.getHistory = function (fileName, content, keyVersion, version) {
|
||||
docManager.prototype.getHistory = function (fileName, content, keyVersion, version) {
|
||||
let oldVersion = false;
|
||||
let contentJson = null;
|
||||
if (content) { // if content is defined
|
||||
@ -414,10 +439,10 @@ docManager.getHistory = function (fileName, content, keyVersion, version) {
|
||||
}
|
||||
}
|
||||
|
||||
const userAddress = docManager.curUserHostAddress();
|
||||
const username = content ? (oldVersion ? contentJson.username : contentJson.user.name) : (docManager.getFileData(fileName, userAddress))[2];
|
||||
const userid = content ? (oldVersion ? contentJson.userid : contentJson.user.id) : (docManager.getFileData(fileName, userAddress))[1];
|
||||
const created = content ? (oldVersion ? contentJson.date : contentJson.created) : (docManager.getFileData(fileName, userAddress))[0];
|
||||
const userAddress = this.curUserHostAddress();
|
||||
const username = content ? (oldVersion ? contentJson.username : contentJson.user.name) : (this.getFileData(fileName, userAddress))[2];
|
||||
const userid = content ? (oldVersion ? contentJson.userid : contentJson.user.id) : (this.getFileData(fileName, userAddress))[1];
|
||||
const created = content ? (oldVersion ? contentJson.date : contentJson.created) : (this.getFileData(fileName, userAddress))[0];
|
||||
const res = (content && !oldVersion) ? content : {changes: content};
|
||||
res.key = keyVersion; // write the information about the user, creation time, key and version to the result object
|
||||
res.version = version;
|
||||
@ -431,7 +456,7 @@ docManager.getHistory = function (fileName, content, keyVersion, version) {
|
||||
};
|
||||
|
||||
// clean folder
|
||||
docManager.cleanFolderRecursive = function (folder, me) {
|
||||
docManager.prototype.cleanFolderRecursive = function (folder, me) {
|
||||
if (fileSystem.existsSync(folder)) { // if the given folder exists
|
||||
const files = fileSystem.readdirSync(folder);
|
||||
files.forEach((file) => { // for each file from the folder
|
||||
@ -449,9 +474,9 @@ docManager.cleanFolderRecursive = function (folder, me) {
|
||||
};
|
||||
|
||||
// get files information
|
||||
docManager.getFilesInfo = function (fileId) {
|
||||
const userAddress = docManager.curUserHostAddress();
|
||||
const directory = path.join(docManager.dir, userAddress);
|
||||
docManager.prototype.getFilesInfo = function (fileId) {
|
||||
const userAddress = this.curUserHostAddress();
|
||||
const directory = this.storageRootPath(userAddress);
|
||||
const filesInDirectory = this.getStoredFiles(); // get all the stored files from the folder
|
||||
let responseArray = [];
|
||||
let responseObject;
|
||||
|
||||
11
web/documentserver-example/nodejs/helpers/documentService.js
Normal file → Executable file
11
web/documentserver-example/nodejs/helpers/documentService.js
Normal file → Executable file
@ -17,11 +17,9 @@
|
||||
*/
|
||||
|
||||
// get all the necessary values and modules
|
||||
var path = require("path");
|
||||
var urlModule = require("url");
|
||||
var urllib = require("urllib");
|
||||
var jwt = require("jsonwebtoken");
|
||||
var jwa = require("jwa");
|
||||
var fileUtility = require("./fileUtility");
|
||||
var guidManager = require("./guidManager");
|
||||
var configServer = require('config').get('server');
|
||||
@ -170,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'
|
||||
|
||||
@ -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];
|
||||
|
||||
@ -66,7 +68,7 @@ fileUtility.fileType = {
|
||||
fileUtility.documentExts = [".doc", ".docx", ".oform", ".docm", ".dot", ".dotx", ".dotm", ".odt", ".fodt", ".ott", ".rtf", ".txt", ".html", ".htm", ".mht", ".xml", ".pdf", ".djvu", ".fb2", ".epub", ".xps", ".oxps"];
|
||||
|
||||
// the spreadsheet extension list
|
||||
fileUtility.spreadsheetExts = [".xls", ".xlsx", ".xlsm", ".xlt", ".xltx", ".xltm", ".ods", ".fods", ".ots", ".csv"];
|
||||
fileUtility.spreadsheetExts = [".xls", ".xlsx", ".xlsm", ".xlsb", ".xlt", ".xltx", ".xltm", ".ods", ".fods", ".ots", ".csv"];
|
||||
|
||||
// the presentation extension list
|
||||
fileUtility.presentationExts = [".pps", ".ppsx", ".ppsm", ".ppt", ".pptx", ".pptm", ".pot", ".potx", ".potm", ".odp", ".fodp", ".otp"];
|
||||
|
||||
@ -23,6 +23,7 @@ var descr_user_1 = [
|
||||
"Can perform all actions with comments",
|
||||
"The file favorite state is undefined",
|
||||
"Can create files from templates using data from the editor",
|
||||
"Can see the information about all users",
|
||||
//"Can submit forms"
|
||||
];
|
||||
|
||||
@ -32,6 +33,7 @@ var descr_user_2 = [
|
||||
"Can view comments, edit his own comments and comments left by users with no group. Can remove his own comments only",
|
||||
"This file is marked as favorite",
|
||||
"Can create new files from the editor",
|
||||
"Can see the information about users from Group2 and users who don’t belong to any group",
|
||||
//"Can’t submit forms"
|
||||
];
|
||||
|
||||
@ -44,6 +46,7 @@ var descr_user_3 = [
|
||||
"Can’t download the file",
|
||||
"Can’t print the file",
|
||||
"Can create new files from the editor",
|
||||
"Can see the information about Group2 users",
|
||||
//"Can’t submit forms"
|
||||
];
|
||||
|
||||
@ -55,39 +58,42 @@ var descr_user_0 = [
|
||||
"The file favorite state is undefined",
|
||||
"Can't mention others in comments",
|
||||
"Can't create new files from the editor",
|
||||
"Can’t see anyone’s information",
|
||||
"Can't rename files from the editor",
|
||||
//"Can’t submit forms"
|
||||
];
|
||||
|
||||
var users = [
|
||||
new User("uid-1", "John Smith", "smith@example.com",
|
||||
null, null, {},
|
||||
null, null, {}, null,
|
||||
null, [], descr_user_1, true),
|
||||
new User("uid-2", "Mark Pottato", "pottato@example.com",
|
||||
"group-2", ["group-2", ""], {
|
||||
view: "",
|
||||
edit: ["group-2", ""],
|
||||
remove: ["group-2"]
|
||||
},
|
||||
}, ["group-2", ""],
|
||||
true, [], descr_user_2, false), // own and without group
|
||||
new User("uid-3", "Hamish Mitchell", "mitchell@example.com",
|
||||
"group-3", ["group-2"], {
|
||||
view: ["group-3", "group-2"],
|
||||
edit: ["group-2"],
|
||||
remove: []
|
||||
},
|
||||
}, ["group-2"],
|
||||
false, ["copy", "download", "print"], descr_user_3, false), // other group only
|
||||
new User("uid-0", null, null,
|
||||
null, null, {},
|
||||
null, null, {}, [],
|
||||
null, [], descr_user_0, false),
|
||||
];
|
||||
|
||||
function User(id, name, email, group, reviewGroups, commentGroups, favorite, deniedPermissions, descriptions, templates) {
|
||||
function User(id, name, email, group, reviewGroups, commentGroups, userInfoGroups, favorite, deniedPermissions, descriptions, templates) {
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
this.email = email;
|
||||
this.group = group;
|
||||
this.reviewGroups = reviewGroups;
|
||||
this.commentGroups = commentGroups;
|
||||
this.userInfoGroups = userInfoGroups;
|
||||
this.favorite = favorite;
|
||||
this.deniedPermissions = deniedPermissions;
|
||||
this.descriptions = descriptions;
|
||||
|
||||
@ -17,14 +17,13 @@
|
||||
*/
|
||||
|
||||
const reqConsts = require('./request');
|
||||
const docManager = require("../docManager");
|
||||
const fileUtility = require("../fileUtility");
|
||||
const lockManager = require("./lockManager");
|
||||
const utils = require("./utils");
|
||||
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;
|
||||
@ -105,8 +104,8 @@ function parseWopiRequest(req) {
|
||||
function lock(wopi, req, res, userHost) {
|
||||
let requestLock = req.headers[reqConsts.requestHeaders.Lock.toLowerCase()];
|
||||
|
||||
let userAddress = docManager.curUserHostAddress(userHost); // get current user host address
|
||||
let filePath = docManager.storagePath(wopi.id, userAddress); // get the storage path of the given file
|
||||
let userAddress = req.docManager.curUserHostAddress(userHost); // get current user host address
|
||||
let filePath = req.docManager.storagePath(wopi.id, userAddress); // get the storage path of the given file
|
||||
|
||||
if (!lockManager.hasLock(filePath)) {
|
||||
// file isn't locked => lock
|
||||
@ -125,8 +124,8 @@ function lock(wopi, req, res, userHost) {
|
||||
|
||||
// retrieve a lock on a file
|
||||
function getLock(wopi, req, res, userHost) {
|
||||
let userAddress = docManager.curUserHostAddress(userHost);
|
||||
let filePath = docManager.storagePath(wopi.id, userAddress);
|
||||
let userAddress = req.docManager.curUserHostAddress(userHost);
|
||||
let filePath = req.docManager.storagePath(wopi.id, userAddress);
|
||||
|
||||
// get the lock of the specified file and set it as the X-WOPI-Lock header
|
||||
res.setHeader(reqConsts.requestHeaders.lock, lockManager.getLock(filePath));
|
||||
@ -137,8 +136,8 @@ function getLock(wopi, req, res, userHost) {
|
||||
function refreshLock(wopi, req, res, userHost) {
|
||||
let requestLock = req.headers[reqConsts.requestHeaders.Lock.toLowerCase()];
|
||||
|
||||
let userAddress = docManager.curUserHostAddress(userHost);
|
||||
let filePath = docManager.storagePath(wopi.id, userAddress);
|
||||
let userAddress = req.docManager.curUserHostAddress(userHost);
|
||||
let filePath = req.docManager.storagePath(wopi.id, userAddress);
|
||||
|
||||
if (!lockManager.hasLock(filePath)) {
|
||||
// file isn't locked => mismatch
|
||||
@ -157,8 +156,8 @@ function refreshLock(wopi, req, res, userHost) {
|
||||
function unlock(wopi, req, res, userHost) {
|
||||
let requestLock = req.headers[reqConsts.requestHeaders.Lock.toLowerCase()];
|
||||
|
||||
let userAddress = docManager.curUserHostAddress(userHost);
|
||||
let filePath = docManager.storagePath(wopi.id, userAddress);
|
||||
let userAddress = req.docManager.curUserHostAddress(userHost);
|
||||
let filePath = req.docManager.storagePath(wopi.id, userAddress);
|
||||
|
||||
if (!lockManager.hasLock(filePath)) {
|
||||
// file isn't locked => mismatch
|
||||
@ -178,8 +177,8 @@ function unlockAndRelock(wopi, req, res, userHost) {
|
||||
let requestLock = req.headers[reqConsts.requestHeaders.Lock.toLowerCase()];
|
||||
let oldLock = req.headers[reqConsts.requestHeaders.oldLock.toLowerCase()]; // get the X-WOPI-OldLock header
|
||||
|
||||
let userAddress = docManager.curUserHostAddress(userHost);
|
||||
let filePath = docManager.storagePath(wopi.id, userAddress);
|
||||
let userAddress = req.docManager.curUserHostAddress(userHost);
|
||||
let filePath = req.docManager.storagePath(wopi.id, userAddress);
|
||||
|
||||
if (!lockManager.hasLock(filePath)) {
|
||||
// file isn't locked => mismatch
|
||||
@ -196,9 +195,9 @@ function unlockAndRelock(wopi, req, res, userHost) {
|
||||
|
||||
// request a message to retrieve a file
|
||||
function getFile(wopi, req, res, userHost) {
|
||||
let userAddress = docManager.curUserHostAddress(userHost);
|
||||
let userAddress = req.docManager.curUserHostAddress(userHost);
|
||||
|
||||
let path = docManager.storagePath(wopi.id, userAddress);
|
||||
let path = req.docManager.storagePath(wopi.id, userAddress);
|
||||
|
||||
res.setHeader("Content-Length", fileSystem.statSync(path).size);
|
||||
res.setHeader("Content-Type", mime.getType(path));
|
||||
@ -213,8 +212,8 @@ function getFile(wopi, req, res, userHost) {
|
||||
function putFile(wopi, req, res, userHost) {
|
||||
let requestLock = req.headers[reqConsts.requestHeaders.Lock.toLowerCase()];
|
||||
|
||||
let userAddress = docManager.curUserHostAddress(userHost);
|
||||
let storagePath = docManager.storagePath(wopi.id, userAddress);
|
||||
let userAddress = req.docManager.curUserHostAddress(userHost);
|
||||
let storagePath = req.docManager.storagePath(wopi.id, userAddress);
|
||||
|
||||
if (!lockManager.hasLock(storagePath)) {
|
||||
// ToDo: if body length is 0 bytes => handle document creation
|
||||
@ -224,20 +223,20 @@ function putFile(wopi, req, res, userHost) {
|
||||
} else if (lockManager.getLock(storagePath) == requestLock) {
|
||||
// lock matches current lock => put file
|
||||
if (req.body) {
|
||||
var historyPath = docManager.historyPath(wopi.id, userAddress); // get the path to the file history
|
||||
var historyPath = req.docManager.historyPath(wopi.id, userAddress); // get the path to the file history
|
||||
if (historyPath == "") { // if it is empty
|
||||
historyPath = docManager.historyPath(wopi.id, userAddress, true); // create it
|
||||
docManager.createDirectory(historyPath); // and create a new directory for the history
|
||||
historyPath = req.docManager.historyPath(wopi.id, userAddress, true); // create it
|
||||
req.docManager.createDirectory(historyPath); // and create a new directory for the history
|
||||
}
|
||||
|
||||
var count_version = docManager.countVersion(historyPath); // get the last file version
|
||||
var count_version = req.docManager.countVersion(historyPath); // get the last file version
|
||||
version = count_version + 1; // get a number of a new file version
|
||||
res.setHeader(reqConsts.requestHeaders.ItemVersion, version + 1); // set the X-WOPI-ItemVersion header
|
||||
var versionPath = docManager.versionPath(wopi.id, userAddress, version); // get the path to the specified file version
|
||||
docManager.createDirectory(versionPath); // and create a new directory for the specified version
|
||||
var versionPath = req.docManager.versionPath(wopi.id, userAddress, version); // get the path to the specified file version
|
||||
req.docManager.createDirectory(versionPath); // and create a new directory for the specified version
|
||||
|
||||
var path_prev = path.join(versionPath, "prev" + fileUtility.getFileExtension(wopi.id)); // get the path to the previous file version
|
||||
fileSystem.renameSync(docManager.storagePath(wopi.id, userAddress), path_prev); // synchronously rename the given file as the previous file version
|
||||
fileSystem.renameSync(req.docManager.storagePath(wopi.id, userAddress), path_prev); // synchronously rename the given file as the previous file version
|
||||
|
||||
let filestream = fileSystem.createWriteStream(storagePath);
|
||||
req.pipe(filestream);
|
||||
@ -256,20 +255,18 @@ 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 = docManager.curUserHostAddress(userHost);
|
||||
let historyPath = docManager.historyPath(wopi.id, userAddress); // get the path to the file history
|
||||
let version = 1;
|
||||
if (historyPath != "") { // if it isn't empty
|
||||
version = docManager.countVersion(historyPath) + 1; // get a number of a new file version
|
||||
}
|
||||
let path = docManager.storagePath(wopi.id, userAddress);
|
||||
let userAddress = req.docManager.curUserHostAddress(userHost);
|
||||
let version = req.docManager.getKey(wopi.id, userAddress);
|
||||
|
||||
let user = users.getUser(req.query.userid);
|
||||
let path = req.docManager.storagePath(wopi.id, userAddress);
|
||||
// add wopi query
|
||||
var query = new URLSearchParams(wopi.accessToken);
|
||||
let user = users.getUser(query.get("userid"));
|
||||
|
||||
// create the file information object
|
||||
let fileInfo = {
|
||||
"BaseFileName": wopi.id,
|
||||
"OwnerId": docManager.getFileData(wopi.id, userAddress)[1],
|
||||
"OwnerId": req.docManager.getFileData(wopi.id, userAddress)[1],
|
||||
"Size": fileSystem.statSync(path).size,
|
||||
"UserId": user.id,
|
||||
"UserFriendlyName": user.name,
|
||||
@ -293,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
|
||||
@ -314,5 +312,5 @@ exports.fileRequestHandler = (req, res) => {
|
||||
return;
|
||||
}
|
||||
|
||||
action(wopiData, req, res);
|
||||
action(wopiData, req, res, userAddress);
|
||||
}
|
||||
56
web/documentserver-example/nodejs/helpers/wopi/wopiRouting.js
Normal file → Executable file
56
web/documentserver-example/nodejs/helpers/wopi/wopiRouting.js
Normal file → Executable file
@ -24,7 +24,6 @@ const fileUtility = require("../fileUtility");
|
||||
const config = require('config');
|
||||
const configServer = config.get('server');
|
||||
const siteUrl = configServer.get('siteUrl'); // the path to the editors installation
|
||||
const storageFolder = configServer.get("storageFolder");
|
||||
const users = require("../users");
|
||||
|
||||
exports.registerRoutes = function(app) {
|
||||
@ -32,11 +31,11 @@ exports.registerRoutes = function(app) {
|
||||
// define a handler for the default wopi page
|
||||
app.get("/wopi", async function(req, res) {
|
||||
|
||||
docManager.init(storageFolder, req, res);
|
||||
req.docManager = new docManager(req, res);
|
||||
|
||||
let absSiteUrl = siteUrl;
|
||||
if (absSiteUrl.indexOf("/") === 0) {
|
||||
absSiteUrl = docManager.getServerHost() + siteUrl;
|
||||
absSiteUrl = req.docManager.getServerHost() + siteUrl;
|
||||
|
||||
//todo: remove
|
||||
if (absSiteUrl.indexOf("example") !== -1) {
|
||||
@ -46,17 +45,25 @@ exports.registerRoutes = function(app) {
|
||||
{
|
||||
host = host.substring(0, pos);
|
||||
}
|
||||
absSiteUrl = docManager.getProtocol() + "://" + host + siteUrl;
|
||||
absSiteUrl = req.docManager.getProtocol() + "://" + host + siteUrl;
|
||||
}
|
||||
}
|
||||
|
||||
// get the wopi discovery information
|
||||
let actions = await utils.getDiscoveryInfo(absSiteUrl);
|
||||
let wopiEnable = actions.length != 0 ? true : false;
|
||||
let docsExtEdit = []; // Supported extensions for WOPI
|
||||
|
||||
actions.forEach(el => {
|
||||
if (el.name == "edit") docsExtEdit.push("."+el.ext);
|
||||
});
|
||||
|
||||
let editedExts = configServer.get('editedDocs').filter(i => docsExtEdit.includes(i)); // Checking supported extensions
|
||||
let fillExts = configServer.get("fillDocs").filter(i => docsExtEdit.includes(i));
|
||||
|
||||
try {
|
||||
// get all the stored files
|
||||
let files = docManager.getStoredFiles();
|
||||
let files = req.docManager.getStoredFiles();
|
||||
|
||||
// run through all the files and write the corresponding information to each file
|
||||
for (var file of files) {
|
||||
@ -69,9 +76,14 @@ exports.registerRoutes = function(app) {
|
||||
res.render("wopiIndex", {
|
||||
wopiEnable : wopiEnable,
|
||||
storedFiles: wopiEnable ? files : [],
|
||||
params: docManager.getCustomParams(),
|
||||
params: req.docManager.getCustomParams(),
|
||||
users: users,
|
||||
serverUrl: docManager.getServerUrl(),
|
||||
serverUrl: req.docManager.getServerUrl(),
|
||||
preloaderUrl: siteUrl + configServer.get('preloaderUrl'),
|
||||
convertExts: configServer.get('convertedDocs'),
|
||||
editedExts: editedExts,
|
||||
fillExts: fillExts,
|
||||
languages: configServer.get('languages'),
|
||||
});
|
||||
|
||||
} catch (ex) {
|
||||
@ -84,11 +96,12 @@ exports.registerRoutes = function(app) {
|
||||
// define a handler for creating a new wopi editing session
|
||||
app.get("/wopi-new", function(req, res) {
|
||||
var fileExt = req.query.fileExt; // get the file extension from the request
|
||||
var user = users.getUser(req.query.userid); // get a user by the id
|
||||
|
||||
req.docManager = new docManager(req, res);
|
||||
|
||||
if (fileExt != null) { // if the file extension exists
|
||||
var fileName = docManager.createDemo(!!req.query.sample, fileExt, user.id, user.name); // create demo document of the given extension
|
||||
var redirectPath = docManager.getServerUrl(true) + "/wopi-action/" + encodeURIComponent(fileName) + "?action=edit" + docManager.getCustomParams(); // get the redirect path
|
||||
var fileName = req.docManager.getCorrectName("new." + fileExt)
|
||||
var redirectPath = req.docManager.getServerUrl(true) + "/wopi-action/" + encodeURIComponent(fileName) + "?action=editnew" + req.docManager.getCustomParams(); // get the redirect path
|
||||
res.redirect(redirectPath);
|
||||
return;
|
||||
}
|
||||
@ -96,17 +109,25 @@ exports.registerRoutes = function(app) {
|
||||
// define a handler for getting wopi action information by its id
|
||||
app.get("/wopi-action/:id", async function(req, res) {
|
||||
try {
|
||||
docManager.init(storageFolder, req, res);
|
||||
req.docManager = new docManager(req, res);
|
||||
|
||||
var fileName = req.docManager.getCorrectName(req.params['id'])
|
||||
var fileExt = fileUtility.getFileExtension(fileName, true); // get the file extension from the request
|
||||
var user = users.getUser(req.query.userid); // get a user by the id
|
||||
|
||||
// get an action for the specified extension and name
|
||||
let action = await utils.getAction(fileUtility.getFileExtension(req.params['id'], true), req.query["action"]);
|
||||
let action = await utils.getAction(fileExt, req.query["action"]);
|
||||
|
||||
if (action != null && req.query["action"] == "editnew") {
|
||||
fileName = req.docManager.RequestEditnew(req, fileName, user);
|
||||
}
|
||||
|
||||
// render wopiAction template with the parameters specified
|
||||
res.render("wopiAction", {
|
||||
actionUrl: utils.getActionUrl(docManager.getServerUrl(true), docManager.curUserHostAddress(), action, req.params['id']),
|
||||
actionUrl: utils.getActionUrl(req.docManager.getServerUrl(true), req.docManager.curUserHostAddress(), action, req.params['id']),
|
||||
token: "test",
|
||||
tokenTtl: Date.now() + 1000 * 60 * 60 * 10,
|
||||
params: docManager.getCustomParams(),
|
||||
params: req.docManager.getCustomParams(),
|
||||
});
|
||||
|
||||
} catch (ex) {
|
||||
@ -140,4 +161,11 @@ exports.registerRoutes = function(app) {
|
||||
.all(tokenValidator.isValidToken)
|
||||
.get(filesController.fileRequestHandler)
|
||||
.post(filesController.fileRequestHandler);
|
||||
|
||||
// define a handler for upload files
|
||||
app.route('/wopi/upload')
|
||||
.all(tokenValidator.isValidToken)
|
||||
.get(filesController.fileRequestHandler)
|
||||
.post(filesController.fileRequestHandler);
|
||||
|
||||
};
|
||||
|
||||
Submodule web/documentserver-example/nodejs/public/assets updated: 589266f57f...1d601d84c4
@ -0,0 +1,3 @@
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M5 19H8.11111L8.84845 18.2627L5.73734 15.1516L5 15.8889V19ZM10.2627 16.8484L19 8.11111V6.55556H17.4444V5H15.8889L7.15155 13.7373L10.2627 16.8484Z" fill="#444444"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 316 B |
3
web/documentserver-example/nodejs/public/images/view.svg
Normal file
3
web/documentserver-example/nodejs/public/images/view.svg
Normal file
@ -0,0 +1,3 @@
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M12 6C8.17879 6 4.71351 8.10432 2.15649 11.5223C1.94784 11.8023 1.94784 12.1935 2.15649 12.4736C4.71351 15.8957 8.17879 18 12 18C15.8212 18 19.2865 15.8957 21.8435 12.4777C22.0522 12.1977 22.0522 11.8065 21.8435 11.5264C19.2865 8.10432 15.8212 6 12 6ZM12.2607 15.9919C9.84844 16.1436 7.8564 14.1554 8.00813 11.7393C8.13264 9.74729 9.74728 8.13265 11.7393 8.00815C14.1516 7.85641 16.1436 9.84456 15.9919 12.2607C15.8635 14.2488 14.2488 15.8635 12.2607 15.9919ZM12.1282 13.9959C10.9219 14.0718 9.92498 13.0783 10.0044 11.8718C10.0658 10.8747 10.8749 10.0691 11.8718 10.0041C13.0781 9.92821 14.075 10.9217 13.9956 12.1282C13.9305 13.1289 13.1215 13.9345 12.1282 13.9959Z" fill="#444444"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 838 B |
@ -198,8 +198,10 @@ if (typeof jQuery != "undefined") {
|
||||
var posExt = fileName.lastIndexOf('.');
|
||||
posExt = 0 <= posExt ? fileName.substring(posExt).trim().toLowerCase() : '';
|
||||
|
||||
if (EditedExtList.indexOf(posExt) != -1
|
||||
|| FilledExtList.indexOf(posExt) != -1) {
|
||||
var checkEdited = EditedExtList.split(",").filter(function(ext) { return ext == posExt;});
|
||||
var checkFilled = FilledExtList.split(",").filter(function(ext) { return ext == posExt;});
|
||||
|
||||
if (checkEdited != "" || checkFilled != "") {
|
||||
jq("#beginEdit").removeClass("disable");
|
||||
}
|
||||
};
|
||||
@ -223,7 +225,11 @@ if (typeof jQuery != "undefined") {
|
||||
|
||||
jq(document).on("click", "#beginEdit:not(.disable)", function () {
|
||||
var fileId = encodeURIComponent(jq('#hiddenFileName').val());
|
||||
var url = UrlEditor + "?fileName=" + fileId + "&lang=" + language + "&userid=" + userid;
|
||||
if (UrlEditor == "wopi-action"){
|
||||
var url = UrlEditor + "/" + fileId + "?action=edit";
|
||||
}else{
|
||||
var url = UrlEditor + "?fileName=" + fileId + "&lang=" + language + "&userid=" + userid;
|
||||
}
|
||||
window.open(url, "_blank");
|
||||
jq('#hiddenFileName').val("");
|
||||
jq.unblockUI();
|
||||
@ -232,7 +238,11 @@ if (typeof jQuery != "undefined") {
|
||||
|
||||
jq(document).on("click", "#beginView:not(.disable)", function () {
|
||||
var fileId = encodeURIComponent(jq('#hiddenFileName').val());
|
||||
var url = UrlEditor + "?mode=view&fileName=" + fileId + "&lang=" + language + "&userid=" + userid;
|
||||
if (UrlEditor == "wopi-action"){
|
||||
var url = UrlEditor + "/" + fileId + "?action=view";
|
||||
}else{
|
||||
var url = UrlEditor + "?mode=view&fileName=" + fileId + "&lang=" + language + "&userid=" + userid;
|
||||
}
|
||||
window.open(url, "_blank");
|
||||
jq('#hiddenFileName').val("");
|
||||
jq.unblockUI();
|
||||
|
||||
@ -87,10 +87,6 @@
|
||||
}
|
||||
|
||||
@media (max-width: 1008px) {
|
||||
#portal-info {
|
||||
width: 65vw;
|
||||
}
|
||||
|
||||
.left-panel {
|
||||
margin-left: 0;
|
||||
}
|
||||
@ -128,6 +124,10 @@
|
||||
height: 80px;
|
||||
}
|
||||
|
||||
.main {
|
||||
height: calc(100% - 128px);
|
||||
}
|
||||
|
||||
.main-panel {
|
||||
left: 0;
|
||||
padding: 48px 18px 24px;
|
||||
@ -312,6 +312,9 @@
|
||||
.tableRow td:first-child {
|
||||
max-width: 17%;
|
||||
}
|
||||
#portal-info {
|
||||
max-width: 60vw;
|
||||
}
|
||||
}
|
||||
|
||||
.downloadContentCellShift:after {
|
||||
@ -363,6 +366,10 @@
|
||||
height: 80px;
|
||||
}
|
||||
|
||||
.main {
|
||||
height: calc(100% - 128px);
|
||||
}
|
||||
|
||||
.copy {
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
@ -436,6 +443,58 @@
|
||||
display: none;
|
||||
width: 1%;
|
||||
}
|
||||
/* Mobile Upload*/
|
||||
.blockUI.blockMsg.blockPage.ui-dialog.ui-widget.ui-corner-all.ui-widget-content.ui-draggable {
|
||||
width: 344px !important;
|
||||
box-shadow: 0px 7px 15px rgba(85, 85, 85, 0.1);
|
||||
border-radius: 2px;
|
||||
top: 10% !important;
|
||||
margin-left: -172px !important;
|
||||
}
|
||||
|
||||
.ui-dialog .ui-dialog-titlebar {
|
||||
padding: 0;
|
||||
}
|
||||
.ui-dialog .ui-dialog-content {
|
||||
padding: 0 !important;
|
||||
}
|
||||
#mainProgress {
|
||||
margin: 24px 16px 0 !important;
|
||||
}
|
||||
.blockTitle {
|
||||
padding: 10px 10px 6px 16px !important;
|
||||
font-size: 14px !important;
|
||||
}
|
||||
#mainProgress .describeUpload {
|
||||
padding: 8px 0 !important;
|
||||
}
|
||||
.dialog-close {
|
||||
margin: 0 !important;
|
||||
}
|
||||
.step-descr{
|
||||
line-height: 150%;
|
||||
}
|
||||
.step {
|
||||
line-height: 160%;
|
||||
}
|
||||
.buttonsMobile{
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
.button.gray{
|
||||
margin: 0;
|
||||
}
|
||||
.button, .button:hover{
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
padding: 0 !important;
|
||||
width: 144px;
|
||||
height: 56px;
|
||||
margin-bottom: 24px !important;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 560px) and (min-width: 510px) {
|
||||
|
||||
@ -97,6 +97,10 @@ header img {
|
||||
width: 896px;
|
||||
}
|
||||
|
||||
#portal-info {
|
||||
max-width: 65vw;
|
||||
}
|
||||
|
||||
.portal-name {
|
||||
color: #FF6F3D;
|
||||
font-size: 24px;
|
||||
@ -748,12 +752,9 @@ html {
|
||||
width: 30vw;
|
||||
min-width: 200px;
|
||||
max-width: 400px;
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.user-descr > b {
|
||||
margin-left: 25px;
|
||||
}
|
||||
|
||||
.portal-descr:nth-child(3) {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
4
web/documentserver-example/nodejs/views/config.ejs
Normal file → Executable file
4
web/documentserver-example/nodejs/views/config.ejs
Normal file → Executable file
@ -24,7 +24,8 @@
|
||||
"modifyContentControl": <%- editor.modifyContentControl %>,
|
||||
"review": <%- editor.review %>,
|
||||
"reviewGroups": <%- editor.reviewGroups %>,
|
||||
"commentGroups": <%- editor.commentGroups %>
|
||||
"commentGroups": <%- editor.commentGroups %>,
|
||||
"userInfoGroups": <%- editor.userInfoGroups %>
|
||||
}
|
||||
},
|
||||
"editorConfig": {
|
||||
@ -47,7 +48,6 @@
|
||||
},
|
||||
"customization": {
|
||||
"about": true,
|
||||
"chat": true,
|
||||
"comments": true,
|
||||
"feedback": true,
|
||||
"forcesave": false,
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user