Compare commits

...

478 Commits

Author SHA1 Message Date
cb8b4d1681 fix(nodejs): replace localhost in unsupported converted file url. Fix Bug 70551 (c4d80f6b5e) 2024-10-21 14:09:42 +03:00
decb722cf9 1.11.0 2024-10-20 17:08:13 +03:00
d7d31bd6b7 fix changelog 2024-10-16 11:56:16 +03:00
e4f5f0bca7 submit not for viewer
This reverts commit 35cf2fb0b0.
2024-10-15 18:06:37 +03:00
8714cc3d69 Revert "nodejs: comment only is not for pdf"
This reverts commit 146d26c868.
2024-10-14 12:08:22 +03:00
f1c5be0401 Merge remote-tracking branch 'remotes/origin/master' into release/v8.2.0 2024-10-11 12:33:49 +03:00
d68860f025 Merge pull request 'release/v1.10.0 from release/v1.10.0 into master
Reviewed-on: https://git.onlyoffice.com/ONLYOFFICE/document-server-integration/pulls/9
2024-10-11 09:27:13 +00:00
fdd90fd851 python: fix lint 2024-10-11 12:20:12 +03:00
abb7f6e893 Merge remote-tracking branch 'remotes/origin/release/v1.10.0' into release/v8.2.0 2024-10-10 13:47:38 +03:00
89c60280ba php-laravel: lint 2024-10-10 13:40:12 +03:00
8522e08670 php-laravel: lint 2024-10-10 13:29:10 +03:00
52b792f3a2 Merge pull request 'fix(java-spring): error saving non-existent file. Fix Bug 70788' from fix-java-spring-forgotten into release/v1.10.0
Reviewed-on: https://git.onlyoffice.com/ONLYOFFICE/document-server-integration/pulls/8
2024-10-10 10:18:41 +00:00
05f7fa2b84 fix(java-spring): error saving non-existent file. Fix Bug 70788 2024-10-10 17:11:48 +07:00
06c3dc1446 Merge remote-tracking branch 'remotes/origin/release/v1.10.0' into release/v8.2.0 2024-10-08 12:54:10 +03:00
b751d44a51 Merge pull request '1.10.0-bugfix' (#5) from 1.10.0-bugfix into release/v1.10.0
Reviewed-on: https://git.onlyoffice.com/ONLYOFFICE/document-server-integration/pulls/5
2024-10-08 09:52:38 +00:00
35cf2fb0b0 submit for all modes 2024-10-07 14:54:16 +03:00
25ec76084f coauthoring/CommandService.ashx address replaced with command 2024-10-07 11:35:55 +03:00
c72218d3ae ConvertService.ashx address replaced with converter 2024-10-07 11:34:22 +03:00
17458ec5b3 fix(java-spring): сut out directUrl. Fix Bug 70571 2024-10-07 14:42:24 +07:00
c4d80f6b5e fix(nodejs): replace localhost in unsupported converted file url. Fix Bug 70551 2024-10-03 15:15:42 +07:00
50bbd86cf5 Merge branch 'release/v1.10.0' into release/v8.2.0 2024-09-30 12:52:43 +03:00
2b0b902f9c using default empty files (For Bug 70101) 2024-09-30 12:50:09 +03:00
b36bfdec4d fix(nodejs): fix maxfilesize issue on upload (Fix Bug 70516) 2024-09-27 14:25:21 +03:00
97b70cceb5 Merge branch 'release/v1.10.0' into release/v8.2.0 2024-09-24 15:07:22 +03:00
596d445439 revert empty files (For Bug 70101) 2024-09-24 15:06:16 +03:00
4943adc21a nodejs: WOPI rename 2024-09-24 14:37:32 +03:00
db3ccd7482 Revert "nodejs: filling by default if possible" (Fix Bug 70284)
This reverts commit 15e09fece2.

# Conflicts:
#	web/documentserver-example/nodejs/app.js
2024-09-24 12:06:41 +03:00
4c7ea51207 Merge remote-tracking branch 'remotes/origin/release/v1.10.0' into release/v8.2.0 2024-09-24 12:02:52 +03:00
4f8f7399bb Merge pull request 'bugfix-1.10.0' (#3) from bugfix-1.10.0 into release/v1.10.0
Reviewed-on: https://git.onlyoffice.com/ONLYOFFICE/document-server-integration/pulls/3
2024-09-24 09:02:19 +00:00
581f2aaef6 he-IL skin language 2024-09-23 10:51:25 +03:00
62f98954b4 fix(python): exclude nochanges(4) error in command service request 2024-09-20 18:10:53 +07:00
819faf84f1 fix(ruby): exclude nochanges(4) error in command service request. Fix Bug 69913 2024-09-20 18:03:38 +07:00
66cf2aca8c Merge remote-tracking branch 'remotes/origin/release/v1.10.0' into bugfix-1.10.0
# Conflicts:
#	web/documentserver-example/csharp-mvc/Scripts/jscript.js
#	web/documentserver-example/csharp/script/jscript.js
#	web/documentserver-example/python/static/js/jscript.js
2024-09-20 09:57:35 +03:00
73b727ff9f Merge pull request 'fix: add file existence check before save. Fix Bug 69948' (#2) from fix/java-check-file-exist into release/v1.10.0
Reviewed-on: https://git.onlyoffice.com/ONLYOFFICE/document-server-integration/pulls/2
2024-09-18 08:55:32 +00:00
4c8fb6b3be nodejs: getting name in wopi (Fix Bug 70092) 2024-09-18 11:53:31 +03:00
dcc5a8f56d build(java-spring): update SDK dependency. Fix Bug 69951 2024-09-18 15:38:34 +07:00
14df5fcfa0 fix: add file existence check before save 2024-09-17 14:17:00 +03:00
e2e8087800 fix(python): extension without dot in conversion script. Fix Bug 69931 2024-09-16 15:59:12 +07:00
4c6e6dc235 fix(java): not blank page goback for uid-2. Fix Bug 69945 2024-09-13 16:31:05 +07:00
cd4ff5e045 fix(php): replacing localhost in saveas file url. Fix Bug 69936 2024-09-13 14:16:58 +07:00
b9b4aeffac fix working with formats (893303c27f) (Fix Bug 70022) 2024-09-12 10:10:05 +03:00
e25b10d618 fix(csharp-mvc): extension without dot in conversion script. Fix Bug 70022 2024-09-12 14:03:49 +07:00
f00abbc9e7 fix(csharp): extension without dot in conversion script. Fix Bug 70022 2024-09-12 14:03:15 +07:00
09344f6bbb fix(ruby): replace url to public server for forgotten files (Fix Bug 69930) 2024-09-11 15:58:47 +03:00
c23e9b6a0f fix(php): replace url to public server for forgotten files 2024-09-11 15:58:05 +03:00
814ed51134 fix(python): replace url to public server for forgotten files 2024-09-11 15:58:05 +03:00
63237f52ca fix(csharp): forgotten pdf logo. Fix Bug 70023 2024-09-11 16:13:46 +07:00
8cf285c51b nodejs: separate method for getting fileName from url (Fix Bug 70092) 2024-09-10 22:36:21 +03:00
4ae4687d29 nodejs: replace unsupported symbols in file name 2024-09-10 22:36:21 +03:00
f55beaa8ac update empty files (Fix Bug 70100) 2024-09-10 18:11:50 +03:00
4be1abca19 update submodule with tiff ext 2024-09-09 09:24:36 +03:00
7eac06aa57 nodejs: fix default actions on mobile (For Bug 65920) 2024-09-06 17:25:16 +03:00
763512afc4 nodejs: fix lint (194ad60648) 2024-09-06 17:22:39 +03:00
1b0867af69 nodejs: percentage on converting (Fix Bug 69567) 2024-09-06 15:15:24 +03:00
aa42745a3a nodejs: opening history for wopi (Fix Bug 70025) 2024-09-06 14:52:14 +03:00
194ad60648 nodejs: decode filename from utf7 in "save as" process (Fix Bug 69827) 2024-09-05 18:21:13 +03:00
1e6465aef7 update templates 2024-08-26 11:06:04 +03:00
6b6fa50e49 Merge pull request #586 from ONLYOFFICE/feature/ruby-update-deps
chore(ruby): update dependencies
2024-08-05 16:53:35 +03:00
c01bcf1807 chore(ruby): update dependencies 2024-08-05 16:30:11 +03:00
7201ec4f9e tabs to changelog (efac5b9d70) 2024-08-01 13:16:07 +03:00
c46b4e16d5 fix remove favorite status (0e1a580a86) 2024-07-31 14:28:21 +03:00
8d7767e4a7 1.10.0 2024-07-25 09:50:41 +03:00
6d4484cbe5 reorder changelog 2024-07-25 09:47:58 +03:00
4f6a0d554c Merge remote-tracking branch 'remotes/origin/master' into develop 2024-07-25 09:43:50 +03:00
a3430f7aec Merge pull request #580 from ONLYOFFICE/pdf-form
PDF-forms
2024-07-24 15:01:55 +03:00
aaea7e4cb8 feat(java-spring): permission submitForm (John Smith: true) 2024-07-24 14:20:57 +03:00
5fd90b295f Merge pull request #581 from ONLYOFFICE/fix/nodejs-conversion-error
Fix/nodejs conversion error
2024-07-19 12:35:01 +03:00
9fda921107 nodejs: display error message if it is the only param in convert response 2024-07-19 13:44:41 +05:00
b55c19f886 nodejs: add tag for displaying conversion error message 2024-07-19 13:42:08 +05:00
d0b1cc9900 feat(java): creating and editing pdf instead docxf 2024-07-16 16:21:15 +07:00
16580f4a00 feat(csharp): creating and editing pdf instead docxf 2024-07-16 15:35:12 +07:00
2f4b28343c feat(csharp-mvc): creating and editing pdf instead docxf 2024-07-16 15:10:17 +07:00
0d37b7ef7c feat(java-spring): creating and editing pdf instead docxf 2024-07-15 17:41:03 +07:00
597b3dfac7 feat(php): creating and editing pdf instead docxf 2024-07-15 17:41:02 +07:00
1936274a13 feat(python): creating and editing pdf instead docxf 2024-07-15 17:41:02 +07:00
b7837f8dcb feat(ruby): creating and editing pdf instead docxf 2024-07-15 17:40:31 +07:00
e088efe744 fix link in readme 2024-07-02 11:02:08 +03:00
f3a56acae9 reorder changelog 2024-07-02 10:41:07 +03:00
b937d304d7 nodejs: form type is pdf 2024-07-02 10:39:15 +03:00
4fb7062b95 Merge remote-tracking branch 'remotes/origin/hotfix/v8.1.1' into develop
# Conflicts:
#	web/documentserver-example/nodejs/app.js
2024-07-02 10:27:41 +03:00
b36388124d Merge pull request #579 from ONLYOFFICE/release/v1.9.0
Release/1.9.0
2024-07-02 10:20:10 +03:00
2c6c5e3a1f nodejs: saving deleted file (Fix Bug 68926) 2024-07-01 12:46:30 +03:00
ed3aa3485e nodejs: search referenceData for current user 2024-06-24 14:06:02 +03:00
6f12493e59 nodejs: check path in referenceData at first 2024-06-24 13:58:12 +03:00
22f98fda0f nodejs: search referenceData for current user 2024-06-24 13:52:00 +03:00
b91772e7d4 Merge remote-tracking branch 'remotes/origin/release/v1.9.0' into develop 2024-06-24 12:34:59 +03:00
052f73e47f nodejs: formats v2.0.0 2024-06-24 12:32:45 +03:00
55b062d64a Merge remote-tracking branch 'remotes/origin/release/v1.9.0' into develop 2024-06-20 13:26:36 +03:00
b06c872a4c Merge pull request #578 from ONLYOFFICE/fix/python-linter
update and fixate flake8 version in python example
2024-06-20 13:23:45 +03:00
ce846f489b build(python): update and fixate flake8 version 2024-06-20 13:20:27 +03:00
7a5fdc9821 Merge pull request #542 from ONLYOFFICE/fix/compose-prod ( Fix Bug 68727 )
Fix/compose prod
2024-06-20 11:36:46 +03:00
fe50a6f1ab fix(python): starting server on localhost in prod container 2024-06-20 11:34:47 +03:00
8268b633c7 fix(ruby): installing dev dependencies in prod container 2024-06-20 11:34:46 +03:00
5974a62fd2 Merge pull request #570 from ONLYOFFICE/feature/mobile-design
Feature/mobile design
2024-06-18 09:00:46 +03:00
56540846f1 Merge pull request #577 from ONLYOFFICE/fix/lint-ruby-workflow
fix(ruby): bundle install in linter workflow
2024-06-18 09:00:26 +03:00
54210428ef fix(ruby): bundle install in linter workflow 2024-06-17 14:11:20 +07:00
458920771c Merge remote-tracking branch 'remotes/origin/develop' into feature/mobile-design 2024-06-14 13:39:30 +03:00
dd189175a1 Merge remote-tracking branch 'remotes/origin/release/v1.9.0' into develop 2024-06-14 13:38:57 +03:00
93c723eb47 nodejs: fix lint 2024-06-14 13:37:33 +03:00
d564e78b2c Merge remote-tracking branch 'remotes/origin/develop' into feature/mobile-design 2024-06-14 13:31:31 +03:00
27c01046af Merge pull request #576 from ONLYOFFICE/fix/csharp-mvc-missing-formats
fix(csharp-mvc): add missing formats js file to scripts bundle
2024-06-14 13:30:37 +03:00
aa7b6aae8b fix(csharp-mvc): add missing formats js file to scripts bundle 2024-06-14 14:50:24 +05:00
be58fa39b2 Merge pull request #575 from ONLYOFFICE/fix/ruby-linter
ruby lint fix
2024-06-14 11:15:43 +03:00
6c827aa8bc Merge pull request #574 from ONLYOFFICE/feature/ruby-gemfile-update
ruby gemfile update
2024-06-14 11:10:51 +03:00
da1111a867 Merge remote-tracking branch 'remotes/origin/release/v1.9.0' into develop 2024-06-14 11:04:40 +03:00
8cc0580310 nodejs: fix comment collumn (146d26c868) 2024-06-14 11:03:58 +03:00
d4b82453d2 fix(ruby): call super without arguments when signature is identical 2024-06-13 17:48:08 +07:00
3420b20c2f build(ruby): update some dependencies 2024-06-13 17:28:21 +07:00
cfe6db3fd4 Merge remote-tracking branch 'remotes/origin/release/v1.9.0' into develop 2024-06-07 12:18:37 +03:00
8c44f4a653 nodejs: switch back templates branch 2024-06-07 12:18:01 +03:00
0561a1068c Merge remote-tracking branch 'remotes/origin/release/v1.9.0' into develop
# Conflicts:
#	CHANGELOG.md
2024-06-07 09:46:26 +03:00
2308abaf80 Merge branch 'feature/editnew-from-wopi-discovery-pdf' into develop 2024-06-07 08:50:45 +03:00
95e7aff092 Merge remote-tracking branch 'remotes/origin/release/v8.1.0' into develop
# Conflicts:
#	CHANGELOG.md
#	web/documentserver-example/java-spring/src/main/resources/application.properties
#	web/documentserver-example/nodejs/app.js
#	web/documentserver-example/nodejs/views/wopiIndex.ejs
2024-06-07 08:49:20 +03:00
88220ddf7c nodejs: upade pdf icon (Fix Bug 68355) 2024-06-05 10:01:03 +03:00
cfd010cc99 sr-Cyrl-RS skin language 2024-05-27 13:22:33 +03:00
e933e918dd Merge pull request #571 from ONLYOFFICE/fix/php-check-fileid
fix(php): check if fileid parameter is present and not empty
2024-05-22 14:16:57 +03:00
3d11876f59 fix(php): check if fileid parameter is present and not empty 2024-05-21 17:55:01 +05:00
259c121707 feat(csharp): implement design for mobile devices 2024-05-21 13:11:01 +05:00
083de6993c feat(csharp-mvc): implement design for mobile devices 2024-05-21 13:10:30 +05:00
b162076378 feat(java-spring): implement design for mobile devices 2024-05-20 19:13:47 +05:00
a37fee7192 feat(java): implement design for mobile devices 2024-05-20 19:09:26 +05:00
96bc425eb5 feat(ruby): implement design for mobile devices 2024-05-20 19:07:00 +05:00
9054e4919d feat(python): implement design for mobile devices 2024-05-20 19:05:42 +05:00
e573bb4cc4 feat(php): implement design for mobile devices 2024-05-20 19:04:18 +05:00
f568f7ae18 feat(nodejs): implement design for mobile devices 2024-05-20 19:01:26 +05:00
efac5b9d70 Merge pull request #561 from ONLYOFFICE/feature/forgotten-page
Feature/forgotten page
2024-05-15 12:52:47 +03:00
9f20706205 forgotten to changelog 2024-05-15 12:48:30 +03:00
f48734b235 nodejs: disable forgotten by default 2024-05-15 12:46:21 +03:00
3b4b1b3684 Merge pull request #568 from ONLYOFFICE/fix/java-spring-filename-check
fix(java-spring): check for null value first
2024-05-14 15:29:07 +03:00
0280503110 fix(java-spring): check for null value first 2024-05-14 15:58:48 +05:00
057d15e00d Merge pull request #563 from ONLYOFFICE/fix/zip-upload
fix(nodejs): uploading only files with actions. Fix Bug 67497
2024-05-14 13:43:48 +03:00
9a22cd66d9 refactor(java-spring): use sdk for fetching and deleting forgotten files 2024-05-14 14:10:14 +05:00
67137ad6e1 fix(nodejs): ignore zip from saveAs 2024-05-14 15:38:48 +07:00
1d3ae82f1c Merge branch 'develop' into feature/forgotten-page 2024-05-14 13:11:13 +05:00
a512a0ed26 Merge pull request #566 from ONLYOFFICE/docs/java-spring-license
docs(java-spring): update 3rd-Party.license file
2024-05-13 14:38:38 +03:00
27a9817f46 update license file 2024-05-13 14:35:12 +03:00
354b500077 Merge branch 'develop' into feature/forgotten-page 2024-05-13 14:02:51 +05:00
7852934047 docs(java-spring): update 3rd-Party.license file 2024-05-08 15:39:57 +03:00
06482fa72c Merge pull request #555 from ONLYOFFICE/feature/editnew-from-wopi-discovery
Creating only files with editnew in wopi discovery
2024-05-08 12:00:04 +03:00
9efc5237aa nodejs: fix creation pdf in wopi 2024-05-08 11:56:04 +03:00
4fa2bb8459 Merge remote-tracking branch 'remotes/origin/develop' into feature/editnew-from-wopi-discovery 2024-05-08 11:45:27 +03:00
38581960f3 Merge pull request #564 from ONLYOFFICE/fix/makefile-compose-migration
makefile docker compose V2 migration. Fix Bug 67214
2024-05-08 11:43:18 +03:00
43bdef50a1 java-spring: using sdk to changelog 2024-05-08 11:03:47 +03:00
4c71114177 nodejs: revert formats (fix 729065fed0) 2024-05-08 11:03:35 +03:00
5eb6171954 Merge pull request #557 from ONLYOFFICE/feature/docs-integration-sdk
Feature/docs integration sdk
2024-05-08 10:45:01 +03:00
26782137e7 csharp: remove unnecessary angel bracket 2024-05-02 13:52:49 +05:00
8680ed5970 php: catch and log commandrequest errors 2024-04-25 20:03:28 +05:00
af39abbf00 php: throw exception if there is connection error or command service returns error code other than 0 2024-04-25 20:01:16 +05:00
dec31c2f59 python: log error 2024-04-25 19:40:48 +05:00
9ae6252e53 feat(python): raise error if command service returns error code other than 0 2024-04-25 19:37:27 +05:00
3c84ab6633 makefile docker compose V2 migration. Fix Bug 67214 2024-04-25 15:11:39 +07:00
7cffe4cee9 fix(nodejs): uploading only files with actions. Fix Bug 67497 2024-04-24 18:04:24 +07:00
107459cf19 en-GB skin language 2024-04-24 13:22:57 +03:00
a9b63ef903 build(nodejs): bump formidable from 1.2.2 to 3.2.4 2024-04-24 15:24:06 +07:00
e863fd60f4 fix(ruby): show empty table in forgotten files page if error occurs 2024-04-23 23:33:45 +05:00
172a501247 feat(ruby): raise error if command service returns error code other than 0 2024-04-23 23:30:27 +05:00
e487a89203 fix(csharp-mvc): show empty table in forgotten files page if error occurs 2024-04-23 18:03:23 +05:00
aeb2394b39 feat(csharp-mvc): control access to forgotten page using config variable 2024-04-23 17:55:22 +05:00
5c804c1e1e feat(csharp-mvc): display message in error template 2024-04-23 17:54:27 +05:00
6b319f1dc1 fix(csharp): show empty table in forgotten files page if error occurs 2024-04-23 17:47:47 +05:00
4a029f8f40 feat(csharp): control access to forgotten page using config variable 2024-04-23 17:42:49 +05:00
030cf91c65 fix(nodejs): show empty forgotten files list if error occurs 2024-04-23 00:02:55 +05:00
c60d2236d5 fix: linter offences 2024-04-22 23:30:24 +05:00
0a181bd04e feat(java-spring): control access to forgotten page using config variable 2024-04-22 23:24:56 +05:00
3fc658b0f8 feat(java): control access to forgotten page using config variable 2024-04-22 22:52:06 +05:00
403c2e2d8c feat(ruby): control access to forgotten page using config variable 2024-04-22 18:11:00 +05:00
beb831173d feat(python): control access to forgotten page using config variable 2024-04-22 17:30:09 +05:00
06a8668107 feat(php): control access to forgotten page using config variable 2024-04-22 16:40:32 +05:00
a722b142bb feat(nodejs): control access to forgotten page using config variable 2024-04-22 15:47:58 +05:00
39a61835ea fix main panel overflow in forgotten page 2024-04-22 13:44:13 +05:00
df3e018e3c fix link on logo 2024-04-22 12:37:03 +05:00
0f32feb1b9 csharp-mvc: fix link on logo 2024-04-19 13:47:05 +03:00
d61ebb27ae csharp-mvc: include files to project 2024-04-19 13:46:15 +03:00
e86118a56f csharp: fix link on logo 2024-04-19 13:43:45 +03:00
096edcfa66 csharp: include files to project 2024-04-19 13:43:15 +03:00
c5c1196a6f nodejs: copyright 2024 2024-04-19 13:24:29 +03:00
844e723387 save as for pdf 2024-04-19 12:29:47 +03:00
57087f0465 fix(nodejs): type confusion through parameter tampering 2024-04-17 22:23:22 +05:00
86339c8ea6 fix(php): fix linter offences 2024-04-17 18:33:16 +05:00
528cc5538e refactor(php): handle commandrequest failure 2024-04-17 18:31:35 +05:00
2880604546 fix(nodejs): fix linter offences 2024-04-17 18:06:41 +05:00
61d7a8003f refactor(nodejs): return correct response statuses 2024-04-17 18:04:29 +05:00
9e52d6d8b1 fix(nodejs): fix responsive design issues 2024-04-17 18:00:03 +05:00
6565fd2178 refactor(nodejs): rewrite delete event using dom and fetch and place it in separate file 2024-04-17 17:52:39 +05:00
f12fc29a57 feature(nodejs): add links to navbar 2024-04-17 17:44:55 +05:00
cd465a633e fix: responsive header image in forgotten files page 2024-04-17 16:36:28 +05:00
5fc22799e1 fix: fix table content overflow 2024-04-17 16:31:04 +05:00
59057a5905 feature(csharp-mvc): add navbar 2024-04-17 13:33:26 +05:00
8be3cfd66a feature(csharp): add navbar 2024-04-17 13:29:38 +05:00
b1167516d4 feature(csharp-mvc): forgotten files page 2024-04-17 13:24:01 +05:00
2f2ef0e65f feature(csharp): forgotten files page 2024-04-17 13:14:40 +05:00
33aba9a404 feature(java-spring): add navbar 2024-04-16 23:32:32 +05:00
82003763fa feature(java): add navbar 2024-04-16 23:19:34 +05:00
ea41130297 feature(ruby): add navbar 2024-04-16 22:57:49 +05:00
f909c31250 feature(python): add navbar 2024-04-16 22:45:39 +05:00
352b4c0ded feature(php): add navbar 2024-04-16 22:32:16 +05:00
7ec588280b feature(java-spring): forgotten files page 2024-04-16 19:15:30 +05:00
d43e4a98df feature(java): forgotten files page 2024-04-16 17:21:27 +05:00
461122a052 feature(ruby): forgotten files page 2024-04-16 13:31:54 +05:00
d1a1127b63 feature(python): forgotten files page 2024-04-16 13:02:55 +05:00
4263175871 refactor(python): return response in commandrequest method 2024-04-16 12:52:58 +05:00
98b93b3bc5 feature(php): forgotten files page 2024-04-16 00:38:07 +05:00
e32438218f refactor(java-spring): return response in commandrequest method 2024-04-15 19:11:10 +05:00
613d5e30a9 refactor(java): return response in commandrequest method 2024-04-15 19:09:55 +05:00
ccaf607cef refactor(csharp-mvc): return response in commandrequest method 2024-04-15 19:08:55 +05:00
837e63f372 refactor(csharp): return response in commandrequest method 2024-04-15 19:07:30 +05:00
a2a4c2b32f Merge branch 'develop' into feature/forgotten-page 2024-04-15 18:45:39 +05:00
e89eee7e28 Merge pull request #560 from ONLYOFFICE/bump-some-gems
build(ruby): bump gem versions as directed by dependabot
2024-04-09 11:20:35 +03:00
6a4b79fb54 build(ruby): bump gem versions as directed by dependabot 2024-04-05 17:39:48 +07:00
b1dd965590 Merge pull request #559 from ONLYOFFICE/fix/nodejs-dependencies-overrides
build(nodejs): add overrides in package.json
2024-04-05 10:25:35 +03:00
208bf086d8 Merge pull request #558 from ONLYOFFICE/feature/nodejs-navbar-update
feature/nodejs navbar update
2024-04-05 10:18:19 +03:00
ebb1179190 build(nodejs): add overrides in package.json 2024-04-04 17:32:09 +07:00
3375315cc0 feature(nodejs): show navigation bar at top even if there are no files in user directory 2024-04-04 13:08:47 +05:00
2bed0f0bb7 build: delete com.inversoft:prime-jwt dependency 2024-04-03 15:44:53 +03:00
3570f189a0 build: ossrh snapshot repository 2024-04-03 15:17:16 +03:00
afd5a88b1d Merge remote-tracking branch 'remotes/origin/develop' into feature/docs-integration-sdk
# Conflicts:
#	web/documentserver-example/java-spring/src/main/java/com/onlyoffice/integration/controllers/IndexController.java
2024-04-03 15:16:19 +03:00
a070b6e82b nodejs: rename back (eda1876f59) 2024-04-03 14:27:57 +03:00
43d260cd7a Merge pull request #534 from ONLYOFFICE/feature/nodejs-forced-conversion
Feature/nodejs forced conversion
2024-04-03 14:05:24 +03:00
14bb9fc8a4 Merge pull request #556 from ONLYOFFICE/fix/wopi-mobile-default-action
fix(nodejs): mobileEdit default action for mobile wopi page. Fix Bug 65920
2024-04-03 13:07:02 +03:00
57ca15153f Merge pull request #551 from ONLYOFFICE/feature/fetching-formats
Feature/fetching formats
2024-04-03 12:31:53 +03:00
bbde4dc87b Merge pull request #525 from ONLYOFFICE/nodejs-update-dependencies
build(nodejs): updated dependencies
2024-04-03 12:19:33 +03:00
a0ce620f84 build: use com.onlyoffice:docs-integration-sdk from maven 2024-04-02 16:36:50 +03:00
5b46195f72 fix(nodejs): mobileEdit default action for mobile wopi page. Fix Bug 65920 2024-04-02 12:55:33 +07:00
81c94c9fbd refactor(nodejs): load formats script and remove redundant variables 2024-04-01 12:24:14 +05:00
cc3c640868 refactor: merge format and format-manager files into formats file 2024-04-01 12:21:18 +05:00
e3c82eed09 feat(nodejs): creating only files with editnew in wopi discovery 2024-04-01 12:10:26 +07:00
1df3c046ee docs: license 2024 2024-03-29 10:27:50 +03:00
1f2623dc07 refactor: settings for connect doc-server to application.properties 2024-03-29 10:19:39 +03:00
317018df5b fix: convert file after upload 2024-03-29 09:54:19 +03:00
729065fed0 Merge branch 'develop' into feature/docs-integration-sdk
# Conflicts:
#	web/documentserver-example/java-spring/src/main/java/com/onlyoffice/integration/controllers/FileController.java
#	web/documentserver-example/java-spring/src/main/java/com/onlyoffice/integration/documentserver/callbacks/Callback.java
#	web/documentserver-example/java-spring/src/main/java/com/onlyoffice/integration/documentserver/callbacks/CallbackHandler.java
#	web/documentserver-example/java-spring/src/main/java/com/onlyoffice/integration/documentserver/callbacks/Status.java
#	web/documentserver-example/java-spring/src/main/java/com/onlyoffice/integration/documentserver/callbacks/implementations/EditCallback.java
#	web/documentserver-example/java-spring/src/main/java/com/onlyoffice/integration/documentserver/callbacks/implementations/ForcesaveCallback.java
#	web/documentserver-example/java-spring/src/main/java/com/onlyoffice/integration/documentserver/callbacks/implementations/SaveCallback.java
#	web/documentserver-example/java-spring/src/main/java/com/onlyoffice/integration/documentserver/managers/document/DefaultDocumentManager.java
#	web/documentserver-example/java-spring/src/main/java/com/onlyoffice/integration/documentserver/managers/document/DocumentManager.java
#	web/documentserver-example/java-spring/src/main/java/com/onlyoffice/integration/documentserver/managers/jwt/DefaultJwtManager.java
#	web/documentserver-example/java-spring/src/main/java/com/onlyoffice/integration/documentserver/managers/jwt/JwtManager.java
#	web/documentserver-example/java-spring/src/main/java/com/onlyoffice/integration/documentserver/managers/template/SampleTemplateManager.java
#	web/documentserver-example/java-spring/src/main/java/com/onlyoffice/integration/documentserver/managers/template/TemplateManager.java
#	web/documentserver-example/java-spring/src/main/java/com/onlyoffice/integration/documentserver/models/AbstractModel.java
#	web/documentserver-example/java-spring/src/main/java/com/onlyoffice/integration/documentserver/models/Format.java
#	web/documentserver-example/java-spring/src/main/java/com/onlyoffice/integration/documentserver/models/configurations/Customization.java
#	web/documentserver-example/java-spring/src/main/java/com/onlyoffice/integration/documentserver/models/configurations/Embedded.java
#	web/documentserver-example/java-spring/src/main/java/com/onlyoffice/integration/documentserver/models/configurations/Goback.java
#	web/documentserver-example/java-spring/src/main/java/com/onlyoffice/integration/documentserver/models/configurations/Info.java
#	web/documentserver-example/java-spring/src/main/java/com/onlyoffice/integration/documentserver/models/enums/ConvertErrorType.java
#	web/documentserver-example/java-spring/src/main/java/com/onlyoffice/integration/documentserver/models/enums/Mode.java
#	web/documentserver-example/java-spring/src/main/java/com/onlyoffice/integration/documentserver/models/enums/ToolbarDocked.java
#	web/documentserver-example/java-spring/src/main/java/com/onlyoffice/integration/documentserver/models/enums/Type.java
#	web/documentserver-example/java-spring/src/main/java/com/onlyoffice/integration/documentserver/models/filemodel/CommentGroup.java
#	web/documentserver-example/java-spring/src/main/java/com/onlyoffice/integration/documentserver/models/filemodel/Document.java
#	web/documentserver-example/java-spring/src/main/java/com/onlyoffice/integration/documentserver/models/filemodel/EditorConfig.java
#	web/documentserver-example/java-spring/src/main/java/com/onlyoffice/integration/documentserver/models/filemodel/FileModel.java
#	web/documentserver-example/java-spring/src/main/java/com/onlyoffice/integration/documentserver/models/filemodel/Permission.java
#	web/documentserver-example/java-spring/src/main/java/com/onlyoffice/integration/documentserver/models/filemodel/ReferenceData.java
#	web/documentserver-example/java-spring/src/main/java/com/onlyoffice/integration/documentserver/models/filemodel/Template.java
#	web/documentserver-example/java-spring/src/main/java/com/onlyoffice/integration/documentserver/models/filemodel/User.java
#	web/documentserver-example/java-spring/src/main/java/com/onlyoffice/integration/documentserver/util/SSLUtils.java
#	web/documentserver-example/java-spring/src/main/java/com/onlyoffice/integration/documentserver/util/file/DefaultFileUtility.java
#	web/documentserver-example/java-spring/src/main/java/com/onlyoffice/integration/documentserver/util/file/FileUtility.java
#	web/documentserver-example/java-spring/src/main/java/com/onlyoffice/integration/documentserver/util/service/DefaultFormatService.java
#	web/documentserver-example/java-spring/src/main/java/com/onlyoffice/integration/documentserver/util/service/DefaultServiceConverter.java
#	web/documentserver-example/java-spring/src/main/java/com/onlyoffice/integration/documentserver/util/service/ServiceConverter.java
#	web/documentserver-example/java-spring/src/main/java/com/onlyoffice/integration/dto/Action.java
#	web/documentserver-example/java-spring/src/main/java/com/onlyoffice/integration/dto/ChangesHistory.java
#	web/documentserver-example/java-spring/src/main/java/com/onlyoffice/integration/dto/ChangesUser.java
#	web/documentserver-example/java-spring/src/main/java/com/onlyoffice/integration/dto/Convert.java
#	web/documentserver-example/java-spring/src/main/java/com/onlyoffice/integration/dto/ConvertedData.java
#	web/documentserver-example/java-spring/src/main/java/com/onlyoffice/integration/dto/History.java
#	web/documentserver-example/java-spring/src/main/java/com/onlyoffice/integration/dto/ReferenceData.java
#	web/documentserver-example/java-spring/src/main/java/com/onlyoffice/integration/dto/Track.java
#	web/documentserver-example/java-spring/src/main/java/com/onlyoffice/integration/mappers/AbstractMapper.java
#	web/documentserver-example/java-spring/src/main/java/com/onlyoffice/integration/mappers/Mapper.java
#	web/documentserver-example/java-spring/src/main/java/com/onlyoffice/integration/mappers/PermissionsMapper.java
#	web/documentserver-example/java-spring/src/main/java/com/onlyoffice/integration/mappers/UsersMapper.java
#	web/documentserver-example/java-spring/src/main/java/com/onlyoffice/integration/services/configurers/Configurer.java
#	web/documentserver-example/java-spring/src/main/java/com/onlyoffice/integration/services/configurers/CustomizationConfigurer.java
#	web/documentserver-example/java-spring/src/main/java/com/onlyoffice/integration/services/configurers/DocumentConfigurer.java
#	web/documentserver-example/java-spring/src/main/java/com/onlyoffice/integration/services/configurers/EditorConfigConfigurer.java
#	web/documentserver-example/java-spring/src/main/java/com/onlyoffice/integration/services/configurers/EmbeddedConfigurer.java
#	web/documentserver-example/java-spring/src/main/java/com/onlyoffice/integration/services/configurers/FileConfigurer.java
#	web/documentserver-example/java-spring/src/main/java/com/onlyoffice/integration/services/configurers/implementations/DefaultCustomizationConfigurer.java
#	web/documentserver-example/java-spring/src/main/java/com/onlyoffice/integration/services/configurers/implementations/DefaultDocumentConfigurer.java
#	web/documentserver-example/java-spring/src/main/java/com/onlyoffice/integration/services/configurers/implementations/DefaultEditorConfigConfigurer.java
#	web/documentserver-example/java-spring/src/main/java/com/onlyoffice/integration/services/configurers/implementations/DefaultEmbeddedConfigurer.java
#	web/documentserver-example/java-spring/src/main/java/com/onlyoffice/integration/services/configurers/implementations/DefaultFileConfigurer.java
#	web/documentserver-example/java-spring/src/main/java/com/onlyoffice/integration/services/configurers/wrappers/DefaultDocumentWrapper.java
#	web/documentserver-example/java-spring/src/main/java/com/onlyoffice/integration/services/configurers/wrappers/DefaultEmbeddedWrapper.java
#	web/documentserver-example/java-spring/src/main/java/com/onlyoffice/integration/services/configurers/wrappers/DefaultFileWrapper.java
#	web/documentserver-example/java-spring/src/main/resources/assets/document-formats
2024-03-28 17:17:16 +03:00
248595472d build: docs-integration-sdk-1.1.3-SNAPSHOT.jar 2024-03-28 15:19:18 +03:00
ead7e8de06 fix: condition upload file 2024-03-28 15:18:43 +03:00
20e6664a6b nodejs: absolute url in request to discovery (1e72167e7d)
Revert "nodejs: absolute host is not needed with urllib" (2460f2c7ac)
2024-03-28 13:35:50 +03:00
61af52a534 nodejs: fix favicon on wopi action 2024-03-28 10:53:12 +03:00
6236f90a50 Merge pull request #554 from ONLYOFFICE/feature/for-bug-59054
Feature/for bug 59054
2024-03-27 13:00:27 +03:00
5118352714 nodejs: debug mobile editors opening (Fix Bug 59054) 2024-03-27 12:57:58 +03:00
aa5a660001 nodejs: fix wopi editor size (Fix Bug 59054) 2024-03-27 12:57:52 +03:00
bf1f987333 nodejs: wopi refactoring 2024-03-27 12:56:08 +03:00
f1f834fb0c refactor: create and use new method for finding formats by extension 2024-03-26 17:57:52 +05:00
53c3e97b5c fix(nodejs): linter offence 2024-03-25 14:25:03 +05:00
eda1876f59 refactor(nodejs): rename convext variable and remove redundant internalext variable 2024-03-25 14:18:55 +05:00
64eab6c4a2 refactor(nodejs): add flag for keeping original file and replace conditional expression with it 2024-03-25 14:09:36 +05:00
acb9a0e4c9 refactor(java-spring): add formatslist dto object and replace jsonobject with it 2024-03-25 12:51:13 +05:00
909f638a92 Merge pull request #552 from ONLYOFFICE/fix/nodejs-wopi-putfile
fix(nodejs): handle document creation in putFile. Fix Bug 66817
2024-03-22 10:02:57 +03:00
6d28e3f8d8 Merge branch 'release/v8.1.0' into develop
# Conflicts:
#	CHANGELOG.md
2024-03-21 14:23:41 +03:00
12ad0d9e7e fix(nodejs): handle document creation in putFile. Fix Bug 66817 2024-03-21 17:18:58 +07:00
f3b35a878c refactor(java-spring): move formats method to indexcontroller and change return type to responseentity 2024-03-21 13:23:31 +05:00
c712f596e1 Merge remote-tracking branch 'remotes/origin/release/v8.1.0' into develop
# Conflicts:
#	CHANGELOG.md
2024-03-20 12:52:55 +03:00
7d2eb086ce Merge pull request #545 from ONLYOFFICE/feature/delete-all-files
Feature/delete all files
2024-03-20 11:01:40 +03:00
0a61708f67 Merge remote-tracking branch 'remotes/origin/develop' into feature/delete-all-files
# Conflicts:
#	CHANGELOG.md
2024-03-20 10:58:41 +03:00
389198aec6 Merge pull request #544 from ONLYOFFICE/feature/auto-conversion-error
Feature/auto conversion error
2024-03-20 10:02:53 +03:00
0d302ee8f6 nodejs: error message when error:1 2024-03-19 18:06:43 +03:00
d3a548bf3f fix(ruby): conversion error code to integer 2024-03-19 17:19:48 +07:00
fadae60e89 fix: linter offenses 2024-03-19 13:43:17 +05:00
426b15b8f1 Merge remote-tracking branch 'origin/develop' into feature/fetching-formats 2024-03-19 13:01:48 +05:00
601146c847 refactor(nodejs): change formats retrieval method on frontend 2024-03-19 12:59:54 +05:00
c4980c19e7 Revert "docxf and oform since v7.0"
This reverts commit beb9885b03.

# Conflicts:
#	web/documentserver-example/php/doceditor.php
2024-03-18 18:24:47 +03:00
0bfb036be6 refactor(csharp-mvc): change formats retrieval method on frontend 2024-03-18 18:03:10 +05:00
88b36049d2 refactor(csharp): change formats retrieval method on frontend 2024-03-18 18:02:29 +05:00
f1a1ec15ad Merge branch 'release/v8.1.0' into develop
# Conflicts:
#	CHANGELOG.md
#	web/documentserver-example/nodejs/app.js
#	web/documentserver-example/nodejs/helpers/users.js
2024-03-18 14:38:55 +03:00
683f1d33c4 nodejs: close editor 2024-03-18 14:30:25 +03:00
e8c98ba12a nodejs: format max length 2024-03-18 14:28:30 +03:00
e389cf41b8 fix(ruby): linter offence 2024-03-18 16:27:59 +05:00
80291baa40 goback: change state for users (408d80fff6) 2024-03-18 14:21:12 +03:00
b9113f93f6 fix: linter offenses 2024-03-18 16:03:00 +05:00
af778a8636 fix(ruby): linter offenses 2024-03-18 15:26:22 +05:00
47f4f022aa Merge remote-tracking branch 'remotes/origin/develop' into feature/delete-all-files
# Conflicts:
#	CHANGELOG.md
2024-03-15 16:48:58 +03:00
b2202111ac fix changelog 2024-03-15 16:47:29 +03:00
1da215b1eb Merge remote-tracking branch 'remotes/origin/develop' into feature/auto-conversion-error
# Conflicts:
#	CHANGELOG.md
2024-03-15 16:46:37 +03:00
8c8d14b48c refactor(java-spring): change formats retrieval method on frontend 2024-03-15 15:50:14 +05:00
5217a64e83 refactor(java): change formats retrieval method on frontend 2024-03-15 15:38:14 +05:00
456789191d build(nodejs): returned some dependencies versions with breaking changes 2024-03-15 17:33:00 +07:00
e1e9efa305 refactor(ruby): change formats retrieval method on frontend 2024-03-15 15:29:58 +05:00
a3016f3f96 Merge remote-tracking branch 'remotes/origin/master' into develop 2024-03-15 13:18:37 +03:00
cee60a340a nodejs: code alert 177 (e85cb5137b) 2024-03-15 12:55:59 +03:00
6c09b3f62a nodejs: wopi formsubmit icon 2024-03-15 11:18:45 +03:00
4b7ba35f83 nodejs: send email and image for protect request 2024-03-15 11:06:48 +03:00
abab30176f refactor(python): change formats retrieval method on frontend 2024-03-14 19:11:37 +05:00
1abcf78b85 refactor(php): change formats retrieval method on frontend 2024-03-14 19:08:12 +05:00
a952858ab8 Merge remote-tracking branch 'remotes/origin/release/1.8.0' into develop 2024-03-14 15:07:47 +03:00
5258fd0674 feat(csharp-mvc): handling auto-conversion error(-9) 2024-03-13 15:39:42 +05:00
ca274bc465 feat(csharp): handling auto-conversion error(-9) 2024-03-13 15:39:07 +05:00
b1d66e16a5 feat(java-spring): handling auto-conversion error(-9) 2024-03-13 15:38:24 +05:00
359cda0f67 feat(java): handling auto-conversion error(-9) 2024-03-13 15:37:13 +05:00
24a3441b1e feat(ruby): handling auto-conversion error(-9) 2024-03-13 15:36:13 +05:00
a7fca1a53b feat(python): handling auto-conversion error(-9) 2024-03-13 15:35:06 +05:00
5b6a2ba318 refactor(csharp): remove console.log 2024-03-13 13:44:47 +05:00
bb4aed6efb fix(python): uncontrolled data used in path expression 2024-03-13 13:38:53 +05:00
01d8c0acde Merge remote-tracking branch 'remotes/origin/release/1.8.0' into develop
# Conflicts:
#	web/documentserver-example/ruby/Gemfile.lock
2024-03-12 11:22:07 +03:00
31cf6ca486 Merge pull request #529 from ONLYOFFICE/fix/ruby-gemfile-lock
build(ruby): updated gemfile.lock to 0 vulnerabilities
2024-03-12 11:20:10 +03:00
fbe24234d2 refactor(python): create method for deleting user folder and call it inside remove http method 2024-03-12 12:15:22 +05:00
ac894171fb changelog: delete all files 2024-03-12 11:23:53 +05:00
0f000c1457 Merge remote-tracking branch 'remotes/origin/release/1.8.0' into develop 2024-03-11 13:28:12 +03:00
1699dc22b5 nodejs: fix rename var (9048082cb7) 2024-03-09 16:54:56 +03:00
cc62ff8a61 Merge pull request #531 from ONLYOFFICE/feature/php-forced-conversion
Feature/php forced conversion
2024-03-07 15:59:54 +03:00
fd21292dbd refactor(nodejs): change parameter name and remove redundant checking 2024-03-07 16:24:51 +05:00
d43294bd8a feat(csharp-mvc): implement delete all files method 2024-03-07 15:56:02 +05:00
81f5bdd528 feat(csharp): implement delete all files method 2024-03-07 15:42:23 +05:00
c1da8e14c3 feat(java-spring): implement delete all files method 2024-03-06 14:41:29 +05:00
767b5588ab feat(java): implement delete all files method 2024-03-06 14:27:21 +05:00
8858c3c256 feat(ruby): implement delete all files method 2024-03-06 14:24:52 +05:00
89f1c18d06 feat(python): implement delete all files method 2024-03-06 13:52:06 +05:00
81ad7f7a64 feat(php): implement delete all files method 2024-03-06 13:42:41 +05:00
23ba4ff5b3 Merge pull request #541 from ONLYOFFICE/feature/fix-domain
Feature/fix domain
2024-03-06 09:32:36 +03:00
423233e93f update submodule 2024-03-05 16:42:41 +03:00
5f3eaa05f9 Merge remote-tracking branch 'remotes/origin/release/1.8.0' into develop
# Conflicts:
#	web/documentserver-example/php/assets/js/jscript.js
2024-03-05 16:33:14 +03:00
283d93667e ruby: change document-server to documentserver 2024-03-05 16:24:39 +03:00
158ac4161c python: change document-server to documentserver 2024-03-05 16:24:27 +03:00
bf3df5c89d php: change document-server to documentserver 2024-03-05 16:24:04 +03:00
d8251f3280 fix config paths 2024-03-05 16:16:31 +03:00
e4db31fbd5 Merge remote-tracking branch 'remotes/origin/feature/readme' into develop
# Conflicts:
#	Readme.md
2024-03-05 16:04:45 +03:00
b633f5ff19 Merge pull request #536 from Afrowave/python-example-update
CHORE: Add the Python example reference on the README.
2024-03-05 15:24:12 +03:00
0f0549c535 Merge remote-tracking branch 'origin/python-example-update' into python-example-update 2024-03-02 15:53:10 +03:00
e896f03acc CHORE: Add the Python example reference on the README. 2024-03-02 15:53:06 +03:00
a74d6b8676 CHORE: Add the Python example reference on the README. 2024-03-02 15:39:19 +03:00
672aae3791 refactor(nodejs): rename variables, ids, and classes regarding forced conversion 2024-03-01 16:29:04 +05:00
999e147539 fix(nodejs): disable file type buttons after selection 2024-03-01 15:25:14 +05:00
e57ad73d4f feat(php): allow to explicitly select output file type when getting auto-conversion error(-9) 2024-03-01 13:03:59 +05:00
690ab5471b Merge remote-tracking branch 'remotes/origin/release/1.8.0' into develop 2024-02-28 17:40:09 +03:00
2460f2c7ac nodejs: absolute host is not needed with urllib (1e72167e7d) 2024-02-28 17:22:31 +03:00
e3342a030c nodejs: fix mobile size (Fix Bug 34620) 2024-02-28 14:40:21 +03:00
e7630f516d build(ruby): updated gemfile.lock to 0 vulnerabilities 2024-02-27 16:47:26 +07:00
19a38df423 Merge remote-tracking branch 'remotes/origin/release/1.8.0' into develop
# Conflicts:
#	web/documentserver-example/nodejs/app.js
2024-02-26 12:39:33 +03:00
67a21fbe35 Merge pull request #524 from ONLYOFFICE/ruby-update-gemfile-lock
build(ruby): update gemfile.lock
2024-02-26 12:13:04 +03:00
08dc8ae6a7 build(ruby): updating gemfile.lock for containers 2024-02-22 17:28:13 +07:00
dcf2fb43e0 build(nodejs): updated dependencies (found 0 vulnerabilities) 2024-02-22 15:47:38 +07:00
dca6f4173e build(ruby): update gemfile.lock 2024-02-22 15:23:07 +07:00
9f2a72aafa Merge remote-tracking branch 'remotes/origin/release/1.8.0' into develop
# Conflicts:
#	web/documentserver-example/php/templates/docEditor.tpl
2024-02-20 15:04:31 +03:00
d8cb434ad2 Merge pull request #521 from ONLYOFFICE/feat/php-make-restart
feat(php): make restart
2024-02-20 14:55:33 +03:00
96af86846b feat(php): make restart 2024-02-20 17:26:40 +07:00
fa5fb2f182 Merge remote-tracking branch 'remotes/origin/release/1.8.0' into develop 2024-02-19 13:56:26 +03:00
f154ffc981 Merge remote-tracking branch 'remotes/origin/release/1.8.0' into develop
# Conflicts:
#	web/documentserver-example/php/src/helpers/Users.php
2024-02-16 18:50:23 +03:00
90142299e5 Merge pull request #516 from ONLYOFFICE/feature/tabs-menu
feat(nodejs): move links to header
2024-02-15 15:12:37 +03:00
0f288d539e feat(nodejs): move links to header 2024-02-15 12:35:12 +03:00
2ead6e1f7e feat(nodejs): move links to header 2024-02-15 11:23:34 +03:00
ea9ac4bb42 Merge pull request #506 from ONLYOFFICE/feature/delete-all-files
feat(nodejs): add a button to clear all files
2024-02-14 22:27:36 +03:00
5775f44f27 Merge remote-tracking branch 'remotes/origin/develop' into feature/delete-all-files
# Conflicts:
#	CHANGELOG.md
2024-02-14 22:26:45 +03:00
4ce10d82a1 Merge pull request #513 from ONLYOFFICE/python-reference-fix
fix(python): link in reference body
2024-02-14 22:22:38 +03:00
3e9e4281c5 Merge pull request #515 from ONLYOFFICE/fix/wopi-edit
fix(nodejs): correct edited exts from discovery info
2024-02-14 22:22:10 +03:00
3eac4912e1 Merge remote-tracking branch 'remotes/origin/release/1.8.0' into develop 2024-02-14 22:19:11 +03:00
e8df1c2821 fix(nodejs): correct edited exts from discovery info 2024-02-14 15:29:27 +07:00
da3224de7b Merge pull request #514 from ONLYOFFICE/fix/client-max-body-size
Fix/client max body size
2024-02-13 16:00:52 +03:00
819aa2b03f fix(python): nginx body size 2024-02-13 17:52:28 +07:00
f1aafa5fd6 fix(php): nginx body size 2024-02-13 17:44:05 +07:00
ff2bcd0ef6 feat(nodejs): add a button to clear all files 2024-02-13 11:12:36 +03:00
a17c349fb8 Merge pull request #512 from ONLYOFFICE/feature/rename-lock-file
Rename lock file
2024-02-13 09:53:36 +03:00
2268bd1cf4 nodejs: refactoring creating file 2024-02-12 13:37:26 +03:00
605c21c0be fix(python): link in reference body 2024-02-12 16:30:50 +07:00
3f0495321c Rename npm-shrinkwrap.json to package-lock.json 2024-02-09 12:35:25 +03:00
18fd30700f copyright 2024 2024-02-09 12:22:50 +03:00
9721187083 Merge remote-tracking branch 'remotes/origin/release/1.8.0' into develop 2024-02-09 12:21:37 +03:00
bce5e3760a do not convert to oform 2024-02-09 12:21:24 +03:00
e4d43eda2a Revert "Remove and make"
This reverts commit ac6632d25b.
2024-02-09 08:56:51 +00:00
ac6632d25b Remove and make 2024-02-09 08:51:58 +00:00
dab4841c1d inserting svg 2024-02-01 12:35:46 +03:00
a7cf7ae378 Merge branch 'release/1.8.0' into develop
# Conflicts:
#	CHANGELOG.md
2024-01-30 18:12:51 +03:00
e85cb5137b nodejs: fix serbian lang 2024-01-23 16:22:41 +03:00
163daa37c9 Merge pull request #508 from ONLYOFFICE/fix/send-notify
fix(php): correct sendNotify agrument
2024-01-23 14:01:56 +03:00
541a1e55b4 Merge pull request #507 from ONLYOFFICE/fix/edit-converted
fix(php): correct ext substring
2024-01-23 13:39:14 +03:00
d692abda4b fix(php): correct sendNotify agrument 2024-01-19 18:08:02 +07:00
f0d7892526 fix(php): correct ext substring 2024-01-19 17:59:18 +07:00
3a2f30bfcd Merge branch 'release/v8.0.0' into develop
# Conflicts:
#	CHANGELOG.md
#	web/documentserver-example/csharp-mvc/web.appsettings.config
#	web/documentserver-example/csharp/settings.config
#	web/documentserver-example/java-spring/src/main/resources/application.properties
#	web/documentserver-example/java/src/main/resources/settings.properties
2024-01-19 12:27:44 +03:00
03cc008de8 Merge pull request #505 from ONLYOFFICE/fix/saveas-exception
fix(python): correct saveAs url  (Fix Bug 65801)
2024-01-16 12:36:00 +03:00
5e76f08c83 fix(python): correct saveAs url 2024-01-16 14:50:46 +07:00
4ca824f1d7 Merge branch 'release/v8.0.0' into develop 2024-01-15 15:07:42 +03:00
ec268cacf7 nodejs: wopi frame without sandbox attribute (Fix Bug 65575) 2024-01-09 17:22:18 +03:00
c683d17bda Merge pull request #496 from ONLYOFFICE/feature/force-converting
Force converting problem files
2024-01-09 15:41:10 +03:00
7918671725 nodejs: handling conversion -9 error 2024-01-09 11:08:15 +03:00
408d80fff6 Merge pull request #502 from ONLYOFFICE/feature/users-different-goback
Users different goback
2024-01-09 11:04:15 +03:00
1b0e8df99f Merge remote-tracking branch 'remotes/origin/develop' into feature/users-different-goback
# Conflicts:
#	CHANGELOG.md
2024-01-09 11:01:08 +03:00
50104f1122 different goback to changelog 2024-01-09 11:00:16 +03:00
b90f333fdd csharp-mvc: add goback Users.cs 2023-12-29 12:47:37 +07:00
9e2aae1658 csharp: add goback Users.cs 2023-12-29 12:23:39 +07:00
0168355600 Merge pull request #494 from ONLYOFFICE/feature/converting
Converting
2023-12-28 12:26:02 +03:00
480b8af172 converting to changelog 2023-12-28 11:58:06 +03:00
f5d767e59d nodejs: wopi layout fix 2023-12-28 11:58:06 +03:00
62ad307327 nodejs: converting dialog window 2023-12-28 11:58:05 +03:00
b3b605230f nodejs: convert button on index page 2023-12-28 11:57:14 +03:00
ae2425f7e4 Merge pull request #503 from ONLYOFFICE/feature/formats-request
Getiing formats object on node
2023-12-28 10:45:30 +03:00
5849c9bb69 nodejs: getiing formats object 2023-12-27 13:35:03 +03:00
8ba1d5e8d7 update formats (add missed records) 2023-12-26 12:32:27 +03:00
91f3bda0b4 ruby: add goback users.rb 2023-12-22 15:15:26 +03:00
185605a1eb python: add goback users.py 2023-12-22 15:15:08 +03:00
6563a26d2d php: add goback users.php 2023-12-22 15:14:49 +03:00
d9061c57a3 nodejs: add goback users.js 2023-12-22 15:09:37 +03:00
b9c2c2e770 java: add goback user.java 2023-12-22 15:08:35 +03:00
a55d7b2d9d java-spring : add goback user.java 2023-12-22 15:08:09 +03:00
e0489a6922 Merge pull request #499 from ONLYOFFICE/feature/remove-history-close-restore
Remove Close History and Restore
2023-12-19 12:30:44 +03:00
dc14a9aa90 csharp-mvc: remove historyClose and restore 2023-12-19 15:41:22 +07:00
92206ed637 csharp: remove historyClose and restore 2023-12-19 15:31:28 +07:00
a763e2b9fe add: using replaceToInnerDocumentServerUrl() 2023-12-18 12:57:32 +03:00
841a4cd47e delete: SSLUtils 2023-12-18 12:52:10 +03:00
a5cd051303 change: method saveAs in FileController 2023-12-18 12:45:19 +03:00
381c9d74aa revert: docservice.properties 2023-12-18 12:41:58 +03:00
154dbb63e9 hange: dependency docs-integration-sdk as jar file 2023-12-18 12:41:51 +03:00
09f6ba00b2 ruby: add changes after pr #501 2023-12-18 10:09:54 +03:00
43f1555c68 python: add changes after pr #501 2023-12-18 10:09:47 +03:00
83535632bb php: add changes after pr #501 2023-12-18 10:09:40 +03:00
f1d41a4bf2 java: add changes after pr #501 2023-12-18 10:09:19 +03:00
f43e7414bb java-spring: add changes after pr #501 2023-12-18 10:09:11 +03:00
4455521e00 nodejs: add changes after pr #501 2023-12-18 10:08:32 +03:00
7b91694107 Merge branch 'develop' into feature/remove-history-close-restore 2023-12-15 18:16:04 +03:00
8edb65692a Merge pull request #501 from ONLYOFFICE/feature/fix-editros-files
Remove history methods for anonymous users
2023-12-15 17:55:20 +03:00
a36f270829 Merge remote-tracking branch 'remotes/origin/develop' into feature/fix-editros-files
# Conflicts:
#	web/documentserver-example/php/templates/docEditor.tpl
2023-12-15 17:54:25 +03:00
f726ae534c Merge pull request #500 from ONLYOFFICE/feature/add-onRequestUsers-onRequestSendNotify
Add functions RequestUsers and RequestSendNotify
2023-12-15 17:50:31 +03:00
69b266489f csharp-mvc: add onRequestUsers and onRequestSendNotify in Editor.aspx 2023-12-15 20:03:15 +07:00
7c18d08bc6 csharp: add onRequestUsers and onRequestSendNotify in DocEditor.aspx 2023-12-15 19:57:55 +07:00
11614ca5be delete: gitmodule document-formats 2023-12-15 11:16:33 +03:00
23caedfeff add: using model ReferenceData from sdk 2023-12-15 11:10:39 +03:00
3c10bdd9c6 delete: unused application.properties 2023-12-15 11:00:57 +03:00
56f4cb2208 refactoring: docservice.properties 2023-12-15 10:08:08 +03:00
bb2b9de205 delete: unused application.properties 2023-12-15 10:07:45 +03:00
6431ee33a8 delete: unused models and dto 2023-12-15 09:58:45 +03:00
9750b37f97 delete: unused FormatService 2023-12-15 09:49:19 +03:00
6dc02a3f43 delete: unused FileUtility 2023-12-15 09:48:16 +03:00
3bb39f4fb0 delete: unused ServiceConverter 2023-12-15 09:47:15 +03:00
5a9933f002 change: FileController, DefaultCallbackManager, DefaultHistoryManager with using sdk DocumentManager 2023-12-15 09:47:11 +03:00
5829794052 add: method generateRevisionId to DocumentManager 2023-12-15 09:46:58 +03:00
870e14af73 change: IndexController with using sdk DocumentManager 2023-12-15 09:36:10 +03:00
e6f6e0572b change: DefaultHistoryManager with using sdk DocumentManager 2023-12-15 09:34:26 +03:00
f4165d7715 change: DefaultCallbackManager with using sdk DocumentManager 2023-12-15 09:34:16 +03:00
bea8fd534e change: method getDocumentName in DocumentMangerImpl 2023-12-15 09:34:10 +03:00
2a59733e61 add: methods getFileName, generateFilepath to LocalFileStorage 2023-12-15 09:33:48 +03:00
ce937a58bb delete: unused DocumentManager 2023-12-14 16:27:46 +03:00
5955137575 change: FileController, DefaultCallbackManager with using sdk DocumentManager 2023-12-14 16:27:28 +03:00
91182b1967 add: method versionDir to HistoryManager 2023-12-14 16:26:47 +03:00
931f2db9d1 change: sdk DocumentManager, moved methods from DocumentManager (getCorrectName, getFilesInfo, createDemo) 2023-12-14 16:19:28 +03:00
bcf6ba1428 delete: FileUtility from sdk UrlManager 2023-12-14 16:02:23 +03:00
32d914c78c delete: unused TemplateManager 2023-12-14 15:59:46 +03:00
e324cb333b add: mathod getTemplateImageUrl to sdk UrlManager 2023-12-14 15:58:11 +03:00
88e80de4fc change: DocumentManager moved url methods to sdk UrlManager 2023-12-14 15:50:46 +03:00
b16e35275b change: FileController replace FileUtility method to sdk DocumentManager 2023-12-14 15:16:46 +03:00
5519ac4afc changed: DefaultHistoryManager with using sdk history models 2023-12-14 13:14:35 +03:00
32a66f4495 change: replace using JwtManager to sdk JwtManager 2023-12-14 12:35:31 +03:00
682265078c change: CallbackManager with using sdk CommandService 2023-12-14 12:13:36 +03:00
6717612fc1 ruby: add onRequestUsers and onRequestSendNotify in editor.html.erb 2023-12-14 12:09:32 +03:00
8db11243fd change: CallbackServiceImpl with using method processEditing from CallbackManager 2023-12-14 12:09:31 +03:00
45b6bfa443 add: method processEditing to CallbackManager 2023-12-14 12:08:27 +03:00
ad43b9298f change: FileController with using sdk CommandService 2023-12-14 12:04:52 +03:00
5577f5388f add: sdk service (CommandService) to spring context 2023-12-14 12:04:32 +03:00
f504b2be6e delete: unused callback handlers (EditCallback, ForcesaveCallback, SaveCallback) 2023-12-14 11:29:59 +03:00
776a34a5a0 change: FileController with using sdk CallbackService 2023-12-14 11:28:41 +03:00
6fcc535468 add: implementations sdk CallbackService (CallbackServiceImpl) 2023-12-14 11:28:07 +03:00
ced855d6ac delete: unused method (getConvertedData) from ServiceConverter 2023-12-13 16:45:24 +03:00
3725020468 change: process conversion with using sdk service convertService (FileController, DefaultCallbackManager) 2023-12-13 16:40:24 +03:00
e230d8ea9b add: sdk service (ConvertService) to spring context 2023-12-13 16:38:05 +03:00
a10366bae9 add: setting docservice.lossyEdit to docservice.properties 2023-12-13 16:37:17 +03:00
a7fc3d38e4 delete: unused mappers (PermissionsMapper, UsersMapper) 2023-12-13 14:57:44 +03:00
11ead2e57f delete: unused wrappers (DefaultCustomizationWrapper, DefaultDocumentWrapper, DefaultEmbeddedWrapper, DefaultFileWrapper) 2023-12-13 14:57:44 +03:00
59a2b1b439 delete: unused services (CustomizationConfigurer, DocumentConfigurer, EditorConfigConfigurer, EmbeddedConfigurer, FileConfigurer) 2023-12-13 14:57:44 +03:00
1bedfa0cf2 change: EditorController with using sdk ConfigService 2023-12-13 14:57:44 +03:00
b9137b1d86 add: sdk service (ConfigService) 2023-12-13 14:57:44 +03:00
892d390fff add: method getCurrentUser to UserServices 2023-12-13 14:57:43 +03:00
2e55bf1cfc add: docservice.properties file 2023-12-13 14:57:43 +03:00
9fe8701718 add: sdk managers (JwtManager, RequestManager) to spring context 2023-12-13 14:57:30 +03:00
c2c14dd2f4 add: implementations sdk managers (DocumentMangerImpl, SettingsManagerImpl, UrlManagerImpl) 2023-12-13 14:43:49 +03:00
d1a67fa322 add: dependency com.onlyoffice.docs-intagration-sdk 2023-12-13 14:42:41 +03:00
7f678c9ed8 ruby: remove history methods for anonymous users (fe352ebad1)
old commit:
fe352ebad1
2023-12-12 10:35:35 +03:00
ee951fbfbc python: remove history methods for anonymous users (18cf21efe4)
old commit:
18cf21efe4
2023-12-12 10:32:42 +03:00
91f32c1387 php: remove history methods for anonymous users (39820cec0a)
old commit:
39820cec0a
2023-12-12 10:30:42 +03:00
7051437928 java: remove history methods for anonymous users (52a722cf89)
old commit:
52a722cf89
2023-12-12 10:25:45 +03:00
0967c1c3ac java-spring: remove history methods for anonymous users (bc5393e28c)
old commit:
bc5393e28c
2023-12-12 10:19:25 +03:00
cf097501c6 Fix Bug 34620 - resize on mobile
This reverts commit d3a08acec3.
2023-12-11 15:33:07 +03:00
0b0e0dad8c python: add onRequestUsers and onRequestSendNotify in editor.html 2023-12-11 12:55:06 +03:00
d97291719a php: add onRequestUsers and onRequestSendNotify in docEditor.tpl 2023-12-11 12:41:40 +03:00
75ca703f8a java-spring: add onRequestUsers and onRequestSendNotify in editor.html 2023-12-11 11:59:52 +03:00
01618fee17 java: add onRequestUsers and onRequestSendNotify in editor.jsp 2023-12-11 11:54:36 +03:00
78a8b56b48 java: delete spaces from editor.jsp 2023-12-07 13:47:25 +03:00
3b9bad4a26 Merge branch 'develop' into feature/remove-history-close-restore 2023-12-07 11:34:27 +03:00
435b8013f6 style: updates to styling 2023-12-07 10:58:41 +03:00
a9063af6e1 fix sr-Latn-RS 2023-12-06 12:56:12 +03:00
bde236075c ruby: remove historyClose and restore 2023-12-05 16:08:45 +03:00
f74f34504f python: remove historyClose and restore 2023-12-05 16:08:29 +03:00
3243a04a1b php: remove historyClose and restore 2023-12-05 15:25:20 +03:00
6598aa585a java: remove historyClose and restore 2023-12-05 15:25:05 +03:00
e02744e56b nodejs: remove historyClose and restore 2023-12-05 14:59:14 +03:00
ec596753c6 java-spring: remove historyClose and restore 2023-12-05 14:58:24 +03:00
3820f76d27 nodejs: added page for forgotten files 2023-11-03 09:14:41 +03:00
361 changed files with 13940 additions and 8058 deletions

View File

@ -0,0 +1,31 @@
name: Artifact PHP Laravel
on:
workflow_dispatch:
push:
branches: [master]
paths: ['web/documentserver-example/php-laravel/**']
pull_request:
branches: [master]
paths: ['web/documentserver-example/php-laravel/**']
jobs:
artifact:
runs-on: ubuntu-latest
steps:
- name: Checkout Repository
uses: actions/checkout@v4
- name: Build Artifact
run: |
cd ${{ github.workspace }}
git submodule update --init --recursive
cd ./web/documentserver-example/php-laravel
mkdir -p ./deploy/'PHP Laravel Example'
rsync -av --exclude='deploy' ./ ./deploy/'PHP Laravel Example'
rm -rf ./deploy/'PHP Laravel Example'/public/assets/document-formats/.git
rm -rf ./deploy/'PHP Laravel Example'/public/assets/document-templates/.git
- name: Upload Artifact
uses: actions/upload-artifact@v4
with:
name: PHP-Laravel.Example
path: ${{ github.workspace }}/web/documentserver-example/php-laravel/deploy

37
.github/workflows/lint-php-laravel.yml vendored Normal file
View File

@ -0,0 +1,37 @@
name: Laravel Pint
on:
workflow_dispatch:
push:
branches: [master, main]
paths: ['web/documentserver-example/php-laravel/**']
pull_request:
branches: [master, main, develop]
paths: ['web/documentserver-example/php-laravel/**']
jobs:
lint:
runs-on: ubuntu-latest
strategy:
fail-fast: true
matrix:
php: [8.2]
defaults:
run:
working-directory: ./web/documentserver-example/php-laravel
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php }}
extensions: json, dom, curl, libxml, mbstring
coverage: none
- name: Install Pint
run: composer global require laravel/pint
- name: Run Pint
run: pint --test

View File

@ -30,7 +30,7 @@ jobs:
- name: Install Dependencies
run: |
bundle update
bundle install
- name: Rubocop
run: |

21
.gitmodules vendored
View File

@ -1,22 +1,21 @@
[submodule "web/documentserver-example/nodejs/public/assets/document-templates"]
path = web/documentserver-example/nodejs/public/assets/document-templates
url = https://github.com/ONLYOFFICE/document-templates
branch = main/en-8.1
branch = main/default
[submodule "web/documentserver-example/nodejs/public/assets/document-formats"]
path = web/documentserver-example/nodejs/public/assets/document-formats
url = https://github.com/ONLYOFFICE/document-formats
branch = feature/v8.1
[submodule "web/documentserver-example/csharp-mvc/assets/document-templates"]
path = web/documentserver-example/csharp-mvc/assets/document-templates
url = https://github.com/ONLYOFFICE/document-templates
branch = main/en
branch = main/default
[submodule "web/documentserver-example/csharp-mvc/assets/document-formats"]
path = web/documentserver-example/csharp-mvc/assets/document-formats
url = https://github.com/ONLYOFFICE/document-formats
[submodule "web/documentserver-example/php/assets/document-templates"]
path = web/documentserver-example/php/assets/document-templates
url = https://github.com/ONLYOFFICE/document-templates
branch = main/en
branch = main/default
[submodule "web/documentserver-example/php/assets/document-formats"]
path = web/documentserver-example/php/assets/document-formats
url = https://github.com/ONLYOFFICE/document-formats
@ -24,19 +23,19 @@
[submodule "web/documentserver-example/python/assets/document-templates"]
path = web/documentserver-example/python/assets/document-templates
url = https://github.com/ONLYOFFICE/document-templates
branch = main/en
branch = main/default
[submodule "web/documentserver-example/java/src/main/resources/assets/document-templates"]
path = web/documentserver-example/java/src/main/resources/assets/document-templates
url = https://github.com/ONLYOFFICE/document-templates
branch = main/en
branch = main/default
[submodule "web/documentserver-example/ruby/assets/document-templates"]
path = web/documentserver-example/ruby/assets/document-templates
url = https://github.com/ONLYOFFICE/document-templates
branch = main/en
branch = main/default
[submodule "web/documentserver-example/java-spring/src/main/resources/assets/document-templates"]
path = web/documentserver-example/java-spring/src/main/resources/assets/document-templates
url = https://github.com/ONLYOFFICE/document-templates
branch = main/en
branch = main/default
[submodule "web/documentserver-example/python/assets/document-formats"]
path = web/documentserver-example/python/assets/document-formats
url = https://github.com/ONLYOFFICE/document-formats
@ -49,14 +48,10 @@
path = web/documentserver-example/java/src/main/resources/assets/document-formats
url = https://github.com/ONLYOFFICE/document-formats
branch = master
[submodule "web/documentserver-example/java-spring/src/main/resources/assets/document-formats"]
path = web/documentserver-example/java-spring/src/main/resources/assets/document-formats
url = https://github.com/ONLYOFFICE/document-formats
branch = master
[submodule "web/documentserver-example/csharp/assets/document-templates"]
path = web/documentserver-example/csharp/assets/document-templates
url = https://github.com/ONLYOFFICE/document-templates
branch = main/en
branch = main/default
[submodule "web/documentserver-example/csharp/assets/document-formats"]
path = web/documentserver-example/csharp/assets/document-formats
url = https://github.com/ONLYOFFICE/document-formats

View File

@ -1,6 +1,5 @@
Document Server integration example uses code from the following 3rd party projects.
web/documentserver-example/csharp
jQuery.BlockUI - The jQuery BlockUI Plugin lets you simulate synchronous behavior when using AJAX, without locking the browser. (https://github.com/malsup/blockui/)
@ -132,6 +131,10 @@ Jackson Databind - General-purpose data-binding functionality and tree-model for
License: Apache 2.0
License File: jackson-databind.license
Jackson Dataformat Properties - Support for reading and writing content of "Java Properties" style configuration files as if there was implied nesting structure (by default using dots as separators). (https://github.com/FasterXML/jackson-dataformats-text/blob/master/LICENSE)
License: Apache 2.0
License File: jackson-dataformat-properties.license
jQuery.BlockUI - The jQuery BlockUI Plugin lets you simulate synchronous behavior when using AJAX, without locking the browser. (https://github.com/malsup/blockui/)
License: MIT, GPL
License File: jQuery.BlockUI.license
@ -156,6 +159,10 @@ jQuery.UI - jQuery UI is an open source library of interface components —
License: MIT
License File: jQuery.UI.license
JSON - JSON is a light-weight, language independent, data interchange format. (https://github.com/stleary/JSON-java/blob/master/LICENSE)
License Public Domain
License File: json.license
JSON.simple - JSON.simple is a simple Java toolkit for JSON. You can use JSON.simple to encode or decode JSON text. (https://github.com/fangyidong/json-simple/blob/master/LICENSE.txt)
License: Apache 2.0
License File: JSON.simple.license
@ -168,14 +175,14 @@ ModelMapper - ModelMapper is an intelligent object mapping library that automa
License: Apache 2.0
License File modelmapper.license
Prime JWT - is intended to be fast and easy to use. Prime JWT has a single external dependency on Jackson. (https://github.com/ws-apps/prime-jwt/blob/master/LICENSE)
License: Apache 2.0
License File: prime-jwt.license
Spring Boot - Helps create Spring-powered, production-grade applications and services. Has external dependencies on Spring Framework. (https://github.com/spring-projects/spring-boot/blob/main/LICENSE.txt)
License: Apache 2.0
License File: spring-boot.license
Spring Boot Web - Starter for building web, including RESTful, applications using Spring MVC. Uses Tomcat as the default embedded container. (https://github.com/spring-projects/spring-boot/blob/main/LICENSE.txt)
License: Apache 2.0
License File: spring-boot.license
Spring Boot Devtools - Provides fast application restarts, LiveReload, and configurations for enhanced development experience. (https://github.com/spring-projects/spring-boot/blob/main/LICENSE.txt)
License: Apache 2.0
License File: spring-boot.license
@ -271,6 +278,9 @@ urllib - Request HTTP URLs in a complex world — basic and digest authen
License: MIT
License File: urllib.license
utf7 - Encodes and decodes JavaScript (Unicode/UCS-2) strings to UTF-7 ASCII strings. (https://github.com/kkaefer/utf7/blob/master/LICENSE)
License: MIT
License File: utf7.license
web/documentserver-example/php

View File

@ -1,5 +1,24 @@
# Change Log
## 1.11.0
- he-IL skin language
- ConvertService.ashx address replaced with converter
- coauthoring/CommandService.ashx address replaced with command
- without submitForm in viewer
## 1.10.0
- nodejs: converting function on index page
- java-spring: using java docs-integration-sdk
- tabs menu
- creating and editing pdf instead docxf
- filling by default
- forgotten files
- delete all files
- save as for pdf
- handling conversion -9 error
- change inserted image
- different goback for users
## 1.9.0
- nodejs: filling by default
- nodejs: docxf, oform as pdf documentType

View File

@ -1,11 +1,11 @@
## Integration examples
Test examples are simple document management systems that can be built into your application for testing.
These 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.
The package contains examples written in .Net (C# MVC), .Net (C#), Java, Java Spring, Node.js, PHP, Python 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`
@ -13,9 +13,9 @@ You should change `http://documentserver` to your server address in these files:
* [Java](https://github.com/ONLYOFFICE/document-server-integration/tree/master/web/documentserver-example/java) - `web/documentserver-example/java/src/main/resources/settings.properties`
* [Java Spring](https://github.com/ONLYOFFICE/document-server-integration/tree/master/web/documentserver-example/java-spring) - `web/documentserver-example/java-spring/src/main/resources/application.properties`
* [Node.js](https://github.com/ONLYOFFICE/document-server-integration/tree/master/web/documentserver-example/nodejs) - `web/documentserver-example/nodejs/config/default.json`
* [PHP](https://github.com/ONLYOFFICE/document-server-integration/tree/master/web/documentserver-example/php) - `web/documentserver-example/php/config.json`
* [Python](https://github.com/ONLYOFFICE/document-server-integration/tree/master/web/documentserver-example/python) - `web/documentserver-example/python/config.py`
* [Ruby](https://github.com/ONLYOFFICE/document-server-integration/tree/master/web/documentserver-example/ruby) - `web/documentserver-example/ruby/config/application.rb`
* [PHP](https://github.com/ONLYOFFICE/document-server-integration/tree/master/web/documentserver-example/php) - `web/documentserver-example/php/src/configuration/ConfigurationManager.php`
* [Python](https://github.com/ONLYOFFICE/document-server-integration/tree/master/web/documentserver-example/python) - `web/documentserver-example/python/src/configuration/configuration.py`
* [Ruby](https://github.com/ONLYOFFICE/document-server-integration/tree/master/web/documentserver-example/ruby) - `web/documentserver-example/ruby/app/configuration/configuration.rb`
More information on how to use these examples can be found here: [http://api.onlyoffice.com/editors/demopreview](http://api.onlyoffice.com/editors/demopreview "http://api.onlyoffice.com/editors/demopreview")

View File

@ -38,9 +38,15 @@ namespace OnlineEditorsExampleMVC
// create the main script bundle
bundles.Add(new ScriptBundle("~/bundles/scripts").Include(
"~/Scripts/formats.js",
"~/Scripts/jscript.js"
));
// create the forgotten page script bundle
bundles.Add(new ScriptBundle("~/bundles/forgotten").Include(
"~/Scripts/forgotten.js"
));
// create a style bundle
bundles.Add(new StyleBundle("~/Content/css").Include(
"~/Content/stylesheet.css",
@ -52,6 +58,11 @@ namespace OnlineEditorsExampleMVC
bundles.Add(new StyleBundle("~/Content/editor").Include(
"~/Content/editor.css"
));
// create the forgotten page style bundle
bundles.Add(new StyleBundle("~/Content/forgotten").Include(
"~/Content/forgotten.css"
));
}
}
}

View File

@ -0,0 +1,161 @@
.center {
width: auto;
}
.left-panel {
width: 256px;
}
.main-panel {
width: 832px;
margin: 0 32px;
padding: 48px 0;
left: 0;
}
.tableRow {
display: flex;
width: 100%;
justify-content: space-between;
align-items: center;
border-bottom: 1px solid #E2E2E2;
}
.tableRow td:first-child {
width: 70%;
flex-grow: 0;
max-width: none;
}
.tableHeader td:first-child {
text-align: left;
}
.tableHeader td:last-child, .tableRow td:last-child {
width: 10%;
text-align: center;
padding: 0 !important;
}
.tableHeader {
width: 100%;
}
.stored-edit {
display: block;
padding-top: 0;
max-width: none;
}
menu.links {
width: 100%;
}
.scroll-table-body table {
table-layout: fixed;
}
.stored-edit span {
font-size: 12px;
line-height: normal;
position: static;
}
.scroll-table-body {
overflow-y: auto;
}
.stored-list {
height: calc(100% - 58px);
}
header {
min-width:auto;
}
header a {
display: block;
margin: 0 auto;
width: 1152px;
}
@media (max-width: 1279px) and (min-width: 1024px) {
.left-panel {
width: 208px;
}
.main-panel {
width: 688px;
}
header a {
width: 928px;
}
header img {
margin-left: 16px;
}
}
@media (max-width: 1023px) and (min-width: 593px) {
.center {
max-width: 768px;
width: calc(100% - 80px);
}
.table-main {
width: 100%;
}
.left-panel {
width: 208px;
}
.main-panel {
width: calc(100% - 32px);
}
.tableHeader td:last-child, .tableRow td:last-child {
width: 20%;
}
header a {
width: 768px;
}
header img {
margin-left: 40px;
}
}
@media (max-width: 592px) and (min-width: 320px) {
.center, .table-main {
width: 100%;
}
.left-panel {
display: none;
}
.main-panel {
width: 100%;
margin: 0;
padding: 28px 16px;
}
.tableHeader td:last-child, .tableRow td:last-child {
width: 25%;
}
header a {
width: auto;
}
.scroll-table-body {
top: 40px;
}
.tableRow {
padding: 8px 0;
}
}

View File

@ -1 +0,0 @@
<svg width="30" height="40" viewBox="0 0 30 40" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M0 3c0-1.65685 1.34315-3 3-3h20l7 7v30c0 1.6569-1.3431 3-3 3H3c-1.65685 0-3-1.3431-3-3V3z" fill="#27ABA3"/><path d="M23 0l7 7h-4c-1.6569 0-3-1.34315-3-3V0z" fill="#008078"/><path fill-rule="evenodd" clip-rule="evenodd" d="M24 14H6v7h18v-7zm-.8182 5.9978H6.81818V15H23.1818v4.9978zM24 23H6v7h18v-7zm-.8182 5.9978H6.81818V24H23.1818v4.9978z" fill="#fff"/></svg>

Before

Width:  |  Height:  |  Size: 463 B

View File

@ -0,0 +1,5 @@
<svg width="30" height="40" viewBox="0 0 30 40" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M0 3C0 1.34315 1.34315 0 3 0H23L30 7V37C30 38.6569 28.6569 40 27 40H3C1.34315 40 0 38.6569 0 37V3Z" fill="#9E1919"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M17.0062 15V16.0065H24V15H17.0062ZM17.0062 19V20.0163H24V19H17.0062ZM24 23H17.0062V24.0261H24V23ZM6 28V27.0293H24V28H6ZM7 16H14V23H7V16ZM6 15H7H14H15V16V23V24H14H7H6V23V16V15Z" fill="white"/>
<path d="M23 0L30 7H26C24.3431 7 23 5.65685 23 4V0Z" fill="black" fill-opacity="0.25"/>
</svg>

After

Width:  |  Height:  |  Size: 558 B

View File

@ -0,0 +1,3 @@
<svg width="20" height="17" viewBox="0 0 20 17" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M8 17V11H12V17H17V9H20L10 0L0 9H3V17H8Z" fill="#444444"/>
</svg>

After

Width:  |  Height:  |  Size: 173 B

View File

@ -0,0 +1 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M2 1h8l4 4v10H2V1z" fill="#fff"/><path fill-rule="evenodd" clip-rule="evenodd" d="M14 5l-4-4H2v14h12V5zm-4-5l5 5v11H1V0h9z" fill="#BFBFBF"/><path fill="#9E1919" d="M3 10h10v4H3z"/><path d="M7 7V2H3v5h4zM8 3V2h2v1H8zM8 5V4h5v1H8zM13 6H8v1h5V6zM13 8H3v1h10V8z" fill="#BFBFBF"/><path opacity=".3" d="M9 1h1v3h4l1 1H9V1z" fill="#333"/></svg>

After

Width:  |  Height:  |  Size: 441 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

View File

@ -0,0 +1,5 @@
<svg width="24" height="23" viewBox="0 0 24 23" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M10.5332 22.2243L0.632544 17.5921C-0.210848 17.1877 -0.210848 16.5627 0.632544 16.1951L4.07945 14.5775L10.4966 17.5921C11.34 17.9965 12.6967 17.9965 13.5034 17.5921L19.9206 14.5775L23.3675 16.1951C24.2108 16.5995 24.2108 17.2245 23.3675 17.5921L13.4668 22.2243C12.6967 22.592 11.34 22.592 10.5332 22.2243Z" fill="#FF6F3D"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M10.5011 16.4922L0.630617 11.8546C-0.210206 11.4497 -0.210206 10.824 0.630617 10.456L3.99391 8.87329L10.5011 11.9282C11.342 12.3331 12.6946 12.3331 13.4989 11.9282L20.0061 8.87329L23.3694 10.456C24.2102 10.8608 24.2102 11.4865 23.3694 11.8546L13.4989 16.4922C12.658 16.897 11.3054 16.897 10.5011 16.4922Z" fill="#95C038"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M10.5011 10.8195L0.630617 6.24863C-0.210206 5.84959 -0.210206 5.23289 0.630617 4.87013L10.5011 0.299281C11.342 -0.0997605 12.6946 -0.0997605 13.4989 0.299281L23.3694 4.87013C24.2102 5.26917 24.2102 5.88587 23.3694 6.24863L13.4989 10.8195C12.658 11.1822 11.3054 11.1822 10.5011 10.8195Z" fill="#5DC0E8"/>
</svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@ -0,0 +1,5 @@
<svg width="20" height="14" viewBox="0 0 20 14" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect width="20" height="2" rx="1" fill="white"/>
<rect y="6" width="20" height="2" rx="1" fill="white"/>
<rect y="12" width="20" height="2" rx="1" fill="white"/>
</svg>

After

Width:  |  Height:  |  Size: 278 B

View 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="M13 17C13 17.5523 12.5523 18 12 18C11.4477 18 11 17.5523 11 17V13H7C6.44772 13 6 12.5523 6 12C6 11.4477 6.44772 11 7 11H11V7C11 6.44772 11.4477 6 12 6C12.5523 6 13 6.44772 13 7V11H17C17.5523 11 18 11.4477 18 12C18 12.5523 17.5523 13 17 13H13V17Z" fill="#444444"/>
</svg>

After

Width:  |  Height:  |  Size: 416 B

View File

@ -79,7 +79,8 @@
margin-left: 0;
}
.tableRow {
.tableRow,
menu.links {
width: 90%;
}
@ -119,7 +120,8 @@
.contentCells-icon{
width: 5%;
}
.tableRow {
.tableRow,
menu.links {
width: 55%;
}
@ -175,7 +177,8 @@
}
@media (max-width: 715px) {
.tableRow {
.tableRow,
menu.links {
width: 45%;
}
}
@ -263,7 +266,8 @@
padding-left: 0;
}
.tableRow {
.tableRow,
menu.links {
width: 75%;
}
@ -293,7 +297,8 @@
width: 580px;
}
.tableRow {
.tableRow,
menu.links {
width: 95%;
}
@ -407,7 +412,8 @@
padding: 16px 0 6px;
}
.tableRow {
.tableRow,
menu.links {
width: 40%;
}
@ -502,6 +508,17 @@
justify-content: space-between;
align-items: center;
}
.buttonsMobile.indent {
margin-bottom: 0;
flex-wrap: nowrap;
}
.button.file-type:hover,
.button.file-type {
height: 28px;
width: 100px;
margin-bottom: 10px !important;
font-size: 9px;
}
.button.gray{
margin: 0;
}
@ -527,7 +544,8 @@
}
@media (max-width: 510px) and (min-width: 470px) {
.tableRow {
.tableRow,
menu.links {
width: 35%;
}
@ -553,7 +571,8 @@
}
@media (max-width: 470px) and (min-width: 420px) {
.tableRow {
.tableRow,
menu.links {
width: 30%;
}
.tableRow td:first-child{
@ -588,7 +607,8 @@
}
@media (max-width: 420px) and (min-width: 320px) {
.tableRow {
.tableRow,
menu.links {
width: 25%;
}
@ -638,7 +658,8 @@
}
}
@media (max-width: 769px) and (min-width: 715px){
.tableRow{
.tableRow,
menu.links {
width: 50%;
}
}
@ -687,3 +708,216 @@
max-width: none;
}
}
@media (max-width: 592px) and (min-width: 320px) {
body.menu-open {
overflow: hidden;
}
header {
min-width: auto;
height: fit-content;
}
header a {
display: block;
}
header img {
margin: 0;
}
header, footer {
position: -webkit-sticky; /* Safari */
position: sticky;
top: 0;
z-index: 100;
}
.center {
width: 100%;
margin: 0;
}
.left-panel {
background-color: rgba(186, 186, 186, 0.6);
display: none;
flex-direction: row;
align-items: start;
max-width: none;
width: 100%;
margin: 0;
position: fixed;
left: 0;
height: calc(100% - 124px);
z-index:99;
}
.left-panel.active {
display: flex;
}
.help-block {
height: 100%;
margin: 0;
background-color: #F5F5F5;
width: 248px;
padding-left: 16px;
padding-top: 33px;
padding-bottom: 33px;
padding-right: 40px;
box-sizing: border-box;
overflow-y: auto;
overflow-x: hidden;
}
.table-main {
width: 100%;
}
.mobile-close-btn {
display: block;
width: 48px;
height: 48px;
background-color: #E2E2E2;
border-radius: 2px;
border-color: #E2E2E2;
color: #808080;
cursor: pointer;
outline: inherit;
border: none;
}
.main-panel {
width: 100%;
left: 0;
padding: 28px 16px;
}
#portal-info {
width: 100%;
max-width: fit-content;
}
menu.links {
width: 100%;
margin-top: 0;
padding: 0;
}
span.portal-name {
font-size: 16px;
}
span.portal-descr:first-child {
font-size: 13px;
}
span.portal-descr {
font-size: 12px;
}
.user-descr {
width: 100%;
max-width: none;
min-width: auto;
border-bottom: 1px solid #E5E5E5;
padding: 12px 0;
margin: 0;
cursor: pointer;
}
.user-descr ul {
display: none;
}
.user-descr ul.active {
display: block;
}
.user-descr b {
font-size: 13px;
display: flex;
align-items: center;
column-gap: 8px;
margin: 0;
}
.user-descr b::before {
content: url("images/plus.svg");
display: inline-block;
width: 24px;
height: 24px;
}
.storedHeader {
width: 100%;
}
.storedHeaderClearAll {
padding-right: 0;
}
.scroll-table-body {
top: 36px;
}
.scroll-table-body tr:first-child {
padding-top: 0;
}
.tableRow {
border-bottom: 1px solid #e5e5e5;
padding: 16px 0;
width: 100%;
}
.tableRow td:first-child {
width: 100%;
}
.stored-edit span {
font-size: 14px;
}
.header-list {
font-size: 16px;
}
.firstContentCellViewers {
border-bottom: none !important;
}
.firstContentCellViewers ~ td {
border-bottom: none !important;
}
.downloadContentCellShift:after {
display: none;
}
.main-nav {
display: none;
}
.responsive-nav {
height: 44px;
display: flex;
flex-direction: row;
margin: 0;
align-items: center;
column-gap: 16px;
padding: 10px 16px;
width: 100%;
box-sizing: border-box;
list-style: none;
}
.main {
height: calc(100% - 124px);
}
.user-block-table {
height: auto;
}
}

View File

@ -65,6 +65,14 @@ header img {
margin: 10px 0 22px 32px;
}
.responsive-nav {
display: none;
}
.mobile-close-btn {
display: none;
}
.center {
position:relative;
margin: 0 auto 0;
@ -164,7 +172,7 @@ label .checkbox {
}
.try-editor.form {
background-image: url("images/file_docxf.svg");
background-image: url("images/file_pdf.svg");
}
.side-option {
@ -230,6 +238,33 @@ label .checkbox {
color: #FF6F3D;
}
.button.file-type {
font-size: 11px;
color: #FFFFFF;
padding: 8px 8px;
margin-right: 10px;
}
.button.file-type.disable {
cursor: default;
}
.button.file-type.pale {
opacity: 30%;
}
.button.file-type.document {
background: #446995;
}
.button.file-type.spreadsheet {
background: #40865C;
}
.button.file-type.presentation {
background: #AA5252;
}
.upload-panel {
float: left;
padding: 24px 0;
@ -271,6 +306,43 @@ label .checkbox {
border-bottom: 1px solid #D0D5DA;
}
.links {
display: flex;
padding: 0;
column-gap: 30px;
align-items: center;
list-style: none;
border-bottom: 1px solid #E2E2E2;
margin: 0;
margin-bottom: 24px;
}
.links li {
padding: 4px;
border-bottom: 2px solid transparent;
margin-bottom: -1px;
}
.links li.active {
border-bottom: 2px solid #FF6F3D;
}
.links li.active a {
color: #FF6F3D;
}
.links li.active a img {
filter: invert(55%) sepia(67%) saturate(2727%) hue-rotate(335deg) brightness(104%) contrast(101%);
}
.links a {
display: inline-block;
padding: 2px 0;
line-height: 20px;
font-size: 13px;
text-decoration: none;
}
#mainProgress {
color: #333333;
display: none;
@ -464,6 +536,11 @@ footer table tr td:first-child {
background-image: url("images/icon_pptx.svg");
}
.stored-edit.pdf,
.uploadFileName.pdf {
background-image: url("images/icon_pdf.svg");
}
.stored-edit span {
font-size: 12px;
line-height: 12px;
@ -592,6 +669,29 @@ footer table tr td:first-child {
width: 4%;
}
.storedHeader {
display: flex;
width: 100%;
justify-content: space-between;
align-items: center;
}
.storedHeaderClearAll {
padding-right: 52px;
}
.clear-all {
display: inline-block;
width: 100px;
padding: 2px;
outline: 1px solid #E5E5E5;
text-align: center;
cursor:pointer;
text-transform: uppercase;
background-color: #F5F5F5;
color: #666666;
}
.select-user {
color: #444444;
font-family: Open Sans;
@ -741,6 +841,16 @@ html {
margin-left: 25px;
}
.buttonsMobile.indent{
padding-left: 35px;
margin-top: 10px;
margin-bottom: 10px;
}
.invisible {
display: none;
}
.tooltip {
background: #FFFFFF;
border-radius: 5px;

View File

@ -17,10 +17,13 @@
*/
using System;
using System.Collections.Generic;
using System.Collections;
using System.IO;
using System.Web.Mvc;
using OnlineEditorsExampleMVC.Helpers;
using OnlineEditorsExampleMVC.Models;
using System.Web.Configuration;
namespace OnlineEditorsExampleMVC.Controllers
{
@ -31,6 +34,46 @@ namespace OnlineEditorsExampleMVC.Controllers
return View();
}
public ActionResult Forgotten()
{
if (!bool.Parse(WebConfigurationManager.AppSettings["enable-forgotten"]))
{
ViewData["Message"] = "The forgotten page is disabled";
return View("~/Views/Shared/Error.aspx");
}
var files = new List<Dictionary<string, string>>();
try
{
var response = TrackManager.commandRequest("getForgottenList", null);
ArrayList keys = (ArrayList)response["keys"];
// fetch all the forgotten files from the document server
foreach (string key in keys)
{
var file = new Dictionary<string, string>();
var fileResult = TrackManager.commandRequest("getForgotten", key);
file.Add("key", fileResult["key"].ToString());
file.Add("url", fileResult["url"].ToString());
file.Add(
"type",
FileUtility.GetFileType(fileResult["url"].ToString())
.ToString()
.ToLower()
);
files.Add(file);
}
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine(ex.Message);
}
return View("Forgotten", new ForgottenFilesModel(files));
}
// viewing file in the editor
public ActionResult Editor(string fileName, string editorsMode, string editorsType, string directUrl)
{
@ -52,7 +95,7 @@ namespace OnlineEditorsExampleMVC.Controllers
var id = Request.Cookies.GetOrDefault("uid", null);
var user = Users.getUser(id);
DocManagerHelper.CreateMeta(fileName, user.id, user.name); // create meta information for the sample document
Response.Redirect(Url.Action("Editor", "Home", new { fileName = fileName }));
Response.Redirect(Url.Action("Editor", "Home", new { fileName = fileName, editorsMode="edit" }));
return null;
}
}

View File

@ -225,10 +225,14 @@ namespace OnlineEditorsExampleMVC.Helpers
private static void ProcessResponseError(int errorCode)
{
var errorMessage = string.Empty;
const string errorMessageTemplate = "Error occurred in the ConvertService.ashx: {0}";
const string errorMessageTemplate = "Error occurred in the ConvertService: {0}";
switch (errorCode)
{
case -9:
// public const int c_nErrorConversionOutputFormatError = -9;
errorMessage = String.Format(errorMessageTemplate, "Error conversion output format");
break;
case -8:
// public const int c_nErrorFileVKey = -8;
errorMessage = String.Format(errorMessageTemplate, "Error document VKey");

View File

@ -282,7 +282,7 @@ namespace OnlineEditorsExampleMVC.Helpers
}
// create a command request
public static void commandRequest(string method, string key, object meta = null)
public static Dictionary<string, object> commandRequest(string method, string key, object meta = null)
{
DocManagerHelper.VerifySSL();
@ -345,6 +345,7 @@ namespace OnlineEditorsExampleMVC.Helpers
{
throw new Exception(dataResponse);
}
return responseObj;
}
// save file

View File

@ -59,7 +59,9 @@ namespace OnlineEditorsExampleMVC.Helpers
"Cant print the file",
"Can create new files from the editor",
"Can see the information about Group2 users",
"Cant submit forms"
"Cant submit forms",
"Can't close history",
"Can't restore the file version"
};
static List<string> descr_user_0 = new List<string>()
@ -92,7 +94,8 @@ namespace OnlineEditorsExampleMVC.Helpers
new List<string>(),
descr_user_1,
true,
true
true,
new Goback(null, false)
),
new User(
"uid-2",
@ -111,7 +114,8 @@ namespace OnlineEditorsExampleMVC.Helpers
new List<string>(),
descr_user_2,
false,
true
true,
new Goback("Go to Documents", null)
),
new User(
"uid-3",
@ -130,7 +134,8 @@ namespace OnlineEditorsExampleMVC.Helpers
new List<string>() { "copy", "download", "print" },
descr_user_3,
false,
false
false,
null
),
new User(
"uid-0",
@ -144,7 +149,8 @@ namespace OnlineEditorsExampleMVC.Helpers
new List<string>() { "protect" },
descr_user_0,
false,
false
false,
null
)
};
@ -235,7 +241,9 @@ namespace OnlineEditorsExampleMVC.Helpers
public List<string> userInfoGroups;
public bool avatar;
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, bool avatar)
public Goback goback;
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, bool avatar, Goback goback)
{
this.id = id;
this.name = name;
@ -249,6 +257,21 @@ namespace OnlineEditorsExampleMVC.Helpers
this.templates = templates;
this.userInfoGroups = userInfoGroups;
this.avatar = avatar;
this.goback = goback;
}
}
public class Goback
{
public string text;
public bool? blank;
public Goback(){}
public Goback(string text, bool? blank)
{
this.text = text;
this.blank = blank;
}
}
}

View File

@ -77,18 +77,19 @@ namespace OnlineEditorsExampleMVC.Models
var jss = new JavaScriptSerializer();
var ext = Path.GetExtension(FileName).ToLower(); // get file extension
var editorsMode = Mode ?? "edit"; // get editor mode
var canFill = DocManagerHelper.FillFormExts.Contains(ext);
var editorsMode = Mode ?? (canFill ? "fillForms" : "edit"); // get editor mode
var canEdit = DocManagerHelper.EditedExts.Contains(ext); // check if the file with such an extension can be edited
var id = request.Cookies.GetOrDefault("uid", null);
var user = Users.getUser(id); // get the user
if ((!canEdit && editorsMode.Equals("edit") || editorsMode.Equals("fillForms")) && DocManagerHelper.FillFormExts.Contains(ext)) {
if ((!canEdit && editorsMode.Equals("edit") || editorsMode.Equals("fillForms")) && canFill) {
editorsMode = "fillForms";
canEdit = true;
}
var submitForm = editorsMode.Equals("fillForms") && id.Equals("uid-1"); // check if the Submit form button is displayed or not
var submitForm = !editorsMode.Equals("view") && user.id.Equals("uid-1"); // check if the Submit form button is displayed or not
var mode = canEdit && editorsMode != "view" ? "edit" : "view"; // set the mode parameter: change it to view if the document can't be edited
// favorite icon state
@ -214,10 +215,12 @@ namespace OnlineEditorsExampleMVC.Models
{ "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
{
"goback", new Dictionary<string, object> // settings for the Open file location menu button and upper right corner button
"goback", user.goback != null ? new Dictionary<string, object> // settings for the Open file location menu button and upper right corner button
{
{ "url", DocManagerHelper.GetServerUrl(false) } // the absolute URL to the website address which will be opened when clicking the Open file location menu button
}
{ "url", DocManagerHelper.GetServerUrl(false) }, // the absolute URL to the website address which will be opened when clicking the Open file location menu button
{ "text", user.goback.text },
{ "blank", user.goback.blank }
} : new Dictionary<string, object>{}
}
}
}
@ -289,20 +292,20 @@ namespace OnlineEditorsExampleMVC.Models
{
Path = HttpRuntime.AppDomainAppVirtualPath
+ (HttpRuntime.AppDomainAppVirtualPath.EndsWith("/") ? "" : "/")
+ "Content\\images\\logo.png"
+ "Content\\images\\logo.svg"
};
var directMailMergeUrl = new UriBuilder(DocManagerHelper.GetServerUrl(false))
{
Path = HttpRuntime.AppDomainAppVirtualPath
+ (HttpRuntime.AppDomainAppVirtualPath.EndsWith("/") ? "" : "/")
+ "Content\\images\\logo.png"
+ "Content\\images\\logo.svg"
};
// create a logo config
var logoConfig = new Dictionary<string, object>
{
{ "fileType", "png"},
{ "fileType", "svg"},
{ "url", mailMergeUrl.ToString()}
};

View File

@ -33,7 +33,8 @@ namespace OnlineEditorsExampleMVC.Models
{
Word,
Cell,
Slide
Slide,
Pdf
}
// get file type
@ -41,6 +42,7 @@ namespace OnlineEditorsExampleMVC.Models
{
var ext = Path.GetExtension(fileName).ToLower();
if (FormatManager.PdfExtensions().Contains(ext)) return FileType.Pdf; // pdf type for document extensions
if (FormatManager.DocumentExtensions().Contains(ext)) return FileType.Word; // word type for document extensions
if (FormatManager.SpreadsheetExtensions().Contains(ext)) return FileType.Cell; // cell type for spreadsheet extensions
if (FormatManager.PresentationExtensions().Contains(ext)) return FileType.Slide; // slide type for presentation extensions
@ -185,6 +187,20 @@ namespace OnlineEditorsExampleMVC.Models
.ToList();
}
public static List<string> PdfExtensions()
{
return Pdfs()
.Select(format => format.Extension())
.ToList();
}
public static List<Format> Pdfs()
{
return All()
.Where(format => format.Type == FileType.Pdf)
.ToList();
}
public static List<string> AllExtensions()
{
return All()

View File

@ -1,4 +1,4 @@
/**
/**
*
* (c) Copyright Ascensio System SIA 2024
*
@ -16,16 +16,15 @@
*
*/
package com.onlyoffice.integration.dto;
using System.Collections.Generic;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
namespace OnlineEditorsExampleMVC.Models
{
// create file model
public class ForgottenFilesModel
{
public List<Dictionary<string, string>> files { get; set; }
@Data
@AllArgsConstructor
@NoArgsConstructor
public class ChangesHistory {
private String created;
private ChangesUser user;
}
public ForgottenFilesModel(List<Dictionary<string, string>> files) { this.files = files; }
}
}

View File

@ -116,6 +116,7 @@
<Compile Include="Helpers\Utils.cs" />
<Compile Include="Models\FileModel.cs" />
<Compile Include="Models\FileUtility.cs" />
<Compile Include="Models\ForgottenFilesModel.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="WebEditor.ashx.cs">
<DependentUpon>WebEditor.ashx</DependentUpon>
@ -123,6 +124,7 @@
</ItemGroup>
<ItemGroup>
<Content Include="Content\editor.css" />
<Content Include="Content\forgotten.css" />
<Content Include="Content\images\block-content.svg" />
<Content Include="Content\images\cell.ico" />
<Content Include="Content\images\close.svg" />
@ -140,18 +142,20 @@
<Content Include="Content\images\file_xlsx.svg" />
<Content Include="Content\images\fill-forms.svg" />
<Content Include="Content\images\filter.svg" />
<Content Include="Content\images\home.svg" />
<Content Include="Content\images\icon_docx.svg" />
<Content Include="Content\images\icon_pptx.svg" />
<Content Include="Content\images\icon_xlsx.svg" />
<Content Include="Content\images\info.svg" />
<Content Include="Content\images\loader16.gif" />
<Content Include="Content\images\logo.png" />
<Content Include="Content\images\logo.svg" />
<Content Include="Content\images\mobile-fill-forms.svg" />
<Content Include="Content\images\mobile.svg" />
<Content Include="Content\images\notdone.svg" />
<Content Include="Content\images\review.svg" />
<Content Include="Content\images\slide.ico" />
<Content Include="Content\images\uid-1.png" />
<Content Include="Content\images\uid-2.png" />
<Content Include="Content\images\word.ico" />
<Content Include="Content\jquery-ui.css" />
<Content Include="Content\media.css" />
@ -159,6 +163,10 @@
<Content Include="favicon.ico" />
<Content Include="Global.asax" />
<Content Include="LICENSE" />
<Content Include="Scripts\forgotten.js" />
<Content Include="Scripts\formats.js" />
<Content Include="Scripts\jquery-3.6.4.js" />
<Content Include="Scripts\jquery-migrate-3.4.1.js" />
<Content Include="Scripts\jquery-ui.js" />
<Content Include="Scripts\jquery.blockUI.js" />
<Content Include="Scripts\jquery.dropdownToggle.js" />
@ -166,17 +174,13 @@
<Content Include="Scripts\jquery.iframe-transport.js" />
<Content Include="Scripts\jscript.js" />
<Content Include="Views\Home\Editor.aspx" />
<Content Include="Views\Home\Forgotten.aspx" />
<Content Include="Views\Home\Index.aspx" />
<Content Include="Web.config">
<SubType>Designer</SubType>
</Content>
<Content Include="Views\Web.config" />
<Content Include="Views\Shared\Error.aspx" />
<Content Include="licenses\EntityFramework.license" />
<Content Include="licenses\Microsoft.Web.Infrastructure.license" />
<Content Include="licenses\Newtonsoft.Json.license" />
<Content Include="licenses\jquery.license" />
<Content Include="licenses\WebGrease.license" />
<Content Include="web.appsettings.config" />
<Content Include="WebEditor.ashx" />
</ItemGroup>

View File

@ -0,0 +1,19 @@
function deleteFile(event) {
let filename = event.currentTarget.getAttribute("data");
filename = encodeURIComponent(filename);
let url = `webeditor.ashx?type=removeforgotten&filename=${filename}`;
fetch(url, {
headers: {
"Content-Type": "application/json",
}
}).then(result => {
if(result.status == 204) {
document.location.reload(true);
}
});
}
document.querySelectorAll('.delete-file').forEach(el => {
el.addEventListener('click', deleteFile);
});

View File

@ -0,0 +1,66 @@
/**
*
* (c) Copyright Ascensio System SIA 2024
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
class Format {
constructor(name, type, actions, convert, mime) {
this.name = name;
this.type = type;
this.actions = actions;
this.convert = convert;
this.mime = mime;
}
isAutoConvertible() {
return this.actions.includes('auto-convert');
}
isEditable() {
return this.actions.includes('edit') || this.actions.includes('lossy-edit');
}
isFillable() {
return this.actions.includes('fill');
}
}
class FormatManager {
formats = [];
constructor(formats) {
if(Array.isArray(formats)) this.formats = formats;
}
findByExtension(extension) {
return this.formats.find(format => format.name == extension);
}
isAutoConvertible(extension) {
let format = this.findByExtension(extension);
return format !== undefined && format.isAutoConvertible();
}
isEditable(extension) {
let format = this.findByExtension(extension);
return format !== undefined && format.isEditable();
}
isFillable(extension) {
let format = this.findByExtension(extension);
return format !== undefined && format.isFillable();
}
}

View File

@ -17,6 +17,27 @@
*/
var directUrl;
var formatManager;
window.onload = function () {
fetch("webeditor.ashx?type=formats")
.then((response) => response.json())
.then((data) => {
if (data.formats) {
let formats = [];
data.formats.forEach(format => {
formats.push(new Format(
format.Name,
format.Type,
format.Actions,
format.Convert,
format.Mime
));
});
formatManager = new FormatManager(formats);
}
})
}
if (typeof jQuery != "undefined") {
jq = jQuery.noConflict();
@ -87,8 +108,8 @@ if (typeof jQuery != "undefined") {
});
var timer = null;
var checkConvert = function (filePass) {
filePass = filePass ? filePass : null;
var checkConvert = function (filePass, fileType) {
filePass = filePass ? filePass : null;
if (timer != null) {
clearTimeout(timer);
}
@ -100,10 +121,10 @@ if (typeof jQuery != "undefined") {
jq("#filePass").val("");
var fileName = jq("#hiddenFileName").val();
var posExt = fileName.lastIndexOf('.');
var posExt = fileName.lastIndexOf('.') + 1;
posExt = 0 <= posExt ? fileName.substring(posExt).trim().toLowerCase() : '';
if (ConverExtList.indexOf(posExt) == -1) {
if (!formatManager.isAutoConvertible(posExt)) {
jq("#step2").addClass("done").removeClass("current");
loadScripts();
return;
@ -116,7 +137,7 @@ if (typeof jQuery != "undefined") {
contentType: "text/xml",
type: "post",
dataType: "json",
data: JSON.stringify({ filename: fileName, filePass: filePass }),
data: JSON.stringify({ filename: fileName, filePass: filePass, fileExt: fileType }),
url: UrlConverter,
complete: function (data) {
var responseText = data.responseText;
@ -132,6 +153,12 @@ if (typeof jQuery != "undefined") {
}
return;
} else {
if (response.error.includes("Error conversion output format")) {
jq("#select-file-type").removeClass("invisible");
jq("#step2").removeClass("current");
jq("#hiddenFileName").attr("placeholder", filePass);
return;
}
jq(".current").removeClass("current");
jq(".step:not(.done)").addClass("error");
jq("#mainProgress .error-message").show().find("span").text(response.error);
@ -143,7 +170,7 @@ if (typeof jQuery != "undefined") {
jq("#hiddenFileName").val(response.filename);
if (response.step && response.step < 100) {
checkConvert(filePass);
checkConvert(filePass, fileType);
} else {
jq("#step2").addClass("done").removeClass("current");
loadScripts();
@ -178,10 +205,10 @@ if (typeof jQuery != "undefined") {
jq("#beginView, #beginEmbedded").removeClass("disable");
var fileName = jq("#hiddenFileName").val();
var posExt = fileName.lastIndexOf('.');
var posExt = fileName.lastIndexOf('.') + 1;
posExt = 0 <= posExt ? fileName.substring(posExt).trim().toLowerCase() : '';
if (EditedExtList.indexOf(posExt) != -1 || FillExtList.indexOf(posExt) != -1) {
if (formatManager.isEditable(posExt) || formatManager.isFillable(posExt)) {
jq("#beginEdit").removeClass("disable");
}
};
@ -213,6 +240,15 @@ if (typeof jQuery != "undefined") {
});
};
jq(document).on("click", ".file-type:not(.disable)", function () {
const currentElement = jq(this);
var fileType = currentElement.attr("data");
var filePass = jq("#hiddenFileName").attr("placeholder");
jq('.file-type').addClass(["disable", "pale"]);
currentElement.removeClass("pale");
checkConvert(filePass, fileType);
});
jq(document).on("click", "#enterPass", function () {
var filePass = jq("#filePass").val();
if (filePass) {
@ -294,6 +330,23 @@ if (typeof jQuery != "undefined") {
});
});
jq(document).on("click", ".clear-all", function () {
if (confirm("Delete all the files?")) {
var requestAddress = "webeditor.ashx"
+ "?type=remove";
jq.ajax({
async: true,
contentType: "text/xml",
url: requestAddress,
complete: function (data) {
if (JSON.parse(data.responseText).success) {
window.location.reload(true);
}
}
});
}
});
function showUserTooltip (isMobile) {
if ( jq("div#portal-info").is(":hidden") ) {
jq("div#portal-info").show();
@ -368,4 +421,27 @@ if (typeof jQuery != "undefined") {
}).mouseout(function () {
jq("div.tooltip").remove();
});
}
}
function toggleSidePanel(event) {
event.preventDefault();
let sidePanel = document.querySelector(".left-panel");
let body = document.querySelector("body");
if (sidePanel.classList.contains("active")) {
sidePanel.classList.remove("active");
body.classList.remove("menu-open");
} else {
sidePanel.classList.add("active")
body.classList.add("menu-open");
}
}
function toggleUserDescr(event) {
let list = event.currentTarget.querySelector("ul");
let cursor = window.getComputedStyle(event.currentTarget).getPropertyValue("cursor");
if (cursor === "pointer") {
if (list.classList.contains("active")) list.classList.remove("active");
else list.classList.add("active");
}
}

View File

@ -108,7 +108,7 @@
// the meta information of the document is changed via the meta command
var onMetaChange = function (event) {
if (event.data.favorite) {
if (event.data.favorite !== undefined) {
var favorite = !!event.data.favorite;
var title = document.title.replace(/^\☆/g, "");
document.title = (favorite ? "☆" : "") + title;
@ -259,6 +259,48 @@
}
}
<% string usersForMentions; %>
<% Model.GetUsersMentions(Request, out usersForMentions); %>
<% string usersInfo; %>
<% Model.GetUsersInfo(Request, out usersInfo); %>
<% string usersForProtect; %>
<% Model.GetUsersProtect(Request, out usersForProtect); %>
var onRequestUsers = function (event) {
if (event && event.data){
var c = event.data.c;
}
switch (c) {
case "info":
users = [];
var allUsers = <%= usersInfo %>;
for (var i = 0; i < event.data.id.length; i++) {
for (var j = 0; j < allUsers.length; j++) {
if (allUsers[j].id == event.data.id[i]) {
users.push(allUsers[j]);
break;
}
}
}
break;
case "protect":
var users = <%= usersForProtect %>;
break;
default:
users = <%= usersForMentions %>;
}
docEditor.setUsers({
"c": c,
"users": users,
});
};
var onRequestSendNotify = function (event) {
event.data.actionLink = replaceActionLink(location.href, JSON.stringify(event.data.actionLink));
var data = JSON.stringify(event.data);
innerAlert("onRequestSendNotify: " + data);
};
config = <%= Model.GetDocConfig(Request, Url) %>;
config.width = "100%";
@ -276,63 +318,28 @@
"onRequestSelectSpreadsheet": onRequestSelectSpreadsheet,
};
<% string usersForMentions; %>
<% Model.GetUsersMentions(Request, out usersForMentions); %>
<% string usersInfo; %>
<% Model.GetUsersInfo(Request, out usersInfo); %>
<% string usersForProtect; %>
<% Model.GetUsersProtect(Request, out usersForProtect); %>
if (config.editorConfig.user.id) {
// the user is trying to show the document version history
config.events['onRequestHistory'] = onRequestHistory;
// the user is trying to click the specific document version in the document version history
config.events['onRequestHistoryData'] = onRequestHistoryData;
// the user is trying to go back to the document from viewing the document version history
config.events['onRequestHistoryClose'] = function () {
document.location.reload();
};
config.events['onRequestRestore'] = onRequestRestore;
if (config.editorConfig.user.id !== "uid-3") {
config.events['onRequestHistoryClose'] = function () {
document.location.reload();
};
config.events['onRequestRestore'] = onRequestRestore;
}
// add mentions for not anonymous users
<% if (!string.IsNullOrEmpty(usersForMentions))
{ %>
config.events['onRequestUsers'] = function (event) {
if (event && event.data){
var c = event.data.c;
}
switch (c) {
case "info":
users = [];
var allUsers = <%= usersInfo %>;
for (var i = 0; i < event.data.id.length; i++) {
for (var j = 0; j < allUsers.length; j++) {
if (allUsers[j].id == event.data.id[i]) {
users.push(allUsers[j]);
break;
}
}
}
break;
case "protect":
var users = <%= usersForProtect %>;
break;
default:
users = <%= usersForMentions %>;
}
docEditor.setUsers({
"c": c,
"users": users,
});
};
config.events['onRequestUsers'] = onRequestUsers;
<% } %>
config.events['onRequestSaveAs'] = onRequestSaveAs;
// 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);
};
config.events['onRequestSendNotify'] = onRequestSendNotify;
// prevent file renaming for anonymous users
config.events['onRequestRename'] = onRequestRename;
config.events['onRequestReferenceData'] = onRequestReferenceData;
@ -341,17 +348,7 @@
config.events['onRequestOpen'] = onRequestOpen;
}
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);
};

View File

@ -0,0 +1,144 @@
<%@ Page Title="ONLYOFFICE" Language="C#" Inherits="System.Web.Mvc.ViewPage<OnlineEditorsExampleMVC.Models.ForgottenFilesModel>" %>
<%@ Import Namespace="System.IO" %>
<%@ Import Namespace="System.Web.Configuration" %>
<%@ Import Namespace="OnlineEditorsExampleMVC.Helpers" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html lang="en">
<head runat="server">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width" />
<meta name="server-version" content=<%= DocManagerHelper.GetVersion() %> />
<!--
*
* (c) Copyright Ascensio System SIA 2024
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
-->
<title>ONLYOFFICE</title>
<link href="<%: Url.Content("~/favicon.ico") %>" rel="shortcut icon" type="image/x-icon" />
<link rel="stylesheet" type="text/css" href="https://fonts.googleapis.com/css?family=Open+Sans:900,800,700,600,500,400,300&subset=latin,cyrillic-ext,cyrillic,latin-ext" />
<%: Styles.Render("~/Content/css") %>
<%: Styles.Render("~/Content/forgotten") %>
</head>
<body>
<header>
<div class="center main-nav">
<a href="./">
<img src ="content/images/logo.svg" alt="ONLYOFFICE" />
</a>
</div>
<menu class="responsive-nav">
<li>
<a href="#" onclick="toggleSidePanel(event)">
<img src="content/images/mobile-menu.svg" alt="ONLYOFFICE" />
</a>
</li>
<li>
<a href="./">
<img src ="content/images/mobile-logo.svg" alt="ONLYOFFICE" />
</a>
</li>
</menu>
</header>
<div class="center main">
<table class="table-main">
<tbody>
<tr>
<td class="left-panel section"></td>
<td class="section">
<div class="main-panel">
<menu class="links">
<li class="home-link" >
<a href="./">
<img src="content/images/home.svg" alt="Home"/>
</a>
</li>
<li class="active">
<a href="/Forgotten">Forgotten files</a>
</li>
</menu>
<div class="stored-list">
<div class="storedHeader">
<div class="storedHeaderText">
<span class="header-list">Forgotten files</span>
</div>
</div>
<table class="tableHeader" cellspacing="0" cellpadding="0" width="100%">
<thead>
<tr>
<td class="tableHeaderCell">Filename</td>
<td class="tableHeaderCell">Action</td>
</tr>
</thead>
</table>
<div class="scroll-table-body">
<table cellspacing="0" cellpadding="0" width="100%">
<tbody>
<% foreach (var file in Model.files) { %>
<tr class="tableRow" title="<%= file["key"] %>">
<td>
<a class="stored-edit action-link <%= file["type"] %>" href="<%= file["url"] %>" target="_blank">
<span><%= file["key"] %></span>
</a>
</td>
<td>
<a href="<%= file["url"] %>">
<img class="icon-download" src="content/images/download.svg" alt="Download" title="Download" /></a>
<a class="delete-file" data="<%= file["key"] %>">
<img class="icon-action" src="content/images/delete.svg" alt="Delete" title="Delete" /></a>
</td>
</tr>
<% } %>
</tbody>
</table>
</div>
</div>
</div>
</td>
</tr>
</tbody>
</table>
</div>
<footer>
<div class="center">
<table>
<tbody>
<tr>
<td>
<a href="http://api.onlyoffice.com/editors/howitworks" target="_blank">API Documentation</a>
</td>
<td>
<a href="mailto:sales@onlyoffice.com">Submit your request</a>
</td>
<td class="copy">
&copy; Ascensio System SIA <%= DateTime.Now.Year.ToString() %>. All rights reserved.
</td>
</tr>
</tbody>
</table>
</div>
</footer>
<%: Scripts.Render("~/bundles/jquery", "~/bundles/forgotten") %>
</body>
</html>

View File

@ -41,11 +41,23 @@
</head>
<body>
<header>
<div class="center">
<a href="">
<div class="center main-nav">
<a href="./">
<img src ="content/images/logo.svg" alt="ONLYOFFICE" />
</a>
</div>
<menu class="responsive-nav">
<li>
<a href="#" onclick="toggleSidePanel(event)">
<img src="content/images/mobile-menu.svg" alt="ONLYOFFICE" />
</a>
</li>
<li>
<a href="./">
<img src ="content/images/mobile-logo.svg" alt="ONLYOFFICE" />
</a>
</li>
</menu>
</header>
<div class="center main">
@ -68,7 +80,7 @@
<a class="try-editor slide" data-type="pptx">Presentation</a>
</li>
<li>
<a class="try-editor form" data-type="docxf">PDF form</a>
<a class="try-editor form" data-type="pdf">PDF form</a>
</li>
</ul>
<label class="side-option">
@ -122,9 +134,24 @@
</tbody>
</table>
</div>
<button class="mobile-close-btn" onclick="toggleSidePanel(event)">
<img src="content/images/close.svg" alt="">
</button>
</td>
<td class="section">
<div class="main-panel">
<menu class="links">
<li class="home-link active" >
<a href="./">
<img src="content/images/home.svg" alt="Home"/>
</a>
</li>
<% if (bool.Parse(WebConfigurationManager.AppSettings["enable-forgotten"])) { %>
<li>
<a href="/Forgotten">Forgotten files</a>
</li>
<% } %>
</menu>
<% var storedFiles = DocManagerHelper.GetStoredFiles(); %>
<div id="portal-info" style="display: <%= storedFiles.Any() ? "none" : "table-cell" %>">
<span class="portal-name">ONLYOFFICE Document Editors Welcome!</span>
@ -136,7 +163,7 @@
<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())
{ %>
<div class="user-descr">
<div class="user-descr" onclick="toggleUserDescr(event)">
<b><%= user.name.IsEmpty() ? "Anonymous" : user.name %></b>
<ul>
<% foreach (string description in user.descriptions)
@ -151,7 +178,14 @@
if (storedFiles.Any())
{ %>
<div class="stored-list">
<span class="header-list">Your documents</span>
<div class="storedHeader">
<div class="storedHeaderText">
<span class="header-list">Your documents</span>
</div>
<div class="storedHeaderClearAll">
<div class="clear-all">Clear all</div>
</div>
</div>
<table class="tableHeader" cellspacing="0" cellpadding="0" width="100%">
<thead>
<tr>
@ -193,11 +227,13 @@
<img src="content/images/mobile.svg" alt="Open in editor for mobile devices" title="Open in editor for mobile devices"/>
</a>
</td>
<td class="contentCells contentCells-icon">
<a href="<%= Url.Action("Editor", "Home", new { fileName = storedFile.Name, editorsType = "desktop", editorsMode = "comment", directUrl = isEnabledDirectUrl }) %>" target="_blank">
<img src="content/images/comment.svg" alt="Open in editor for comment" title="Open in editor for comment"/>
</a>
</td>
<% if (docType != "pdf") { %>
<td class="contentCells contentCells-icon">
<a href="<%= Url.Action("Editor", "Home", new { fileName = storedFile.Name, editorsType = "desktop", editorsMode = "comment", directUrl = isEnabledDirectUrl }) %>" target="_blank">
<img src="content/images/comment.svg" alt="Open in editor for comment" title="Open in editor for comment"/>
</a>
</td>
<% } %>
<% if (docType == "word") { %>
<td class="contentCells contentCells-icon">
<a href="<%= Url.Action("Editor", "Home", new { fileName = storedFile.Name, editorsType = "desktop", editorsMode = "review", directUrl = isEnabledDirectUrl }) %>" target="_blank">
@ -295,6 +331,15 @@
<div class="describeUpload">After these steps are completed, you can work with your document.</div>
<span id="step1" class="step">1. Loading the file.</span>
<span class="step-descr">The loading speed depends on file size and additional elements it contains.</span>
<div id="select-file-type" class="invisible">
<br />
<span class="step">Please select the current document type</span>
<div class="buttonsMobile indent">
<div class="button file-type document" data="docx">Document</div>
<div class="button file-type spreadsheet" data="xlsx">Spreadsheet</div>
<div class="button file-type presentation" data="pptx">Presentation</div>
</div>
</div>
<br />
<span id="step2" class="step">2. Conversion.</span>
<span class="step-descr">The file is converted to OOXML so that you can edit it.</span>
@ -357,9 +402,6 @@
<%: Scripts.Render("~/bundles/jquery", "~/bundles/scripts") %>
<script language="javascript" type="text/javascript">
var FillExtList = '<%= string.Join(",", DocManagerHelper.FillFormExts.ToArray()) %>';
var ConverExtList = '<%= string.Join(",", DocManagerHelper.ConvertExts.ToArray()) %>';
var EditedExtList = '<%= string.Join(",", DocManagerHelper.EditedExts.ToArray()) %>';
var UrlConverter = '<%= Url.Content("~/webeditor.ashx?type=convert") %>';
var UrlEditor = '<%= Url.Action("editor", "Home") %>';
</script>

View File

@ -26,6 +26,7 @@
<hgroup>
<h1>Error.</h1>
<h2>An error occurred while processing your request.</h2>
<p><%= ViewData["Message"] %></p>
</hgroup>
</body>
</html>

View File

@ -69,6 +69,9 @@ namespace OnlineEditorsExampleMVC
case "remove":
Remove(context);
break;
case "removeforgotten":
RemoveForgotten(context);
break;
case "assets":
Assets(context);
break;
@ -87,6 +90,9 @@ namespace OnlineEditorsExampleMVC
case "reference":
Reference(context);
break;
case "formats":
Formats(context);
break;
}
}
@ -240,7 +246,13 @@ namespace OnlineEditorsExampleMVC
var fileUri = DocManagerHelper.GetDownloadUrl(fileName);
var extension = (Path.GetExtension(fileName).ToLower() ?? "").Trim('.');
var internalExtension = "ooxml";
string conversionExtension = "ooxml";
object fileExt;
if (body.TryGetValue("fileExt", out fileExt) && !String.IsNullOrEmpty(fileExt.ToString()))
{
conversionExtension = fileExt.ToString();
}
// check if the file with such an extension can be converted
if (DocManagerHelper.ConvertExts.Contains("." + extension))
@ -258,7 +270,7 @@ namespace OnlineEditorsExampleMVC
// get the url and file type of the converted file
Dictionary<string, string> newFileData;
var result = ServiceConverter.GetConvertedData(downloadUri.ToString(), extension, internalExtension, key, true, out newFileData, filePass, lang);
var result = ServiceConverter.GetConvertedData(downloadUri.ToString(), extension, conversionExtension, key, true, out newFileData, filePass, lang);
if (result != 100)
{
context.Response.Write("{ \"step\" : \"" + result + "\", \"filename\" : \"" + fileName + "\"}");
@ -393,8 +405,17 @@ namespace OnlineEditorsExampleMVC
context.Response.ContentType = "text/plain";
try
{
var fileName = Path.GetFileName(context.Request["fileName"]);
Remove(fileName); // remove a file and its history if it exists
string fileName = context.Request["fileName"];
if (!String.IsNullOrEmpty(fileName))
{
fileName = Path.GetFileName(context.Request["fileName"]);
Remove(fileName); // remove a file and its history if it exists
}
else
{
RemoveUserDirectory(); // remove the user's directory
}
context.Response.Write("{ \"success\": true }");
}
@ -414,6 +435,14 @@ namespace OnlineEditorsExampleMVC
if (Directory.Exists(histDir)) Directory.Delete(histDir, true);
}
// remove the user's directory
private static void RemoveUserDirectory()
{
var path = DocManagerHelper.StoragePath("", null); // get the path to the user directory
if (Directory.Exists(path)) Directory.Delete(path, true);
}
// get files information
private static void Files(HttpContext context)
{
@ -951,6 +980,51 @@ namespace OnlineEditorsExampleMVC
return history;
}
// return all the supported formats
private static void Formats(HttpContext context)
{
try
{
Dictionary<string, object> data = new Dictionary<string, object>
{
{ "formats", FormatManager.All() }
};
context.Response.ContentType = "application/json";
var jss = new JavaScriptSerializer();
context.Response.Write(jss.Serialize(data));
}
catch (Exception e)
{
context.Response.Write("{ \"error\": \"" + e.Message + "\"}");
}
}
// delete a forgotten file from the document server
private static void RemoveForgotten(HttpContext context)
{
try
{
if (!bool.Parse(WebConfigurationManager.AppSettings["enable-forgotten"]))
{
throw new HttpException(403, "The forgotten page is disabled");
}
string filename = context.Request["filename"];
if (!String.IsNullOrEmpty(filename))
{
TrackManager.commandRequest("deleteForgotten", filename);
}
context.Response.StatusCode = 204;
}
catch (Exception e)
{
context.Response.StatusCode = 500;
context.Response.Write("{ \"error\": \"" + e.Message + "\"}");
}
}
}
}

View File

@ -1,11 +1,12 @@
<?xml version="1.0"?>
<appSettings>
<clear />
<add key="version" value="1.9.0"/>
<add key="version" value="1.11.0"/>
<add key="filesize-max" value="52428800"/>
<add key="storage-path" value=""/>
<add key="filename-max" value="50"/>
<add key="enable-forgotten" value="true"/>
<add key="files.docservice.timeout" value="120000" />
<add key="files.docservice.secret" value="" />
@ -15,14 +16,14 @@
<add key="files.docservice.verify-peer-off" value="true"/>
<add key="files.docservice.languages" value="en:English|ar:Arabic|hy:Armenian|az:Azerbaijani|eu:Basque|be:Belarusian|bg:Bulgarian|ca:Catalan|zh:Chinese (Simplified)|zh-TW:Chinese (Traditional)|cs:Czech|da:Danish|nl:Dutch|en-GB:English (United Kingdom)|fi:Finnish|fr:French|gl:Galego|de:German|el:Greek|hu:Hungarian|id:Indonesian|it:Italian|ja:Japanese|ko:Korean|lo:Lao|lv:Latvian|ms:Malay (Malaysia)|no:Norwegian|pl:Polish|pt:Portuguese (Brazil)|pt-PT:Portuguese (Portugal)|ro:Romanian|ru:Russian|sr-Cyrl-RS:Serbian (Cyrillic)|sr-Latn-RS:Serbian (Latin)|si:Sinhala (Sri Lanka)|sk:Slovak|sl:Slovenian|es:Spanish|sv:Swedish|tr:Turkish|uk:Ukrainian|vi:Vietnamese|aa-AA:Test Language"/>
<add key="files.docservice.languages" value="en:English|ar:Arabic|hy:Armenian|az:Azerbaijani|eu:Basque|be:Belarusian|bg:Bulgarian|ca:Catalan|zh:Chinese (Simplified)|zh-TW:Chinese (Traditional)|cs:Czech|da:Danish|nl:Dutch|en-GB:English (United Kingdom)|fi:Finnish|fr:French|gl:Galego|de:German|el:Greek|he-IL:Hebrew (Israel)|hu:Hungarian|id:Indonesian|it:Italian|ja:Japanese|ko:Korean|lo:Lao|lv:Latvian|ms:Malay (Malaysia)|no:Norwegian|pl:Polish|pt:Portuguese (Brazil)|pt-PT:Portuguese (Portugal)|ro:Romanian|ru:Russian|sr-Cyrl-RS:Serbian (Cyrillic)|sr-Latn-RS:Serbian (Latin)|si:Sinhala (Sri Lanka)|sk:Slovak|sl:Slovenian|es:Spanish|sv:Swedish|tr:Turkish|uk:Ukrainian|vi:Vietnamese|aa-AA:Test Language"/>
<add key="files.docservice.url.site" value="http://documentserver/"/>
<add key="files.docservice.url.converter" value="ConvertService.ashx"/>
<add key="files.docservice.url.converter" value="converter"/>
<add key="files.docservice.url.api" value="web-apps/apps/api/documents/api.js"/>
<add key="files.docservice.url.preloader" value="web-apps/apps/api/documents/cache-scripts.html"/>
<add key="files.docservice.url.command" value="coauthoring/CommandService.ashx"/>
<add key="files.docservice.url.command" value="command"/>
<add key="files.docservice.url.example" value=""/>

View File

@ -0,0 +1,161 @@
.center {
width: auto;
}
.left-panel {
width: 256px;
}
.main-panel {
width: 832px;
margin: 0 32px;
padding: 48px 0;
left: 0;
}
.tableRow {
display: flex;
width: 100%;
justify-content: space-between;
align-items: center;
border-bottom: 1px solid #E2E2E2;
}
.tableRow td:first-child {
width: 70%;
flex-grow: 0;
max-width: none;
}
.tableHeader td:first-child {
text-align: left;
}
.tableHeader td:last-child, .tableRow td:last-child {
width: 10%;
text-align: center;
padding: 0 !important;
}
.tableHeader {
width: 100%;
}
.stored-edit {
display: block;
padding-top: 0;
max-width: none;
}
menu.links {
width: 100%;
}
.scroll-table-body table {
table-layout: fixed;
}
.stored-edit span {
font-size: 12px;
line-height: normal;
position: static;
}
.scroll-table-body {
overflow-y: auto;
}
.stored-list {
height: calc(100% - 58px);
}
header {
min-width:auto;
}
header a {
display: block;
margin: 0 auto;
width: 1152px;
}
@media (max-width: 1279px) and (min-width: 1024px) {
.left-panel {
width: 208px;
}
.main-panel {
width: 688px;
}
header a {
width: 928px;
}
header img {
margin-left: 16px;
}
}
@media (max-width: 1023px) and (min-width: 593px) {
.center {
max-width: 768px;
width: calc(100% - 80px);
}
.table-main {
width: 100%;
}
.left-panel {
width: 208px;
}
.main-panel {
width: calc(100% - 32px);
}
.tableHeader td:last-child, .tableRow td:last-child {
width: 20%;
}
header a {
width: 768px;
}
header img {
margin-left: 40px;
}
}
@media (max-width: 592px) and (min-width: 320px) {
.center, .table-main {
width: 100%;
}
.left-panel {
display: none;
}
.main-panel {
width: 100%;
margin: 0;
padding: 28px 16px;
}
.tableHeader td:last-child, .tableRow td:last-child {
width: 25%;
}
header a {
width: auto;
}
.scroll-table-body {
top: 40px;
}
.tableRow {
padding: 8px 0;
}
}

View File

@ -1 +0,0 @@
<svg width="30" height="40" viewBox="0 0 30 40" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M0 3c0-1.65685 1.34315-3 3-3h20l7 7v30c0 1.6569-1.3431 3-3 3H3c-1.65685 0-3-1.3431-3-3V3z" fill="#27ABA3"/><path d="M23 0l7 7h-4c-1.6569 0-3-1.34315-3-3V0z" fill="#008078"/><path fill-rule="evenodd" clip-rule="evenodd" d="M24 14H6v7h18v-7zm-.8182 5.9978H6.81818V15H23.1818v4.9978zM24 23H6v7h18v-7zm-.8182 5.9978H6.81818V24H23.1818v4.9978z" fill="#fff"/></svg>

Before

Width:  |  Height:  |  Size: 463 B

View File

@ -0,0 +1,5 @@
<svg width="30" height="40" viewBox="0 0 30 40" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M0 3C0 1.34315 1.34315 0 3 0H23L30 7V37C30 38.6569 28.6569 40 27 40H3C1.34315 40 0 38.6569 0 37V3Z" fill="#9E1919"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M17.0062 15V16.0065H24V15H17.0062ZM17.0062 19V20.0163H24V19H17.0062ZM24 23H17.0062V24.0261H24V23ZM6 28V27.0293H24V28H6ZM7 16H14V23H7V16ZM6 15H7H14H15V16V23V24H14H7H6V23V16V15Z" fill="white"/>
<path d="M23 0L30 7H26C24.3431 7 23 5.65685 23 4V0Z" fill="black" fill-opacity="0.25"/>
</svg>

After

Width:  |  Height:  |  Size: 558 B

View File

@ -0,0 +1,3 @@
<svg width="20" height="17" viewBox="0 0 20 17" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M8 17V11H12V17H17V9H20L10 0L0 9H3V17H8Z" fill="#444444"/>
</svg>

After

Width:  |  Height:  |  Size: 173 B

View File

@ -0,0 +1 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M2 1h8l4 4v10H2V1z" fill="#fff"/><path fill-rule="evenodd" clip-rule="evenodd" d="M14 5l-4-4H2v14h12V5zm-4-5l5 5v11H1V0h9z" fill="#BFBFBF"/><path fill="#9E1919" d="M3 10h10v4H3z"/><path d="M7 7V2H3v5h4zM8 3V2h2v1H8zM8 5V4h5v1H8zM13 6H8v1h5V6zM13 8H3v1h10V8z" fill="#BFBFBF"/><path opacity=".3" d="M9 1h1v3h4l1 1H9V1z" fill="#333"/></svg>

After

Width:  |  Height:  |  Size: 441 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

View File

@ -0,0 +1,5 @@
<svg width="24" height="23" viewBox="0 0 24 23" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M10.5332 22.2243L0.632544 17.5921C-0.210848 17.1877 -0.210848 16.5627 0.632544 16.1951L4.07945 14.5775L10.4966 17.5921C11.34 17.9965 12.6967 17.9965 13.5034 17.5921L19.9206 14.5775L23.3675 16.1951C24.2108 16.5995 24.2108 17.2245 23.3675 17.5921L13.4668 22.2243C12.6967 22.592 11.34 22.592 10.5332 22.2243Z" fill="#FF6F3D"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M10.5011 16.4922L0.630617 11.8546C-0.210206 11.4497 -0.210206 10.824 0.630617 10.456L3.99391 8.87329L10.5011 11.9282C11.342 12.3331 12.6946 12.3331 13.4989 11.9282L20.0061 8.87329L23.3694 10.456C24.2102 10.8608 24.2102 11.4865 23.3694 11.8546L13.4989 16.4922C12.658 16.897 11.3054 16.897 10.5011 16.4922Z" fill="#95C038"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M10.5011 10.8195L0.630617 6.24863C-0.210206 5.84959 -0.210206 5.23289 0.630617 4.87013L10.5011 0.299281C11.342 -0.0997605 12.6946 -0.0997605 13.4989 0.299281L23.3694 4.87013C24.2102 5.26917 24.2102 5.88587 23.3694 6.24863L13.4989 10.8195C12.658 11.1822 11.3054 11.1822 10.5011 10.8195Z" fill="#5DC0E8"/>
</svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@ -0,0 +1,5 @@
<svg width="20" height="14" viewBox="0 0 20 14" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect width="20" height="2" rx="1" fill="white"/>
<rect y="6" width="20" height="2" rx="1" fill="white"/>
<rect y="12" width="20" height="2" rx="1" fill="white"/>
</svg>

After

Width:  |  Height:  |  Size: 278 B

View 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="M13 17C13 17.5523 12.5523 18 12 18C11.4477 18 11 17.5523 11 17V13H7C6.44772 13 6 12.5523 6 12C6 11.4477 6.44772 11 7 11H11V7C11 6.44772 11.4477 6 12 6C12.5523 6 13 6.44772 13 7V11H17C17.5523 11 18 11.4477 18 12C18 12.5523 17.5523 13 17 13H13V17Z" fill="#444444"/>
</svg>

After

Width:  |  Height:  |  Size: 416 B

View File

@ -79,7 +79,8 @@
margin-left: 0;
}
.tableRow {
.tableRow,
menu.links {
width: 90%;
}
@ -119,7 +120,8 @@
.contentCells-icon{
width: 5%;
}
.tableRow {
.tableRow,
menu.links {
width: 55%;
}
@ -175,7 +177,8 @@
}
@media (max-width: 715px) {
.tableRow {
.tableRow,
menu.links {
width: 45%;
}
}
@ -263,7 +266,8 @@
padding-left: 0;
}
.tableRow {
.tableRow,
menu.links {
width: 75%;
}
@ -293,7 +297,8 @@
width: 580px;
}
.tableRow {
.tableRow,
menu.links {
width: 95%;
}
@ -407,7 +412,8 @@
padding: 16px 0 6px;
}
.tableRow {
.tableRow,
menu.links {
width: 40%;
}
@ -502,6 +508,17 @@
justify-content: space-between;
align-items: center;
}
.buttonsMobile.indent {
margin-bottom: 0;
flex-wrap: nowrap;
}
.button.file-type:hover,
.button.file-type {
height: 28px;
width: 100px;
margin-bottom: 10px !important;
font-size: 9px;
}
.button.gray{
margin: 0;
}
@ -527,7 +544,8 @@
}
@media (max-width: 510px) and (min-width: 470px) {
.tableRow {
.tableRow,
menu.links {
width: 35%;
}
@ -553,7 +571,8 @@
}
@media (max-width: 470px) and (min-width: 420px) {
.tableRow {
.tableRow,
menu.links {
width: 30%;
}
.tableRow td:first-child{
@ -588,7 +607,8 @@
}
@media (max-width: 420px) and (min-width: 320px) {
.tableRow {
.tableRow,
menu.links {
width: 25%;
}
@ -638,7 +658,8 @@
}
}
@media (max-width: 769px) and (min-width: 715px){
.tableRow{
.tableRow,
menu.links {
width: 50%;
}
}
@ -687,3 +708,216 @@
max-width: none;
}
}
@media (max-width: 592px) and (min-width: 320px) {
body.menu-open {
overflow: hidden;
}
header {
min-width: auto;
height: fit-content;
}
header a {
display: block;
}
header img {
margin: 0;
}
header, footer {
position: -webkit-sticky; /* Safari */
position: sticky;
top: 0;
z-index: 100;
}
.center {
width: 100%;
margin: 0;
}
.left-panel {
background-color: rgba(186, 186, 186, 0.6);
display: none;
flex-direction: row;
align-items: start;
max-width: none;
width: 100%;
margin: 0;
position: fixed;
left: 0;
height: calc(100% - 124px);
z-index:99;
}
.left-panel.active {
display: flex;
}
.help-block {
height: 100%;
margin: 0;
background-color: #F5F5F5;
width: 248px;
padding-left: 16px;
padding-top: 33px;
padding-bottom: 33px;
padding-right: 40px;
box-sizing: border-box;
overflow-y: auto;
overflow-x: hidden;
}
.table-main {
width: 100%;
}
.mobile-close-btn {
display: block;
width: 48px;
height: 48px;
background-color: #E2E2E2;
border-radius: 2px;
border-color: #E2E2E2;
color: #808080;
cursor: pointer;
outline: inherit;
border: none;
}
.main-panel {
width: 100%;
left: 0;
padding: 28px 16px;
}
#portal-info {
width: 100%;
max-width: fit-content;
}
menu.links {
width: 100%;
margin-top: 0;
padding: 0;
}
span.portal-name {
font-size: 16px;
}
span.portal-descr:first-child {
font-size: 13px;
}
span.portal-descr {
font-size: 12px;
}
.user-descr {
width: 100%;
max-width: none;
min-width: auto;
border-bottom: 1px solid #E5E5E5;
padding: 12px 0;
margin: 0;
cursor: pointer;
}
.user-descr ul {
display: none;
}
.user-descr ul.active {
display: block;
}
.user-descr b {
font-size: 13px;
display: flex;
align-items: center;
column-gap: 8px;
margin: 0;
}
.user-descr b::before {
content: url("images/plus.svg");
display: inline-block;
width: 24px;
height: 24px;
}
.storedHeader {
width: 100%;
}
.storedHeaderClearAll {
padding-right: 0;
}
.scroll-table-body {
top: 36px;
}
.scroll-table-body tr:first-child {
padding-top: 0;
}
.tableRow {
border-bottom: 1px solid #e5e5e5;
padding: 16px 0;
width: 100%;
}
.tableRow td:first-child {
width: 100%;
}
.stored-edit span {
font-size: 14px;
}
.header-list {
font-size: 16px;
}
.firstContentCellViewers {
border-bottom: none !important;
}
.firstContentCellViewers ~ td {
border-bottom: none !important;
}
.downloadContentCellShift:after {
display: none;
}
.main-nav {
display: none;
}
.responsive-nav {
height: 44px;
display: flex;
flex-direction: row;
margin: 0;
align-items: center;
column-gap: 16px;
padding: 10px 16px;
width: 100%;
box-sizing: border-box;
list-style: none;
}
.main {
height: calc(100% - 124px);
}
.user-block-table {
height: auto;
}
}

View File

@ -65,6 +65,14 @@ header img {
margin: 10px 0 22px 32px;
}
.responsive-nav {
display: none;
}
.mobile-close-btn {
display: none;
}
.center {
position: relative;
margin: 0 auto 0;
@ -164,7 +172,7 @@ label .checkbox {
}
.try-editor.form {
background-image: url("images/file_docxf.svg");
background-image: url("images/file_pdf.svg");
}
.side-option {
@ -230,6 +238,33 @@ label .checkbox {
color: #FF6F3D;
}
.button.file-type {
font-size: 11px;
color: #FFFFFF;
padding: 8px 8px;
margin-right: 10px;
}
.button.file-type.disable {
cursor: default;
}
.button.file-type.pale {
opacity: 30%;
}
.button.file-type.document {
background: #446995;
}
.button.file-type.spreadsheet {
background: #40865C;
}
.button.file-type.presentation {
background: #AA5252;
}
.upload-panel {
float: left;
padding: 24px 0;
@ -271,6 +306,43 @@ label .checkbox {
border-bottom: 1px solid #D0D5DA;
}
.links {
display: flex;
padding: 0;
column-gap: 30px;
align-items: center;
list-style: none;
border-bottom: 1px solid #E2E2E2;
margin: 0;
margin-bottom: 24px;
}
.links li {
padding: 4px;
border-bottom: 2px solid transparent;
margin-bottom: -1px;
}
.links li.active {
border-bottom: 2px solid #FF6F3D;
}
.links li.active a {
color: #FF6F3D;
}
.links li.active a img {
filter: invert(55%) sepia(67%) saturate(2727%) hue-rotate(335deg) brightness(104%) contrast(101%);
}
.links a {
display: inline-block;
padding: 2px 0;
line-height: 20px;
font-size: 13px;
text-decoration: none;
}
#mainProgress {
color: #333333;
display: none;
@ -468,6 +540,11 @@ footer a:hover {
background-image: url("images/icon_pptx.svg");
}
.stored-edit.pdf,
.uploadFileName.pdf {
background-image: url("images/icon_pdf.svg");
}
.stored-edit span {
font-size: 12px;
line-height: 12px;
@ -596,6 +673,29 @@ footer a:hover {
width: 4%;
}
.storedHeader {
display: flex;
width: 100%;
justify-content: space-between;
align-items: center;
}
.storedHeaderClearAll {
padding-right: 52px;
}
.clear-all {
display: inline-block;
width: 100px;
padding: 2px;
outline: 1px solid #E5E5E5;
text-align: center;
cursor:pointer;
text-transform: uppercase;
background-color: #F5F5F5;
color: #666666;
}
.select-user {
color: #444444;
font-family: Open Sans;
@ -745,6 +845,16 @@ html {
margin-left: 25px;
}
.buttonsMobile.indent{
padding-left: 35px;
margin-top: 10px;
margin-bottom: 10px;
}
.invisible {
display: none;
}
.tooltip {
background: #FFFFFF;
border-radius: 5px;

View File

@ -45,11 +45,23 @@
<body>
<form id="form1" runat="server">
<header>
<div class="center">
<a href="">
<div class="center main-nav">
<a href="./">
<img src ="app_themes/images/logo.svg" alt="ONLYOFFICE" />
</a>
</div>
<menu class="responsive-nav">
<li>
<a href="#" onclick="toggleSidePanel(event)">
<img src="app_themes/images/mobile-menu.svg" alt="ONLYOFFICE" />
</a>
</li>
<li>
<a href="./">
<img src ="app_themes/images/mobile-logo.svg" alt="ONLYOFFICE" />
</a>
</li>
</menu>
</header>
<div class="center main">
<table class="table-main">
@ -71,7 +83,7 @@
<a class="try-editor slide" data-type="slide">Presentation</a>
</li>
<li>
<a class="try-editor form" data-type="docxf">PDF form</a>
<a class="try-editor form" data-type="pdf">PDF form</a>
</li>
</ul>
<label class="side-option">
@ -124,10 +136,25 @@
</tbody>
</table>
</div>
<button class="mobile-close-btn" onclick="toggleSidePanel(event)">
<img src="app_themes/images/close.svg" alt="">
</button>
</td>
<td class="section">
<% var storedFiles = GetStoredFiles(); %>
<div class="main-panel">
<menu class="links">
<li class="home-link active" >
<a href="./">
<img src="app_themes/images/home.svg" alt="Home"/>
</a>
</li>
<% if (bool.Parse(WebConfigurationManager.AppSettings["enable-forgotten"])) { %>
<li>
<a href="/Forgotten.aspx">Forgotten files</a>
</li>
<% } %>
</menu>
<div id="portal-info" style="display: <%= storedFiles.Any() ? "none" : "table-cell" %>">
<span class="portal-name">ONLYOFFICE Document Editors Welcome!</span>
<span class="portal-descr">
@ -138,7 +165,7 @@
<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())
{ %>
<div class="user-descr">
<div class="user-descr" onclick="toggleUserDescr(event)">
<b><%= user.name.IsEmpty() ? "Anonymous" : user.name %></b>
<ul>
<% foreach (string description in user.descriptions)
@ -153,7 +180,14 @@
if (storedFiles.Any())
{ %>
<div class="stored-list">
<span class="header-list">Your documents</span>
<div class="storedHeader">
<div class="storedHeaderText">
<span class="header-list">Your documents</span>
</div>
<div class="storedHeaderClearAll">
<div class="clear-all">Clear all</div>
</div>
</div>
<table class="tableHeader" cellspacing="0" cellpadding="0" width="100%">
<thead>
<tr >
@ -195,11 +229,13 @@
<img src="app_themes/images/mobile.svg" alt="Open in editor for mobile devices" title="Open in editor for mobile devices"/>
</a>
</td>
<td class="contentCells contentCells-icon">
<a href="<%= editUrl + "&editorsType=desktop&editorsMode=comment" %>" target="_blank">
<img src="app_themes/images/comment.svg" alt="Open in editor for comment" title="Open in editor for comment"/>
</a>
</td>
<% if (docType != "pdf") { %>
<td class="contentCells contentCells-icon">
<a href="<%= editUrl + "&editorsType=desktop&editorsMode=comment" %>" target="_blank">
<img src="app_themes/images/comment.svg" alt="Open in editor for comment" title="Open in editor for comment"/>
</a>
</td>
<% } %>
<% if (docType == "word") { %>
<td class="contentCells contentCells-icon">
<a href="<%= editUrl + "&editorsType=desktop&editorsMode=review" %>" target="_blank">
@ -297,6 +333,15 @@
<div class="describeUpload">After these steps are completed, you can work with your document.</div>
<span id="step1" class="step">1. Loading the file.</span>
<span class="step-descr">The loading speed depends on file size and additional elements it contains.</span>
<div id="select-file-type" class="invisible">
<br />
<span class="step">Please select the current document type</span>
<div class="buttonsMobile indent">
<div class="button file-type document" data="docx">Document</div>
<div class="button file-type spreadsheet" data="xlsx">Spreadsheet</div>
<div class="button file-type presentation" data="pptx">Presentation</div>
</div>
</div>
<br />
<span id="step2" class="step">2. Conversion.</span>
<span class="step-descr">The file is converted to OOXML so that you can edit it.</span>
@ -364,12 +409,8 @@
<script language="javascript" type="text/javascript" src="script/jquery.iframe-transport.js"></script>
<script language="javascript" type="text/javascript" src="script/jquery.fileupload.js"></script>
<script language="javascript" type="text/javascript" src="script/jquery.dropdownToggle.js"></script>
<script language="javascript" type="text/javascript" src="script/formats.js"></script>
<script language="javascript" type="text/javascript" src="script/jscript.js"></script>
<script language="javascript" type="text/javascript">
var FillFormExtList = '<%= string.Join(",", FillFormsExts.ToArray()) %>';
var ConverExtList = '<%= string.Join(",", ConvertExts.ToArray()) %>';
var EditedExtList = '<%= string.Join(",", EditedExts.ToArray()) %>';
</script>
</body>
</html>

View File

@ -250,6 +250,7 @@ namespace OnlineEditorsExample
{
var ext = Path.GetExtension(fileName).ToLower();
if (FormatManager.PdfExtensions().Contains(ext)) return "pdf"; // pdf for pdf extensions
if (FormatManager.DocumentExtensions().Contains(ext)) return "word"; // word for text document extensions
if (FormatManager.SpreadsheetExtensions().Contains(ext)) return "cell"; // cell for spreadsheet extensions
if (FormatManager.PresentationExtensions().Contains(ext)) return "slide"; // slide for presentation extensions
@ -437,7 +438,14 @@ namespace OnlineEditorsExample
var lang = context.Request.Cookies.GetOrDefault("ulang", null);
var extension = (Path.GetExtension(_fileName).ToLower() ?? "").Trim('.');
var internalExtension = "ooxml";
string conversionExtension = "ooxml"; // set the default conversion extension as ooxml
object fileExt;
// change the conversion extension if it was provided in the request body
if (body.TryGetValue("fileExt", out fileExt) && !String.IsNullOrEmpty(fileExt.ToString()))
{
conversionExtension = fileExt.ToString();
}
// check if the file with such an extension can be converted
if (ConvertExts.Contains("." + extension))
@ -454,7 +462,7 @@ namespace OnlineEditorsExample
// get the url and file type of the converted file
Dictionary<string, string> newFileData;
var result = ServiceConverter.GetConvertedData(fileUrl.ToString() , extension, internalExtension, key, true, out newFileData, filePass, lang);
var result = ServiceConverter.GetConvertedData(fileUrl.ToString() , extension, conversionExtension, key, true, out newFileData, filePass, lang);
if (result != 100)
{
return "{ \"step\" : \"" + result + "\", \"filename\" : \"" + _fileName + "\"}";

View File

@ -126,7 +126,7 @@
// the meta information of the document is changed via the meta command
var onMetaChange = function (event) {
if (event.data.favorite) {
if (event.data.favorite !== undefined) {
var favorite = !!event.data.favorite;
var title = document.title.replace(/^\☆/g, "");
document.title = (favorite ? "☆" : "") + title;
@ -233,6 +233,41 @@
}
};
var onRequestUsers = function (event) {
if (event && event.data){
var c = event.data.c;
}
switch (c) {
case "info":
users = [];
var allUsers = <%= UsersInfo %>;
for (var i = 0; i < event.data.id.length; i++) {
for (var j = 0; j < allUsers.length; j++) {
if (allUsers[j].id == event.data.id[i]) {
users.push(allUsers[j]);
break;
}
}
}
break;
case "protect":
var users = <%= UsersForProtect %>;
break;
default:
users = <%= UsersForMentions %>;
}
docEditor.setUsers({
"c": c,
"users": users,
});
};
var onRequestSendNotify = function (event) {
event.data.actionLink = replaceActionLink(location.href, JSON.stringify(event.data.actionLink));
var data = JSON.stringify(event.data);
innerAlert("onRequestSendNotify: " + data);
};
config = <%= DocConfig %>;
config.width = "100%";
@ -275,65 +310,37 @@
docEditor.setHistoryData(JSON.parse(xhr.responseText)); // send the link to the document for viewing the version history
}
};
config.events['onRequestHistoryClose'] = function () { // the user is trying to go back to the document from viewing the document version history
document.location.reload();
};
config.events['onRequestRestore'] = function (event) {
var fileName = "<%= FileName %>";
var version = event.data.version;
var data = {
fileName: fileName,
version: version
if (config.editorConfig.user.id !== "uid-3") {
config.events['onRequestHistoryClose'] = function () { // the user is trying to go back to the document from viewing the document version history
document.location.reload();
};
config.events['onRequestRestore'] = function (event) {
var fileName = "<%= FileName %>";
var version = event.data.version;
var data = {
fileName: fileName,
version: version
};
let xhr = new XMLHttpRequest();
xhr.open("POST", "webeditor.ashx?type=restore&directUrl=" + !!config.document.directUrl);
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.send(JSON.stringify(data));
xhr.onload = function () {
docEditor.refreshHistory(JSON.parse(xhr.responseText));
}
};
let xhr = new XMLHttpRequest();
xhr.open("POST", "webeditor.ashx?type=restore&directUrl=" + !!config.document.directUrl);
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.send(JSON.stringify(data));
xhr.onload = function () {
docEditor.refreshHistory(JSON.parse(xhr.responseText));
}
};
}
// add mentions for not anonymous users
<% if (!string.IsNullOrEmpty(UsersForMentions))
{ %>
config.events['onRequestUsers'] = function (event) {
if (event && event.data){
var c = event.data.c;
}
switch (c) {
case "info":
users = [];
var allUsers = <%= UsersInfo %>;
for (var i = 0; i < event.data.id.length; i++) {
for (var j = 0; j < allUsers.length; j++) {
if (allUsers[j].id == event.data.id[i]) {
users.push(allUsers[j]);
break;
}
}
}
break;
case "protect":
var users = <%= UsersForProtect %>;
break;
default:
users = <%= UsersForMentions %>;
}
docEditor.setUsers({
"c": c,
"users": users,
});
};
config.events['onRequestUsers'] = onRequestUsers;
<% } %>
config.events['onRequestSaveAs'] = onRequestSaveAs;
// 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);
};
config.events['onRequestSendNotify'] = onRequestSendNotify;
// prevent file renaming for anonymous users
config.events['onRequestRename'] = onRequestRename;
config.events['onRequestReferenceData'] = onRequestReferenceData;
@ -342,17 +349,7 @@
config.events['onRequestOpen'] = onRequestOpen;
}
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);
};

View File

@ -135,14 +135,14 @@ namespace OnlineEditorsExample
{
// create demo document of a specified file type
Try(type, Request["sample"], Request);
Response.Redirect("doceditor.aspx?fileID=" + HttpUtility.UrlEncode(FileName));
Response.Redirect("doceditor.aspx?editorsMode=edit&fileID=" + HttpUtility.UrlEncode(FileName));
}
// get file extension
var ext = Path.GetExtension(FileName).ToLower();
var canFill = _Default.FillFormsExts.Contains(ext);
// get editor mode or set the default one (edit)
var editorsMode = Request.GetOrDefault("editorsMode", "edit");
var editorsMode = Request.GetOrDefault("editorsMode", canFill ? "fillForms" : "edit");
var canEdit = _Default.EditedExts.Contains(ext); // check if this file can be edited
var editorsType = Request.GetOrDefault("editorsType", "desktop");
@ -150,11 +150,11 @@ namespace OnlineEditorsExample
var id = Request.Cookies.GetOrDefault("uid", null);
var user = Users.getUser(id); // get the user
if ((!canEdit && editorsMode.Equals("edit") || editorsMode.Equals("fillForms")) && _Default.FillFormsExts.Contains(ext)) {
if ((!canEdit && editorsMode.Equals("edit") || editorsMode.Equals("fillForms")) && canFill) {
editorsMode = "fillForms";
canEdit = true;
}
var submitForm = editorsMode.Equals("fillForms") && id.Equals("uid-1"); // check if the Submit form button is displayed or hidden
var submitForm = !editorsMode.Equals("view") && user.id.Equals("uid-1"); // check if the Submit form button is displayed or hidden
var mode = canEdit && editorsMode != "view" ? "edit" : "view"; // get the editor opening mode (edit or view)
var jss = new JavaScriptSerializer();
@ -282,10 +282,12 @@ namespace OnlineEditorsExample
{ "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
{
"goback", new Dictionary<string, object> // settings for the Open file location menu button and upper right corner button
"goback", user.goback != null ? new Dictionary<string, object> // settings for the Open file location menu button and upper right corner button
{
{ "url", _Default.GetServerUrl(false) + "default.aspx" } // the absolute URL to the website address which will be opened when clicking the Open file location menu button
}
{ "url", _Default.GetServerUrl(false) + "default.aspx" }, // the absolute URL to the website address which will be opened when clicking the Open file location menu button
{ "text", user.goback.text },
{ "blank", user.goback.blank }
} : new Dictionary<string, object>{}
}
}
}
@ -338,17 +340,17 @@ namespace OnlineEditorsExample
var InsertImageUrl = new UriBuilder(_Default.GetServerUrl(true));
InsertImageUrl.Path = HttpRuntime.AppDomainAppVirtualPath
+ (HttpRuntime.AppDomainAppVirtualPath.EndsWith("/") ? "" : "/")
+ "App_Themes\\images\\logo.png";
+ "App_Themes\\images\\logo.svg";
var DirectImageUrl = new UriBuilder(_Default.GetServerUrl(false));
DirectImageUrl.Path = HttpRuntime.AppDomainAppVirtualPath
+ (HttpRuntime.AppDomainAppVirtualPath.EndsWith("/") ? "" : "/")
+ "App_Themes\\images\\logo.png";
+ "App_Themes\\images\\logo.svg";
// create a logo config
Dictionary<string, object> logoConfig = new Dictionary<string, object>
{
{ "fileType", "png"},
{ "fileType", "svg"},
{ "url", InsertImageUrl.ToString()}
};
@ -487,8 +489,8 @@ namespace OnlineEditorsExample
case "slide":
ext = ".pptx"; // .pptx for slide document type
break;
case "docxf":
ext = ".docxf";
case "pdf":
ext = ".pdf";
break;
default:
return;

View File

@ -227,10 +227,14 @@ namespace ASC.Api.DocumentConverter
private static void ProcessResponseError(int errorCode)
{
var errorMessage = string.Empty;
const string errorMessageTemplate = "Error occurred in the ConvertService.ashx: {0}";
const string errorMessageTemplate = "Error occurred in the ConvertService: {0}";
switch (errorCode)
{
case -9:
// public const int c_nErrorConversionOutputFormatError = -9;
errorMessage = String.Format(errorMessageTemplate, "Error conversion output format");
break;
case -8:
// public const int c_nErrorFileVKey = -8;
errorMessage = String.Format(errorMessageTemplate, "Error document VKey");

View File

@ -0,0 +1,147 @@
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Forgotten.aspx.cs" Inherits="OnlineEditorsExample.Forgotten" Title="ONLYOFFICE" %>
<%@ Import Namespace="System.IO" %>
<%@ Import Namespace="OnlineEditorsExample" %>
<!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" />
<meta name="server-version" content=<%= GetVersion() %> />
<title>ONLYOFFICE</title>
<!--
*
* (c) Copyright Ascensio System SIA 2024
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
-->
<link rel="icon" href="~/favicon.ico" type="image/x-icon" />
<link rel="stylesheet" type="text/css" href="https://fonts.googleapis.com/css?family=Open+Sans:900,800,700,600,500,400,300&subset=latin,cyrillic-ext,cyrillic,latin-ext" />
<link rel="stylesheet" type="text/css" href="app_themes/stylesheet.css" />
<link rel="stylesheet" type="text/css" href="app_themes/media.css" />
<link rel="stylesheet" type="text/css" href="app_themes/forgotten.css" />
<link rel="stylesheet" type="text/css" href="app_themes/jquery-ui.css" />
</head>
<body>
<form id="form1" runat="server">
<header>
<div class="center main-nav">
<a href="./">
<img src ="app_themes/images/logo.svg" alt="ONLYOFFICE" />
</a>
</div>
<menu class="responsive-nav">
<li>
<a href="#">
<img src="app_themes/images/mobile-menu.svg" alt="ONLYOFFICE" />
</a>
</li>
<li>
<a href="./">
<img src ="app_themes/images/mobile-logo.svg" alt="ONLYOFFICE" />
</a>
</li>
</menu>
</header>
<div class="center main">
<table class="table-main">
<tbody>
<tr>
<td class="left-panel section"></td>
<td class="section">
<div class="main-panel">
<menu class="links">
<li class="home-link" >
<a href="./">
<img src="app_themes/images/home.svg" alt="Home"/>
</a>
</li>
<li class="active">
<a href="/Forgotten.aspx">Forgotten files</a>
</li>
</menu>
<div class="stored-list">
<div class="storedHeader">
<div class="storedHeaderText">
<span class="header-list">Forgotten files</span>
</div>
</div>
<table class="tableHeader" cellspacing="0" cellpadding="0" width="100%">
<thead>
<tr>
<td class="tableHeaderCell">Filename</td>
<td class="tableHeaderCell">Action</td>
</tr>
</thead>
</table>
<div class="scroll-table-body">
<table cellspacing="0" cellpadding="0" width="100%">
<tbody>
<% foreach (var file in GetForgottenFiles()) { %>
<tr class="tableRow" title="<%= file["key"] %>">
<td>
<a class="stored-edit <%= file["type"] %>" href="<%= file["url"] %>" target="_blank">
<span><%= file["key"] %></span>
</a>
</td>
<td>
<a href="<%= file["url"] %>">
<img class="icon-download" src="app_themes/images/download.svg" alt="Download" title="Download" /></a>
<a class="delete-file" data="<%= file["key"] %>">
<img class="icon-action" src="app_themes/images/delete.svg" alt="Delete" title="Delete" /></a>
</td>
</tr>
<% } %>
</tbody>
</table>
</div>
</div>
</div>
</td>
</tr>
</tbody>
</table>
</div>
<footer>
<div class="center">
<table>
<tbody>
<tr>
<td>
<a href="http://api.onlyoffice.com/editors/howitworks" target="_blank">API Documentation</a>
</td>
<td>
<a href="mailto:sales@onlyoffice.com">Submit your request</a>
</td>
<td class="copy">
&copy; Ascensio System SIA <%= DateTime.Now.Year.ToString() %>. All rights reserved.
</td>
</tr>
</tbody>
</table>
</div>
</footer>
</form>
<script language="javascript" type="text/javascript" src="script/forgotten.js"></script>
</body>
</html>

View File

@ -0,0 +1,97 @@
/**
*
* (c) Copyright Ascensio System SIA 2024
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Web.Configuration;
using System.Web.UI;
namespace OnlineEditorsExample
{
public partial class Forgotten : Page
{
//get server version
public static string GetVersion()
{
return WebConfigurationManager.AppSettings["version"];
}
private static bool? _ismono;
public static bool IsMono
{
get { return _ismono.HasValue ? _ismono.Value : (_ismono = (bool?)(Type.GetType("Mono.Runtime") != null)).Value; }
}
// get the document type
public static string DocumentType(string fileName)
{
var ext = Path.GetExtension(fileName).ToLower();
if (FormatManager.PdfExtensions().Contains(ext)) return "pdf"; // pdf for pdf extensions
if (FormatManager.DocumentExtensions().Contains(ext)) return "word"; // word for text document extensions
if (FormatManager.SpreadsheetExtensions().Contains(ext)) return "cell"; // cell for spreadsheet extensions
if (FormatManager.PresentationExtensions().Contains(ext)) return "slide"; // slide for presentation extensions
return "word"; // the default document type is word
}
protected void Page_Load(object sender, EventArgs e)
{
if (!bool.Parse(WebConfigurationManager.AppSettings["enable-forgotten"]))
{
Response.Clear();
Response.StatusCode = 403;
Response.End();
}
}
// fetch forgotten files from the document server
public static List<Dictionary<string, string>> GetForgottenFiles()
{
var files = new List<Dictionary<string, string>>();
try
{
var response = TrackManager.commandRequest("getForgottenList", null);
ArrayList keys = (ArrayList) response["keys"];
// fetch all the forgotten files from the document server
foreach (string key in keys)
{
var file = new Dictionary<string, string>();
var fileResult = TrackManager.commandRequest("getForgotten", key);
file.Add("key", fileResult["key"].ToString());
file.Add("url", fileResult["url"].ToString());
file.Add("type", DocumentType(fileResult["url"].ToString()));
files.Add(file);
}
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine(ex.Message);
}
return files;
}
}
}

View File

@ -0,0 +1,24 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace OnlineEditorsExample {
public partial class Forgotten {
/// <summary>
/// form1 control.
/// </summary>
/// <remarks>
/// Auto-generated field.
/// To modify move field declaration from designer file to code-behind file.
/// </remarks>
protected global::System.Web.UI.HtmlControls.HtmlForm form1;
}
}

View File

@ -150,6 +150,20 @@ namespace OnlineEditorsExample
.ToList();
}
public static List<string> PdfExtensions()
{
return Pdfs()
.Select(format => format.Extension())
.ToList();
}
public static List<Format> Pdfs()
{
return All()
.Where(format => format.Type == "pdf")
.ToList();
}
public static List<string> AllExtensions()
{
return All()

View File

@ -77,6 +77,7 @@
</Reference>
</ItemGroup>
<ItemGroup>
<Content Include="App_Themes\forgotten.css" />
<Content Include="App_Themes\images\block-content.svg" />
<Content Include="App_Themes\images\cell.ico" />
<Content Include="App_Themes\images\close.svg" />
@ -94,6 +95,7 @@
<Content Include="App_Themes\images\file_xlsx.svg" />
<Content Include="App_Themes\images\fill-forms.svg" />
<Content Include="App_Themes\images\filter.svg" />
<Content Include="App_Themes\images\home.svg" />
<Content Include="App_Themes\images\icon_docx.svg" />
<Content Include="App_Themes\images\icon_pptx.svg" />
<Content Include="App_Themes\images\icon_xlsx.svg" />
@ -104,10 +106,16 @@
<Content Include="App_Themes\images\notdone.svg" />
<Content Include="App_Themes\images\review.svg" />
<Content Include="App_Themes\images\slide.ico" />
<Content Include="App_Themes\images\uid-1.png" />
<Content Include="App_Themes\images\uid-2.png" />
<Content Include="App_Themes\images\word.ico" />
<Content Include="App_Themes\media.css" />
<Content Include="Forgotten.aspx" />
<Content Include="LICENSE" />
<Content Include="licenses\jquery.license" />
<Content Include="script\forgotten.js" />
<Content Include="script\formats.js" />
<Content Include="script\jquery-3.6.4.min.js" />
<Content Include="script\jquery-migrate-3.4.1.min.js" />
<Content Include="Web.config" />
</ItemGroup>
<ItemGroup>
@ -119,6 +127,12 @@
<DependentUpon>DocEditor.aspx</DependentUpon>
</Compile>
<Compile Include="DocumentConverter.cs" />
<Compile Include="Forgotten.aspx.cs">
<DependentUpon>Forgotten.aspx</DependentUpon>
</Compile>
<Compile Include="Forgotten.aspx.designer.cs">
<DependentUpon>Forgotten.aspx</DependentUpon>
</Compile>
<Compile Include="FormatManager.cs" />
<Compile Include="JwtManager.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
@ -145,7 +159,6 @@
</ItemGroup>
<ItemGroup>
<Content Include="App_Themes\images\loader16.gif" />
<Content Include="App_Themes\images\logo.png" />
<Content Include="App_Themes\jquery-ui.css" />
<Content Include="App_Themes\stylesheet.css" />
<Content Include="DocEditor.aspx" />

View File

@ -285,7 +285,7 @@ namespace OnlineEditorsExample
}
// create a command request
public static void commandRequest(string method, string key, object meta = null)
public static Dictionary<string, object> commandRequest(string method, string key, object meta = null)
{
_Default.VerifySSL();
@ -348,6 +348,7 @@ namespace OnlineEditorsExample
{
throw new Exception(dataResponse);
}
return responseObj;
}
private static void SaveFile(byte[] data, string path)

View File

@ -58,7 +58,9 @@ namespace OnlineEditorsExample
"Cant print the file",
"Can create new files from the editor",
"Can see the information about Group2 users",
"Cant submit forms"
"Cant submit forms",
"Can't close history",
"Can't restore the file version"
};
static List<string> descr_user_0 = new List<string>()
@ -91,7 +93,8 @@ namespace OnlineEditorsExample
new List<string>(),
descr_user_1,
true,
true
true,
new Goback(null, false)
),
new User(
"uid-2",
@ -110,7 +113,8 @@ namespace OnlineEditorsExample
new List<string>(),
descr_user_2,
false,
true
true,
new Goback("Go to Documents",null)
),
new User(
"uid-3",
@ -129,7 +133,8 @@ namespace OnlineEditorsExample
new List<string>() { "copy", "download", "print" },
descr_user_3,
false,
false
false,
null
),
new User(
"uid-0",
@ -143,7 +148,8 @@ namespace OnlineEditorsExample
new List<string>() { "protect" },
descr_user_0,
false,
false
false,
null
)
};
@ -235,8 +241,9 @@ namespace OnlineEditorsExample
public bool templates;
public List<string> userInfoGroups;
public bool avatar;
public Goback goback;
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, bool avatar)
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, bool avatar, Goback goback)
{
this.id = id;
this.name = name;
@ -250,6 +257,21 @@ namespace OnlineEditorsExample
this.templates = templates;
this.userInfoGroups = userInfoGroups;
this.avatar = avatar;
this.goback = goback;
}
}
public class Goback
{
public string text;
public bool? blank;
public Goback(){}
public Goback(string text, bool? blank)
{
this.text = text;
this.blank = blank;
}
}
}

View File

@ -69,6 +69,9 @@ namespace OnlineEditorsExample
case "remove":
Remove(context);
break;
case "removeforgotten":
RemoveForgotten(context);
break;
case "assets":
Assets(context);
break;
@ -87,6 +90,9 @@ namespace OnlineEditorsExample
case "reference":
Reference(context);
break;
case "formats":
Formats(context);
break;
}
}
@ -222,12 +228,22 @@ namespace OnlineEditorsExample
context.Response.ContentType = "text/plain";
try
{
var fileName = Path.GetFileName(context.Request["fileName"]);
var path = _Default.StoragePath(fileName, HttpUtility.UrlEncode(_Default.CurUserHostAddress(HttpContext.Current.Request.UserHostAddress)));
var histDir = _Default.HistoryDir(path);
string fileName = context.Request["fileName"];
string userAddress = HttpUtility.UrlEncode(_Default.CurUserHostAddress(HttpContext.Current.Request.UserHostAddress));
if (File.Exists(path)) File.Delete(path); // delete file
if (Directory.Exists(histDir)) Directory.Delete(histDir, true); // delete file history
if (!String.IsNullOrEmpty(fileName))
{
fileName = Path.GetFileName(fileName);
var path = _Default.StoragePath(fileName, userAddress);
var histDir = _Default.HistoryDir(path);
if (File.Exists(path)) File.Delete(path); // delete file
if (Directory.Exists(histDir)) Directory.Delete(histDir, true); // delete file history
} else
{
string userDir = _Default.StoragePath("", userAddress);
if (Directory.Exists(userDir)) Directory.Delete(userDir, true); // delete the user's directory
}
context.Response.Write("{ \"success\": true }");
}
@ -778,5 +794,50 @@ namespace OnlineEditorsExample
+ userAddress;
return fileUrl.ToString();
}
// return all the supported formats
private static void Formats(HttpContext context)
{
try
{
Dictionary<string, object> data = new Dictionary<string, object>
{
{ "formats", FormatManager.All() }
};
context.Response.ContentType = "application/json";
var jss = new JavaScriptSerializer();
context.Response.Write(jss.Serialize(data));
}
catch (Exception e)
{
context.Response.Write("{ \"error\": \"" + e.Message + "\"}");
}
}
// delete a forgotten file from the document server
private static void RemoveForgotten(HttpContext context)
{
try
{
if (!bool.Parse(WebConfigurationManager.AppSettings["enable-forgotten"]))
{
throw new HttpException(403, "The forgotten page is disabled");
}
string filename = context.Request["filename"];
if (!String.IsNullOrEmpty(filename))
{
TrackManager.commandRequest("deleteForgotten", filename);
}
context.Response.StatusCode = 204;
}
catch (Exception e)
{
context.Response.Write("{ \"error\": \"" + e.Message + "\"}");
}
}
}
}

View File

@ -0,0 +1,19 @@
function deleteFile(event) {
let filename = event.currentTarget.getAttribute("data");
filename = encodeURIComponent(filename);
let url = `webeditor.ashx?type=removeforgotten&filename=${filename}`;
fetch(url, {
headers: {
"Content-Type": "application/json",
}
}).then(result => {
if (result.status == 204) {
document.location.reload(true);
}
});
}
document.querySelectorAll('.delete-file').forEach(el => {
el.addEventListener('click', deleteFile);
});

View File

@ -0,0 +1,66 @@
/**
*
* (c) Copyright Ascensio System SIA 2024
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
class Format {
constructor(name, type, actions, convert, mime) {
this.name = name;
this.type = type;
this.actions = actions;
this.convert = convert;
this.mime = mime;
}
isAutoConvertible() {
return this.actions.includes('auto-convert');
}
isEditable() {
return this.actions.includes('edit') || this.actions.includes('lossy-edit');
}
isFillable() {
return this.actions.includes('fill');
}
}
class FormatManager {
formats = [];
constructor(formats) {
if(Array.isArray(formats)) this.formats = formats;
}
findByExtension(extension) {
return this.formats.find(format => format.name == extension);
}
isAutoConvertible(extension) {
let format = this.findByExtension(extension);
return format !== undefined && format.isAutoConvertible();
}
isEditable(extension) {
let format = this.findByExtension(extension);
return format !== undefined && format.isEditable();
}
isFillable(extension) {
let format = this.findByExtension(extension);
return format !== undefined && format.isFillable();
}
}

View File

@ -17,6 +17,27 @@
*/
var directUrl;
var formatManager;
window.onload = function () {
fetch("webeditor.ashx?type=formats")
.then((response) => response.json())
.then((data) => {
if (data.formats) {
let formats = [];
data.formats.forEach(format => {
formats.push(new Format(
format.Name,
format.Type,
format.Actions,
format.Convert,
format.Mime
));
});
formatManager = new FormatManager(formats);
}
})
}
if (typeof jQuery != "undefined") {
jq = jQuery.noConflict();
@ -87,8 +108,8 @@ if (typeof jQuery != "undefined") {
});
var timer = null;
var checkConvert = function (filePass) {
filePass = filePass ? filePass : null;
var checkConvert = function (filePass, fileType) {
filePass = filePass ? filePass : null;
if (timer != null) {
clearTimeout(timer);
}
@ -100,10 +121,10 @@ if (typeof jQuery != "undefined") {
jq("#filePass").val("");
var fileName = jq("#hiddenFileName").val();
var posExt = fileName.lastIndexOf('.');
var posExt = fileName.lastIndexOf('.') + 1;
posExt = 0 <= posExt ? fileName.substring(posExt).trim().toLowerCase() : '';
if (ConverExtList.indexOf(posExt) == -1) {
if (!formatManager.isAutoConvertible(posExt)) {
jq("#step2").addClass("done").removeClass("current");
loadScripts();
return;
@ -116,7 +137,7 @@ if (typeof jQuery != "undefined") {
contentType: "text/xml",
type: "post",
dataType: "json",
data: JSON.stringify({ filename: fileName, filePass: filePass }),
data: JSON.stringify({ filename: fileName, filePass: filePass, fileExt: fileType }),
url: requestAddress,
complete: function (data) {
var responseText = data.responseText;
@ -132,6 +153,12 @@ if (typeof jQuery != "undefined") {
}
return;
} else {
if (response.error.includes("Error conversion output format")) {
jq("#select-file-type").removeClass("invisible");
jq("#step2").removeClass("current");
jq("#hiddenFileName").attr("placeholder", filePass);
return;
}
jq(".current").removeClass("current");
jq(".step:not(.done)").addClass("error");
jq("#mainProgress .error-message").show().find("span").text(response.error);
@ -143,7 +170,7 @@ if (typeof jQuery != "undefined") {
jq("#hiddenFileName").val(response.filename);
if (response.step && response.step < 100) {
checkConvert(filePass);
checkConvert(filePass, fileType);
} else {
jq("#step2").addClass("done").removeClass("current");
loadScripts();
@ -178,10 +205,10 @@ if (typeof jQuery != "undefined") {
jq("#beginView, #beginEmbedded").removeClass("disable");
var fileName = jq("#hiddenFileName").val();
var posExt = fileName.lastIndexOf('.');
var posExt = fileName.lastIndexOf('.') + 1;
posExt = 0 <= posExt ? fileName.substring(posExt).trim().toLowerCase() : '';
if (EditedExtList.indexOf(posExt) != -1 || FillFormExtList.indexOf(posExt) != -1) {
if (formatManager.isEditable(posExt) || formatManager.isFillable(posExt)) {
jq("#beginEdit").removeClass("disable");
}
};
@ -213,6 +240,15 @@ if (typeof jQuery != "undefined") {
});
};
jq(document).on("click", ".file-type:not(.disable)", function () {
const currentElement = jq(this);
var fileType = currentElement.attr("data");
var filePass = jq("#hiddenFileName").attr("placeholder");
jq('.file-type').addClass(["disable", "pale"]);
currentElement.removeClass("pale");
checkConvert(filePass, fileType);
});
jq(document).on("click", "#enterPass", function () {
var filePass = jq("#filePass").val();
if (filePass) {
@ -293,6 +329,24 @@ if (typeof jQuery != "undefined") {
});
});
jq(document).on("click", ".clear-all", function () {
if (confirm("Delete all the files?")) {
var requestAddress = "webeditor.ashx"
+ "?type=remove";
jq.ajax({
async: true,
contentType: "text/xml",
url: requestAddress,
complete: function (data) {
if (JSON.parse(data.responseText).success) {
window.location.reload(true);
}
}
});
}
});
function showUserTooltip (isMobile) {
if ( jq("div#portal-info").is(":hidden") ) {
jq("div#portal-info").show();
@ -367,4 +421,27 @@ if (typeof jQuery != "undefined") {
}).mouseout(function () {
jq("div.tooltip").remove();
});
}
function toggleSidePanel(event) {
event.preventDefault();
let sidePanel = document.querySelector(".left-panel");
let body = document.querySelector("body");
if (sidePanel.classList.contains("active")) {
sidePanel.classList.remove("active");
body.classList.remove("menu-open");
} else {
sidePanel.classList.add("active")
body.classList.add("menu-open");
}
}
function toggleUserDescr(event) {
let list = event.currentTarget.querySelector("ul");
let cursor = window.getComputedStyle(event.currentTarget).getPropertyValue("cursor");
if (cursor === "pointer") {
if (list.classList.contains("active")) list.classList.remove("active");
else list.classList.add("active");
}
}

View File

@ -1,11 +1,12 @@
<?xml version="1.0" encoding="utf-8" ?>
<appSettings>
<clear />
<add key="version" value="1.9.0"/>
<add key="version" value="1.11.0"/>
<add key="filesize-max" value="52428800"/>
<add key="storage-path" value=""/>
<add key="filename-max" value="50"/>
<add key="enable-forgotten" value="true"/>
<add key="files.docservice.timeout" value="120000" />
<add key="files.docservice.secret" value="" />
@ -14,14 +15,14 @@
<add key="files.docservice.token.useforrequest" value="true" />
<add key="files.docservice.languages" value="en:English|ar:Arabic|hy:Armenian|az:Azerbaijani|eu:Basque|be:Belarusian|bg:Bulgarian|ca:Catalan|zh:Chinese (Simplified)|zh-TW:Chinese (Traditional)|cs:Czech|da:Danish|nl:Dutch|en-GB:English (United Kingdom)|fi:Finnish|fr:French|gl:Galego|de:German|el:Greek|hu:Hungarian|id:Indonesian|it:Italian|ja:Japanese|ko:Korean|lo:Lao|lv:Latvian|ms:Malay (Malaysia)|no:Norwegian|pl:Polish|pt:Portuguese (Brazil)|pt-PT:Portuguese (Portugal)|ro:Romanian|ru:Russian|sr-Cyrl-RS:Serbian (Cyrillic)|sr-Latn-RS:Serbian (Latin)|si:Sinhala (Sri Lanka)|sk:Slovak|sl:Slovenian|es:Spanish|sv:Swedish|tr:Turkish|uk:Ukrainian|vi:Vietnamese|aa-AA: Test Language"/>
<add key="files.docservice.languages" value="en:English|ar:Arabic|hy:Armenian|az:Azerbaijani|eu:Basque|be:Belarusian|bg:Bulgarian|ca:Catalan|zh:Chinese (Simplified)|zh-TW:Chinese (Traditional)|cs:Czech|da:Danish|nl:Dutch|en-GB:English (United Kingdom)|fi:Finnish|fr:French|gl:Galego|de:German|el:Greek|he-IL:Hebrew (Israel)|hu:Hungarian|id:Indonesian|it:Italian|ja:Japanese|ko:Korean|lo:Lao|lv:Latvian|ms:Malay (Malaysia)|no:Norwegian|pl:Polish|pt:Portuguese (Brazil)|pt-PT:Portuguese (Portugal)|ro:Romanian|ru:Russian|sr-Cyrl-RS:Serbian (Cyrillic)|sr-Latn-RS:Serbian (Latin)|si:Sinhala (Sri Lanka)|sk:Slovak|sl:Slovenian|es:Spanish|sv:Swedish|tr:Turkish|uk:Ukrainian|vi:Vietnamese|aa-AA: Test Language"/>
<add key="files.docservice.url.site" value="http://documentserver/"/>
<add key="files.docservice.url.converter" value="ConvertService.ashx"/>
<add key="files.docservice.url.converter" value="converter"/>
<add key="files.docservice.url.api" value="web-apps/apps/api/documents/api.js"/>
<add key="files.docservice.url.preloader" value="web-apps/apps/api/documents/cache-scripts.html"/>
<add key="files.docservice.url.command" value="coauthoring/CommandService.ashx"/>
<add key="files.docservice.url.command" value="command"/>
<add key="files.docservice.url.example" value=""/>

View File

@ -1,6 +1,5 @@
ONLYOFFICE Applications example uses code from the following 3rd party projects:
Gson - Gson is a Java library that can be used to convert Java Objects into their JSON representation. (https://github.com/google/gson/blob/master/LICENSE)
License: Apache 2.0
License File: gson.license
@ -13,6 +12,10 @@ Jackson Databind - General-purpose data-binding functionality and tree-model for
License: Apache 2.0
License File: jackson-databind.license
Jackson Dataformat Properties - Support for reading and writing content of "Java Properties" style configuration files as if there was implied nesting structure (by default using dots as separators). (https://github.com/FasterXML/jackson-dataformats-text/blob/master/LICENSE)
License: Apache 2.0
License File: jackson-dataformat-properties.license
jQuery.BlockUI - The jQuery BlockUI Plugin lets you simulate synchronous behavior when using AJAX, without locking the browser. (https://github.com/malsup/blockui/)
License: MIT, GPL
License File: jQuery.BlockUI.license
@ -37,6 +40,10 @@ jQuery.UI - jQuery UI is an open source library of interface components —
License: MIT
License File: jQuery.UI.license
JSON - JSON is a light-weight, language independent, data interchange format. (https://github.com/stleary/JSON-java/blob/master/LICENSE)
License Public Domain
License File: json.license
JSON.simple - JSON.simple is a simple Java toolkit for JSON. You can use JSON.simple to encode or decode JSON text. (https://github.com/fangyidong/json-simple/blob/master/LICENSE.txt)
License: Apache 2.0
License File: JSON.simple.license
@ -49,14 +56,14 @@ ModelMapper - ModelMapper is an intelligent object mapping library that automa
License: Apache 2.0
License File modelmapper.license
Prime JWT - is intended to be fast and easy to use. Prime JWT has a single external dependency on Jackson. (https://github.com/ws-apps/prime-jwt/blob/master/LICENSE)
License: Apache 2.0
License File: prime-jwt.license
Spring Boot - Helps create Spring-powered, production-grade applications and services. Has external dependencies on Spring Framework. (https://github.com/spring-projects/spring-boot/blob/main/LICENSE.txt)
License: Apache 2.0
License File: spring-boot.license
Spring Boot Web - Starter for building web, including RESTful, applications using Spring MVC. Uses Tomcat as the default embedded container. (https://github.com/spring-projects/spring-boot/blob/main/LICENSE.txt)
License: Apache 2.0
License File: spring-boot.license
Spring Boot Devtools - Provides fast application restarts, LiveReload, and configurations for enhanced development experience. (https://github.com/spring-projects/spring-boot/blob/main/LICENSE.txt)
License: Apache 2.0
License File: spring-boot.license

View File

@ -135,9 +135,9 @@ See the detailed guide to learn how to install Document Server [for Linux](https
a) archive with Java-Spring:
```
wget https://api.onlyoffice.com/app_data/editor/Java.Spring.Example.zip
wget https://github.com/ONLYOFFICE/document-server-integration/releases/latest/download/Java.Spring.Example.zip
```
```
unzip Java.Spring.Example.zip
```

View File

@ -1,6 +1,5 @@
ONLYOFFICE Applications example uses code from the following 3rd party projects:
Gson - Gson is a Java library that can be used to convert Java Objects into their JSON representation. (https://github.com/google/gson/blob/master/LICENSE)
License: Apache 2.0
License File: gson.license
@ -13,6 +12,10 @@ Jackson Databind - General-purpose data-binding functionality and tree-model for
License: Apache 2.0
License File: jackson-databind.license
Jackson Dataformat Properties - Support for reading and writing content of "Java Properties" style configuration files as if there was implied nesting structure (by default using dots as separators). (https://github.com/FasterXML/jackson-dataformats-text/blob/master/LICENSE)
License: Apache 2.0
License File: jackson-dataformat-properties.license
jQuery.BlockUI - The jQuery BlockUI Plugin lets you simulate synchronous behavior when using AJAX, without locking the browser. (https://github.com/malsup/blockui/)
License: MIT, GPL
License File: jQuery.BlockUI.license
@ -37,6 +40,10 @@ jQuery.UI - jQuery UI is an open source library of interface components —
License: MIT
License File: jQuery.UI.license
JSON - JSON is a light-weight, language independent, data interchange format. (https://github.com/stleary/JSON-java/blob/master/LICENSE)
License Public Domain
License File: json.license
JSON.simple - JSON.simple is a simple Java toolkit for JSON. You can use JSON.simple to encode or decode JSON text. (https://github.com/fangyidong/json-simple/blob/master/LICENSE.txt)
License: Apache 2.0
License File: JSON.simple.license
@ -49,14 +56,14 @@ ModelMapper - ModelMapper is an intelligent object mapping library that automa
License: Apache 2.0
License File modelmapper.license
Prime JWT - is intended to be fast and easy to use. Prime JWT has a single external dependency on Jackson. (https://github.com/ws-apps/prime-jwt/blob/master/LICENSE)
License: Apache 2.0
License File: prime-jwt.license
Spring Boot - Helps create Spring-powered, production-grade applications and services. Has external dependencies on Spring Framework. (https://github.com/spring-projects/spring-boot/blob/main/LICENSE.txt)
License: Apache 2.0
License File: spring-boot.license
Spring Boot Web - Starter for building web, including RESTful, applications using Spring MVC. Uses Tomcat as the default embedded container. (https://github.com/spring-projects/spring-boot/blob/main/LICENSE.txt)
License: Apache 2.0
License File: spring-boot.license
Spring Boot Devtools - Provides fast application restarts, LiveReload, and configurations for enhanced development experience. (https://github.com/spring-projects/spring-boot/blob/main/LICENSE.txt)
License: Apache 2.0
License File: spring-boot.license

View File

@ -1,4 +1,5 @@
Apache License
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
@ -178,7 +179,7 @@ Apache License
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "{}"
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
@ -186,7 +187,7 @@ Apache License
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright {yyyy} {name of copyright owner}
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.

View File

@ -0,0 +1 @@
Public Domain.

View File

@ -50,11 +50,6 @@
<artifactId>gson</artifactId>
<version>2.8.9</version>
</dependency>
<dependency>
<groupId>com.inversoft</groupId>
<artifactId>prime-jwt</artifactId>
<version>1.3.1</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
@ -71,12 +66,39 @@
<artifactId>jackson-databind</artifactId>
<version>2.13.4.2</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-properties</artifactId>
<version>2.13.5</version>
</dependency>
<dependency>
<groupId>org.modelmapper</groupId>
<artifactId>modelmapper</artifactId>
<version>2.4.2</version>
</dependency>
<dependency>
<groupId>org.json</groupId>
<artifactId>json</artifactId>
<version>20231013</version>
</dependency>
<dependency>
<groupId>com.onlyoffice</groupId>
<artifactId>docs-integration-sdk</artifactId>
<version>1.2.1-SNAPSHOT</version>
</dependency>
</dependencies>
<repositories>
<repository>
<id>ossrh</id>
<name>Sonatype OSSRH</name>
<url>https://s01.oss.sonatype.org/content/repositories/snapshots/</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
</repositories>
<build>
<plugins>
<plugin>

View File

@ -19,6 +19,7 @@
package com.onlyoffice.integration;
import com.onlyoffice.integration.documentserver.serializers.FilterState;
import com.onlyoffice.integration.entities.Goback;
import com.onlyoffice.integration.services.UserServices;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@ -92,30 +93,34 @@ public class ExampleData {
"Can create a file from an editor",
"Can see the information about Group2 users",
"Can view chat",
"Cant submit forms"
"Cant submit forms",
"Can't close history",
"Can't restore the file version"
);
// create user 1 with the specified parameters
userService.createUser("John Smith", "smith@example.com", descriptionUserFirst,
"", List.of(FilterState.NULL.toString()), List.of(FilterState.NULL.toString()),
List.of(FilterState.NULL.toString()), List.of(FilterState.NULL.toString()),
List.of(FilterState.NULL.toString()), null, true, true, true);
List.of(FilterState.NULL.toString()), null, true, true, true,
new Goback(null, false), true);
// create user 2 with the specified parameters
userService.createUser("Mark Pottato", "pottato@example.com", descriptionUserSecond,
"group-2", List.of("", "group-2"), List.of(FilterState.NULL.toString()),
List.of("group-2", ""), List.of("group-2"), List.of("group-2", ""), true, true,
true, true);
true, true, new Goback("Go to Documents", null), false);
// create user 3 with the specified parameters
userService.createUser("Hamish Mitchell", null, descriptionUserThird,
"group-3", List.of("group-2"), List.of("group-2", "group-3"), List.of("group-2"),
new ArrayList<>(), List.of("group-2"), false, true, true, false);
new ArrayList<>(), List.of("group-2"), false, true, true, false,
null, false);
// create user 0 with the specified parameters
userService.createUser("Anonymous", null, descriptionUserZero, "",
List.of(FilterState.NULL.toString()), List.of(FilterState.NULL.toString()),
List.of(FilterState.NULL.toString()), List.of(FilterState.NULL.toString()),
new ArrayList<>(), null, false, false, false);
new ArrayList<>(), null, false, false, false, null, false);
}
}

View File

@ -20,6 +20,17 @@ package com.onlyoffice.integration;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.onlyoffice.integration.documentserver.storage.FileStoragePathBuilder;
import com.onlyoffice.manager.document.DocumentManager;
import com.onlyoffice.manager.request.DefaultRequestManager;
import com.onlyoffice.manager.request.RequestManager;
import com.onlyoffice.manager.security.DefaultJwtManager;
import com.onlyoffice.manager.security.JwtManager;
import com.onlyoffice.manager.settings.SettingsManager;
import com.onlyoffice.manager.url.UrlManager;
import com.onlyoffice.service.command.CommandService;
import com.onlyoffice.service.command.DefaultCommandService;
import com.onlyoffice.service.convert.ConvertService;
import com.onlyoffice.service.convert.DefaultConvertService;
import org.json.simple.parser.JSONParser;
import org.modelmapper.ModelMapper;
import org.modelmapper.convention.MatchingStrategies;
@ -30,23 +41,15 @@ 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();
@ -67,21 +70,34 @@ 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
public ObjectMapper objectMapper() { // create the object mapper
return new ObjectMapper();
}
@Bean
public JwtManager jwtManager(final SettingsManager settingsManager) {
return new DefaultJwtManager(settingsManager);
}
@Bean
public RequestManager requestManager(final UrlManager urlManager, final JwtManager jwtManager,
final SettingsManager settingsManager) {
return new DefaultRequestManager(urlManager, jwtManager, settingsManager);
}
@Bean
public ConvertService convertService(final DocumentManager documentManager, final UrlManager urlManager,
final RequestManager requestManager,
final SettingsManager settingsManager) {
return new DefaultConvertService(documentManager, urlManager, requestManager, settingsManager);
}
@Bean
public CommandService commandService(final RequestManager requestManager) {
return new DefaultCommandService(requestManager);
}
}

View File

@ -20,19 +20,21 @@ package com.onlyoffice.integration.controllers;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.onlyoffice.integration.documentserver.managers.jwt.JwtManager;
import com.onlyoffice.integration.documentserver.models.enums.Action;
import com.onlyoffice.integration.documentserver.storage.FileStoragePathBuilder;
import com.onlyoffice.integration.entities.User;
import com.onlyoffice.integration.dto.Mentions;
import com.onlyoffice.integration.dto.UserInfo;
import com.onlyoffice.integration.dto.Protect;
import com.onlyoffice.integration.documentserver.models.enums.Type;
import com.onlyoffice.integration.documentserver.models.filemodel.FileModel;
import com.onlyoffice.integration.dto.UserInfo;
import com.onlyoffice.integration.entities.User;
import com.onlyoffice.integration.sdk.manager.UrlManager;
import com.onlyoffice.integration.sdk.service.ConfigService;
import com.onlyoffice.integration.services.UserServices;
import com.onlyoffice.integration.services.configurers.FileConfigurer;
import com.onlyoffice.integration.services.configurers.wrappers.DefaultFileWrapper;
import com.onlyoffice.manager.security.JwtManager;
import com.onlyoffice.manager.settings.SettingsManager;
import com.onlyoffice.model.documenteditor.Config;
import com.onlyoffice.model.documenteditor.config.document.Type;
import lombok.SneakyThrows;
import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
@ -56,12 +58,6 @@ import static com.onlyoffice.integration.documentserver.util.Constants.ANONYMOUS
@Controller
public class EditorController {
@Value("${files.docservice.url.site}")
private String docserviceSite;
@Value("${files.docservice.url.api}")
private String docserviceApiUrl;
@Value("${files.docservice.languages}")
private String langs;
@ -78,7 +74,13 @@ public class EditorController {
private ObjectMapper objectMapper;
@Autowired
private FileConfigurer<DefaultFileWrapper> fileConfigurer;
private SettingsManager settingsManager;
@Autowired
private ConfigService configService;
@Autowired
private UrlManager urlManager;
@GetMapping(path = "${url.editor}")
// process request to open the editor page
@ -86,20 +88,18 @@ public class EditorController {
@RequestParam(value = "action", required = false) final String actionParam,
@RequestParam(value = "type", required = false) final String typeParam,
@RequestParam(value = "actionLink", required = false) final String actionLink,
@RequestParam(value = "directUrl", required = false,
defaultValue = "false") final Boolean directUrl,
@CookieValue(value = "uid") final String uid,
@CookieValue(value = "ulang") final String lang,
final Model model) throws JsonProcessingException {
Action action = Action.edit;
Type type = Type.desktop;
Action action = null;
Type type = Type.DESKTOP;
Locale locale = new Locale("en");
if (actionParam != null) {
action = Action.valueOf(actionParam);
}
if (typeParam != null) {
type = Type.valueOf(typeParam);
type = Type.valueOf(typeParam.toUpperCase());
}
List<String> langsAndKeys = Arrays.asList(langs.split("\\|"));
@ -118,39 +118,34 @@ public class EditorController {
return "index.html";
}
User user = optionalUser.get();
user.setImage(user.getAvatar() ? storagePathBuilder.getServerUrl(true) + "/css/img/uid-"
+ user.getId() + ".png" : null);
// get file model with the default file parameters
FileModel fileModel = fileConfigurer.getFileModel(
DefaultFileWrapper
.builder()
.fileName(fileName)
.type(type)
.lang(locale.toLanguageTag())
.action(action)
.user(user)
.actionData(actionLink)
.isEnableDirectUrl(directUrl)
.build()
Config config = configService.createConfig(
fileName,
action,
type
);
// add attributes to the specified model
// add file model with the default parameters to the original model
model.addAttribute("model", fileModel);
JSONObject actionData = null;
if (actionLink != null && !actionLink.isEmpty()) {
actionData = new JSONObject(actionLink);
}
config.getEditorConfig().setActionLink(actionData);
config.getEditorConfig().setLang(locale.toLanguageTag());
model.addAttribute("model", config);
// create the document service api URL and add it to the model
model.addAttribute("docserviceApiUrl", docserviceSite + docserviceApiUrl);
model.addAttribute("docserviceApiUrl", urlManager.getDocumentServerApiUrl());
// get an image and add it to the model
model.addAttribute("dataInsertImage", getInsertImage(directUrl));
model.addAttribute("dataInsertImage", getInsertImage());
// get a document for comparison and add it to the model
model.addAttribute("dataDocument", getCompareFile(directUrl));
model.addAttribute("dataDocument", getCompareFile());
// get recipients data for mail merging and add it to the model
model.addAttribute("dataSpreadsheet", getSpreadsheet(directUrl));
model.addAttribute("dataSpreadsheet", getSpreadsheet());
// get user data for mentions and add it to the model
model.addAttribute("usersForMentions", getUserMentions(uid));
@ -210,17 +205,13 @@ public class EditorController {
@SneakyThrows
private String getInsertImage(final Boolean directUrl) { // get an image that will be inserted into the document
private String getInsertImage() { // get an image that will be inserted into the document
Map<String, Object> dataInsertImage = new HashMap<>();
dataInsertImage.put("fileType", "png");
dataInsertImage.put("url", storagePathBuilder.getServerUrl(true) + "/css/img/logo.png");
if (directUrl) {
dataInsertImage.put("directUrl", storagePathBuilder
.getServerUrl(false) + "/css/img/logo.png");
}
dataInsertImage.put("fileType", "svg");
dataInsertImage.put("url", storagePathBuilder.getServerUrl(true) + "/css/img/logo.svg");
// check if the document token is enabled
if (jwtManager.tokenEnabled()) {
if (settingsManager.isSecurityEnabled()) {
// create token from the dataInsertImage object
dataInsertImage.put("token", jwtManager.createToken(dataInsertImage));
@ -232,17 +223,13 @@ public class EditorController {
// get a document that will be compared with the current document
@SneakyThrows
private String getCompareFile(final Boolean directUrl) {
private String getCompareFile() {
Map<String, Object> dataDocument = new HashMap<>();
dataDocument.put("fileType", "docx");
dataDocument.put("url", storagePathBuilder.getServerUrl(true) + "/assets?name=sample.docx");
if (directUrl) {
dataDocument.put("directUrl", storagePathBuilder
.getServerUrl(false) + "/assets?name=sample.docx");
}
// check if the document token is enabled
if (jwtManager.tokenEnabled()) {
if (settingsManager.isSecurityEnabled()) {
// create token from the dataDocument object
dataDocument.put("token", jwtManager.createToken(dataDocument));
@ -252,16 +239,13 @@ public class EditorController {
}
@SneakyThrows
private String getSpreadsheet(final Boolean directUrl) {
private String getSpreadsheet() {
Map<String, Object> dataSpreadsheet = new HashMap<>(); // get recipients data for mail merging
dataSpreadsheet.put("fileType", "csv");
dataSpreadsheet.put("url", storagePathBuilder.getServerUrl(true) + "/csv");
if (directUrl) {
dataSpreadsheet.put("directUrl", storagePathBuilder.getServerUrl(false) + "/csv");
}
// check if the document token is enabled
if (jwtManager.tokenEnabled()) {
if (settingsManager.isSecurityEnabled()) {
// create token from the dataSpreadsheet object
dataSpreadsheet.put("token", jwtManager.createToken(dataSpreadsheet));

View File

@ -21,32 +21,38 @@ package com.onlyoffice.integration.controllers;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.onlyoffice.integration.documentserver.callbacks.CallbackHandler;
import com.onlyoffice.integration.documentserver.managers.history.HistoryManager;
import com.onlyoffice.integration.documentserver.managers.jwt.JwtManager;
import com.onlyoffice.integration.documentserver.storage.FileStorageMutator;
import com.onlyoffice.integration.documentserver.storage.FileStoragePathBuilder;
import com.onlyoffice.integration.dto.Converter;
import com.onlyoffice.integration.dto.ConvertedData;
import com.onlyoffice.integration.dto.Reference;
import com.onlyoffice.integration.dto.ReferenceData;
import com.onlyoffice.integration.dto.Rename;
import com.onlyoffice.integration.dto.Restore;
import com.onlyoffice.integration.dto.SaveAs;
import com.onlyoffice.integration.dto.Track;
import com.onlyoffice.integration.entities.User;
import com.onlyoffice.integration.documentserver.models.enums.DocumentType;
import com.onlyoffice.integration.sdk.manager.DocumentManager;
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 com.onlyoffice.manager.request.RequestManager;
import com.onlyoffice.manager.security.JwtManager;
import com.onlyoffice.manager.settings.SettingsManager;
import com.onlyoffice.manager.url.UrlManager;
import com.onlyoffice.model.commandservice.CommandRequest;
import com.onlyoffice.model.commandservice.CommandResponse;
import com.onlyoffice.model.commandservice.commandrequest.Command;
import com.onlyoffice.model.commandservice.commandrequest.Meta;
import com.onlyoffice.model.convertservice.ConvertRequest;
import com.onlyoffice.model.convertservice.ConvertResponse;
import com.onlyoffice.model.documenteditor.Callback;
import com.onlyoffice.model.documenteditor.config.document.ReferenceData;
import com.onlyoffice.service.command.CommandService;
import com.onlyoffice.service.convert.ConvertService;
import com.onlyoffice.service.documenteditor.callback.CallbackService;
import org.apache.http.HttpEntity;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.Resource;
import org.springframework.core.io.UrlResource;
import org.springframework.http.HttpHeaders;
@ -74,7 +80,6 @@ import java.io.IOException;
import java.io.InputStream;
import java.net.InetAddress;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
@ -91,22 +96,6 @@ import java.util.Optional;
@Controller
public class FileController {
@Value("${files.docservice.header}")
private String documentJwtHeader;
@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
private DocumentManager documentManager;
@Autowired
private JwtManager jwtManager;
@Autowired
@ -116,20 +105,29 @@ public class FileController {
@Autowired
private UserServices userService;
@Autowired
private CallbackHandler callbackHandler;
@Autowired
private ObjectMapper objectMapper;
@Autowired
private ServiceConverter serviceConverter;
@Autowired
private CallbackManager callbackManager;
@Autowired
private HistoryManager historyManager;
@Autowired
private DocumentManager documentManager;
@Autowired
private ConvertService convertService;
@Autowired
private RequestManager requestManager;
@Autowired
private SettingsManager settingsManager;
@Autowired
private CallbackService callbackService;
@Autowired
private CommandService commandService;
@Autowired
private UrlManager urlManager;
// create user metadata
private String createUserMetadata(final String uid, final String fullFileName) {
Optional<User> optionalUser = userService.findUserById(Integer.parseInt(uid)); // find a user by their ID
String documentType = fileUtility.getDocumentType(fullFileName).toString().toLowerCase(); // get document type
// get document type
String documentType = documentManager.getDocumentType(fullFileName).toString().toLowerCase();
if (optionalUser.isPresent()) {
User user = optionalUser.get();
storageMutator.createMeta(fullFileName, // create meta information with the user ID and name specified
@ -196,17 +194,17 @@ public class FileController {
@CookieValue("uid") final String uid) {
try {
String fullFileName = file.getOriginalFilename(); // get file name
String fileExtension = fileUtility.getFileExtension(fullFileName); // get file extension
String fileExtension = documentManager.getExtension(fullFileName); // get file extension
long fileSize = file.getSize(); // get file size
byte[] bytes = file.getBytes(); // get file in bytes
// check if the file size exceeds the maximum file size or is less than 0
if (fileUtility.getMaxFileSize() < fileSize || fileSize <= 0) {
if (documentManager.getMaxFileSize() < fileSize || fileSize <= 0) {
return "{ \"error\": \"File size is incorrect\"}"; // if so, write an error message to the response
}
// check if file extension is supported by the editor
if (!fileUtility.getFileExts().contains(fileExtension)) {
if (documentManager.getDocumentType(fullFileName) == null) {
// if not, write an error message to the response
return "{ \"error\": \"File type is not supported\"}";
@ -217,7 +215,7 @@ public class FileController {
throw new IOException("Could not update a file"); // if the file cannot be updated, an error occurs
}
fullFileName = fileUtility.getFileNameWithoutExtension(fileNamePath)
fullFileName = documentManager.getBaseName(fileNamePath)
+ "." + fileExtension; // get full file name
return createUserMetadata(uid, fullFileName); // create user metadata and return it
@ -235,80 +233,87 @@ public class FileController {
@CookieValue("uid") final String uid, @CookieValue("ulang") final String lang) {
// get file name
String fileName = body.getFileName();
// get URL for downloading a file with the specified name
String fileUri = documentManager.getDownloadUrl(fileName, true);
// get file password if it exists
String filePass = body.getFilePass() != null ? body.getFilePass() : null;
// get file extension
String fileExt = fileUtility.getFileExtension(fileName);
// get document type (word, cell or slide)
DocumentType type = fileUtility.getDocumentType(fileName);
// convert to .ooxml
String internalFileExt = "ooxml";
// get an auto-conversion extension from the request body or set it to the ooxml extension
String conversionExtension = body.getFileExt() != null ? body.getFileExt() : "ooxml";
try {
// check if the file with such an extension can be converted
if (fileUtility.getConvertExts().contains(fileExt)) {
String key = serviceConverter.generateRevisionId(fileUri); // generate document key
ConvertedData response = serviceConverter // get the URL to the converted file
.getConvertedData(fileUri, fileExt, internalFileExt, key, filePass, true, lang);
if (documentManager.getDefaultConvertExtension(fileName) != null) {
ConvertRequest convertRequest = ConvertRequest.builder()
.password(filePass)
.outputtype(conversionExtension)
.region(lang)
.async(true)
.build();
String newFileUri = response.getUri();
String newFileType = "." + response.getFileType();
ConvertResponse convertResponse = convertService.processConvert(convertRequest, fileName);
if (newFileUri.isEmpty()) {
return "{ \"step\" : \"0\", \"filename\" : \"" + fileName + "\"}";
if (convertResponse.getError() != null || convertResponse.getFileUrl() == null) {
return objectMapper.writeValueAsString(convertResponse);
}
String newFileUri = convertResponse.getFileUrl();
String newFileType = convertResponse.getFileType();
/* get a file name of an internal file extension with an index if the file
with such a name already exists */
String nameWithInternalExt = fileUtility.getFileNameWithoutExtension(fileName) + newFileType;
final String oldFileName = fileName;
String nameWithInternalExt = documentManager.getBaseName(fileName) + "." + newFileType;
String correctedName = documentManager.getCorrectName(nameWithInternalExt);
URL url = new URL(newFileUri);
java.net.HttpURLConnection connection = (java.net.HttpURLConnection) url.openConnection();
InputStream stream = connection.getInputStream(); // get input stream of the converted file
fileName = requestManager.executeGetRequest(newFileUri, new RequestManager.Callback<String>() {
public String doWork(final Object response) throws IOException {
InputStream stream = ((HttpEntity) response).getContent(); // get input stream of the converted
// file
if (stream == null) {
connection.disconnect();
throw new RuntimeException("Input stream is null");
}
if (stream == null) {
throw new RuntimeException("Input stream is null");
}
// remove source file
storageMutator.deleteFile(fileName);
// create the converted file with input stream
storageMutator.createFile(Path.of(storagePathBuilder.getFileLocation(correctedName)), stream);
fileName = correctedName;
// remove source file
storageMutator.deleteFile(oldFileName);
// create the converted file with input stream
storageMutator.createFile(Path.of(storagePathBuilder.getFileLocation(correctedName)), stream);
return correctedName;
}
});
}
// create meta information about the converted file with the user ID and name specified
return createUserMetadata(uid, fileName);
} catch (Exception e) {
e.printStackTrace();
// if the operation of file converting is unsuccessful, an error occurs
return "{ \"error\": \"" + e.getMessage() + "\"}";
}
// if the operation of file converting is unsuccessful, an error occurs
return "{ \"error\": \"" + "The file can't be converted.\"}";
}
@PostMapping("/delete")
@ResponseBody
public String delete(@RequestBody final Converter body) { // delete a file
try {
String fullFileName = fileUtility.getFileName(body.getFileName()); // get full file name
String filename = body.getFileName();
boolean success = false;
// delete a file from the storage and return the status of this operation (true or false)
boolean fileSuccess = storageMutator.deleteFile(fullFileName);
if (filename != null) {
String fullFileName = documentManager.getDocumentName(filename); // get full file name
// delete file history and return the status of this operation (true or false)
boolean historySuccess = storageMutator.deleteFileHistory(fullFileName);
// delete a file from the storage and return the status of this operation (true or false)
boolean fileSuccess = storageMutator.deleteFile(fullFileName);
return "{ \"success\": \"" + (fileSuccess && historySuccess) + "\"}";
// delete file history and return the status of this operation (true or false)
boolean historySuccess = storageMutator.deleteFileHistory(fullFileName);
success = fileSuccess && historySuccess;
} else {
// delete the user's folder and return the boolean status
success = storageMutator.deleteUserFolder();
}
return "{ \"success\": \"" + (success) + "\"}";
} catch (Exception e) {
// if the operation of file deleting is unsuccessful, an error occurs
return "{ \"error\": \"" + e.getMessage() + "\"}";
@ -322,13 +327,12 @@ public class FileController {
@RequestParam("file") final String file) { // history file
try {
// check if a token is enabled or not
if (jwtManager.tokenEnabled() && jwtManager.tokenUseForRequest()) {
String header = request.getHeader(documentJwtHeader == null // get the document JWT header
|| documentJwtHeader.isEmpty() ? "Authorization" : documentJwtHeader);
if (settingsManager.isSecurityEnabled()) {
String header = request.getHeader(settingsManager.getSecurityHeader());
if (header != null && !header.isEmpty()) {
String token = header
.replace("Bearer ", ""); // token is the header without the Bearer prefix
jwtManager.readToken(token); // read the token
jwtManager.verify(token); // read the token
} else {
return null;
}
@ -346,13 +350,12 @@ public class FileController {
final String userAddress) {
try {
// check if a token is enabled or not
if (jwtManager.tokenEnabled() && userAddress != null && jwtManager.tokenUseForRequest()) {
String header = request.getHeader(documentJwtHeader == null // get the document JWT header
|| documentJwtHeader.isEmpty() ? "Authorization" : documentJwtHeader);
if (settingsManager.isSecurityEnabled() && userAddress != null) {
String header = request.getHeader(settingsManager.getSecurityHeader());
if (header != null && !header.isEmpty()) {
String token = header
.replace("Bearer ", ""); // token is the header without the Bearer prefix
jwtManager.readToken(token); // read the token
jwtManager.verify(token); // read the token
} else {
return null;
}
@ -382,10 +385,10 @@ public class FileController {
sampleData,
uid,
user.get().getName()); // create a demo document with the sample data
if (fileName.isBlank() || fileName == null) {
if (fileName == null || fileName.isBlank()) {
throw new RuntimeException("You must have forgotten to add asset files");
}
return "redirect:editor?fileName=" + URLEncoder
return "redirect:editor?action=edit&fileName=" + URLEncoder
.encode(fileName, StandardCharsets.UTF_8); // redirect the request
} catch (Exception ex) {
model.addAttribute("error", ex.getMessage());
@ -418,28 +421,29 @@ public class FileController {
public String track(final HttpServletRequest request, // track file changes
@RequestParam("fileName") final String fileName,
@RequestParam("userAddress") final String userAddress,
@RequestBody final Track body) {
Track track;
@RequestBody final Callback body) {
Callback callback;
try {
String bodyString = objectMapper
.writeValueAsString(body); // write the request body to the object mapper as a string
String header = request.getHeader(documentJwtHeader == null // get the request header
|| documentJwtHeader.isEmpty() ? "Authorization" : documentJwtHeader);
if (bodyString.isEmpty()) { // if the request body is empty, an error occurs
throw new RuntimeException("{\"error\":1,\"message\":\"Request payload is empty\"}");
}
JSONObject bodyCheck = jwtManager.parseBody(bodyString, header); // parse the request body
track = objectMapper.readValue(bodyCheck.toJSONString(), Track.class); // read the request body
String authorizationHeader = request.getHeader(settingsManager.getSecurityHeader());
callback = callbackService.verifyCallback(body, authorizationHeader);
callbackService.processCallback(callback, fileName);
} catch (Exception e) {
e.printStackTrace();
return e.getMessage();
String message = e.getMessage();
if (!message.contains("\"error\":1")) {
e.printStackTrace();
}
return message;
}
int error = callbackHandler.handle(track, fileName);
return "{\"error\":" + error + "}";
return "{\"error\":\"0\"}";
}
@PostMapping("/saveas")
@ -447,24 +451,30 @@ public class FileController {
public String saveAs(@RequestBody final SaveAs body, @CookieValue("uid") final String uid) {
try {
String fileName = documentManager.getCorrectName(body.getTitle());
String curExt = fileUtility.getFileExtension(fileName);
if (!fileUtility.getFileExts().contains(curExt)) {
if (documentManager.getDocumentType(fileName) == null) {
return "{\"error\":\"File type is not supported\"}";
}
URL url = new URL(body.getUrl());
java.net.HttpURLConnection connection = (java.net.HttpURLConnection) url.openConnection();
InputStream stream = connection.getInputStream();
String url = body.getUrl();
if (Integer.parseInt(filesizeMax) < stream.available() || stream.available() <= 0) {
return "{\"error\":\"File size is incorrect\"}";
}
storageMutator.createFile(Path.of(storagePathBuilder.getFileLocation(fileName)), stream);
createUserMetadata(uid, fileName);
url = urlManager.replaceToInnerDocumentServerUrl(url);
return "{\"file\": \"" + fileName + "\"}";
} catch (IOException e) {
return requestManager.executeGetRequest(url, new RequestManager.Callback<String>() {
@Override
public String doWork(final Object response) throws Exception {
InputStream stream = ((HttpEntity) response).getContent();
if (documentManager.getMaxFileSize() < stream.available() || stream.available() <= 0) {
return "{\"error\":\"File size is incorrect\"}";
}
storageMutator.createFile(Path.of(storagePathBuilder.getFileLocation(fileName)), stream);
createUserMetadata(uid, fileName);
return "{\"file\": \"" + fileName + "\"}";
}
});
} catch (Exception e) {
e.printStackTrace();
return "{ \"error\" : 1, \"message\" : \"" + e.getMessage() + "\"}";
}
@ -473,14 +483,18 @@ public class FileController {
@PostMapping("/rename")
@ResponseBody
public String rename(@RequestBody final Rename body) {
String fileName = body.getFileName();
HashMap<String, String> meta = new HashMap<>();
meta.put("title", fileName + "." + body.getFileType());
CommandRequest commandRequest = CommandRequest.builder()
.key(body.getFileKey())
.c(Command.META)
.meta(Meta.builder()
.title(body.getFileName() + "." + body.getFileType())
.build())
.build();
try {
callbackManager.commandRequest("meta", body.getFileKey(), meta);
return "result ok";
CommandResponse commandResponse = commandService.processCommand(commandRequest, body.getFileName());
return commandResponse.getError().getDescription();
} catch (Exception e) {
e.printStackTrace();
return e.getMessage();
@ -514,7 +528,6 @@ public class FileController {
if (!link.contains(storagePathBuilder.getServerUrl(true))) {
HashMap<String, String> data = new HashMap<>();
data.put("url", link);
data.put("directUrl", link);
return gson.toJson(data);
}
@ -529,7 +542,8 @@ public class FileController {
if (fileName.equals("")) {
try {
String path = (String) body.getPath();
path = fileUtility.getFileName(path);
path = path.substring(path.lastIndexOf('/') + 1);
path = path.split("\\?")[0];
File f = new File(storagePathBuilder.getFileLocation(path));
if (f.exists()) {
fileName = path;
@ -552,19 +566,18 @@ public class FileController {
referenceData.put("fileKey", gson.toJson(fileKey));
HashMap<String, Object> data = new HashMap<>();
data.put("fileType", fileUtility.getFileExtension(fileName));
data.put("key", serviceConverter.generateRevisionId(
data.put("fileType", documentManager.getDocumentName(fileName));
data.put("key", documentManager.generateRevisionId(
storagePathBuilder.getStorageLocation()
+ "/" + fileName + "/"
+ new File(storagePathBuilder.getFileLocation(fileName)).lastModified()
));
data.put("url", documentManager.getDownloadUrl(fileName, true));
data.put("directUrl", body.getDirectUrl() ? documentManager.getDownloadUrl(fileName, false) : null);
data.put("url", urlManager.getFileUrl(fileName));
data.put("referenceData", referenceData);
data.put("path", fileName);
data.put("link", storagePathBuilder.getServerUrl(true) + "/editor?fileName=" + fileName);
if (jwtManager.tokenEnabled()) {
if (settingsManager.isSecurityEnabled()) {
String token = jwtManager.createToken(data);
data.put("token", token);
}
@ -584,9 +597,8 @@ public class FileController {
@GetMapping("/historydata")
@ResponseBody
public String history(@RequestParam("fileName") final String fileName,
@RequestParam("version") final String version,
@RequestParam(value = "directUrl", defaultValue = "false") final Boolean directUrl) {
return historyManager.getHistoryData(fileName, version, directUrl);
@RequestParam("version") final String version) {
return historyManager.getHistoryData(fileName, version);
}
@PutMapping("/restore")
@ -599,7 +611,7 @@ public class FileController {
String historyDirectory = storagePathBuilder.getHistoryDir(sourcePathFile.toString());
Integer bumpedVersion = storagePathBuilder.getFileVersion(historyDirectory, false);
String bumpedVersionStringDirectory = documentManager.versionDir(historyDirectory, bumpedVersion, true);
String bumpedVersionStringDirectory = historyManager.versionDir(historyDirectory, bumpedVersion, true);
File bumpedVersionDirectory = new File(bumpedVersionStringDirectory);
if (!bumpedVersionDirectory.exists()) {
bumpedVersionDirectory.mkdir();
@ -608,7 +620,7 @@ public class FileController {
Path bumpedKeyPathFile = Paths.get(bumpedVersionStringDirectory, "key.txt");
String bumpedKeyStringFile = bumpedKeyPathFile.toString();
File bumpedKeyFile = new File(bumpedKeyStringFile);
String bumpedKey = serviceConverter.generateRevisionId(
String bumpedKey = documentManager.generateRevisionId(
storagePathBuilder.getStorageLocation()
+ "/"
+ body.getFileName()
@ -642,13 +654,13 @@ public class FileController {
bumpedChangesFileWriter.write(bumpedChangesContent);
bumpedChangesFileWriter.close();
String sourceExtension = fileUtility.getFileExtension(body.getFileName());
String sourceExtension = documentManager.getExtension(body.getFileName());
String previousBasename = "prev." + sourceExtension;
Path bumpedFile = Paths.get(bumpedVersionStringDirectory, previousBasename);
Files.move(sourcePathFile, bumpedFile);
String recoveryVersionStringDirectory = documentManager.versionDir(
String recoveryVersionStringDirectory = historyManager.versionDir(
historyDirectory,
body.getVersion(),
true

View File

@ -0,0 +1,121 @@
/**
*
* (c) Copyright Ascensio System SIA 2024
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package com.onlyoffice.integration.controllers;
import com.onlyoffice.integration.dto.ForgottenFile;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.http.ResponseEntity;
import org.springframework.http.HttpStatus;
import com.onlyoffice.model.commandservice.CommandRequest;
import com.onlyoffice.model.commandservice.CommandResponse;
import com.onlyoffice.model.commandservice.commandrequest.Command;
import com.onlyoffice.manager.document.DocumentManager;
import com.onlyoffice.service.command.CommandService;
import java.util.ArrayList;
import java.util.List;
@CrossOrigin("*")
@Controller
public class ForgottenController {
@Value("${server.version}")
private String serverVersion;
@Value("${enable-forgotten}")
private String enableForgotten;
@Autowired
private CommandService commandService;
@Autowired
private DocumentManager documentManager;
@GetMapping("${url.forgotten}")
public String index(final Model model) {
if (!forgottenEnabled()) {
model.addAttribute("error", "The forgotten page is disabled");
return "error.html";
}
model.addAttribute("files", getForgottenFiles());
model.addAttribute("serverVersion", serverVersion);
return "forgotten.html";
}
private ArrayList<ForgottenFile> getForgottenFiles() {
ArrayList<ForgottenFile> files = new ArrayList<ForgottenFile>();
try {
CommandRequest commandRequest = CommandRequest.builder()
.c(Command.GET_FORGOTTEN_LIST)
.build();
CommandResponse commandResponse = commandService.processCommand(commandRequest, null);
List<String> keys = commandResponse.getKeys();
for (int i = 0; i < keys.size(); i++) {
commandRequest = CommandRequest.builder()
.c(Command.GET_FORGOTTEN)
.key(keys.get(i))
.build();
commandResponse = commandService.processCommand(commandRequest, null);
ForgottenFile file = new ForgottenFile(
commandResponse.getKey(),
documentManager.getDocumentType(commandResponse.getUrl()).toString().toLowerCase(),
commandResponse.getUrl()
);
files.add(file);
}
} catch (Exception e) {
e.printStackTrace();
}
return files;
}
private boolean forgottenEnabled() {
return Boolean.valueOf(enableForgotten);
}
@DeleteMapping("/forgotten/{filename}")
public ResponseEntity<String> delete(@PathVariable("filename") final String filename) {
if (!forgottenEnabled()) {
return new ResponseEntity<>(HttpStatus.FORBIDDEN);
}
try {
CommandRequest commandRequest = CommandRequest.builder()
.c(Command.DELETE_FORGOTTEN)
.key(filename)
.build();
CommandResponse commandResponse = commandService.processCommand(commandRequest, null);
return new ResponseEntity<>(HttpStatus.NO_CONTENT);
} catch (Exception e) {
e.printStackTrace();
return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
}
}
}

View File

@ -21,9 +21,11 @@ package com.onlyoffice.integration.controllers;
import com.onlyoffice.integration.documentserver.storage.FileStorageMutator;
import com.onlyoffice.integration.documentserver.storage.FileStoragePathBuilder;
import com.onlyoffice.integration.documentserver.util.Misc;
import com.onlyoffice.integration.documentserver.util.file.FileUtility;
import com.onlyoffice.integration.entities.User;
import com.onlyoffice.integration.sdk.manager.DocumentManager;
import com.onlyoffice.integration.sdk.manager.UrlManager;
import com.onlyoffice.integration.services.UserServices;
import com.onlyoffice.integration.dto.FormatsList;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
@ -31,8 +33,8 @@ import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.http.ResponseEntity;
import java.util.ArrayList;
import java.util.Arrays;
@ -52,20 +54,17 @@ public class IndexController {
@Autowired
private FileStoragePathBuilder storagePathBuilder;
@Autowired
private FileUtility fileUtility;
@Autowired
private Misc mistUtility;
@Autowired
private UserServices userService;
@Value("${files.docservice.url.site}")
private String docserviceSite;
@Autowired
private DocumentManager documentManager;
@Value("${files.docservice.url.preloader}")
private String docservicePreloader;
@Autowired
private UrlManager urlManager;
@Value("${url.converter}")
private String urlConverter;
@ -79,9 +78,11 @@ public class IndexController {
@Value("${server.version}")
private String serverVersion;
@Value("${enable-forgotten}")
private String enableForgotten;
@GetMapping("${url.index}")
public String index(@RequestParam(value = "directUrl", required = false) final Boolean directUrl,
final Model model) {
public String index(final Model model) {
java.io.File[] files = storageMutator.getStoredFiles(); // get all the stored files from the storage
List<String> docTypes = new ArrayList<>();
List<Boolean> filesEditable = new ArrayList<>();
@ -105,15 +106,14 @@ public class IndexController {
for (java.io.File file:files) { // run through all the files
String fileName = file.getName(); // get file name
docTypes.add(fileUtility
docTypes.add(documentManager
.getDocumentType(fileName)
.toString()
.toLowerCase()); // add a document type of each file to the list
filesEditable.add(fileUtility.getEditedExts()
.contains(fileUtility.getFileExtension(fileName))); // specify if a file is editable or not
filesEditable.add(documentManager.isEditable(fileName)); // specify if a file is editable or not
versions.add(" [" + storagePathBuilder.
getFileVersion(fileName, true) + "]"); // add a file version to the list
isFillFormDoc.add(fileUtility.getFillExts().contains(fileUtility.getFileExtension(fileName)));
isFillFormDoc.add(documentManager.isFillable(fileName));
}
// add all the parameters to the model
@ -122,12 +122,12 @@ public class IndexController {
model.addAttribute("files", files);
model.addAttribute("docTypes", docTypes);
model.addAttribute("filesEditable", filesEditable);
model.addAttribute("datadocs", docserviceSite + docservicePreloader);
model.addAttribute("datadocs", urlManager.getDocumentServerPreloaderApiUrl());
model.addAttribute("tooltip", tooltip);
model.addAttribute("users", users);
model.addAttribute("languages", languages);
model.addAttribute("directUrl", directUrl);
model.addAttribute("serverVersion", serverVersion);
model.addAttribute("enableForgotten", Boolean.valueOf(enableForgotten));
return "index.html";
}
@ -136,16 +136,16 @@ public class IndexController {
@ResponseBody
public HashMap<String, String> configParameters() { // get configuration parameters
HashMap<String, String> configuration = new HashMap<>();
configuration.put("FillExtList", String.join(",", fileUtility
.getFillExts())); // put a list of the extensions that can be filled to config
configuration.put("ConverExtList", String.join(",", fileUtility
.getConvertExts())); // put a list of the extensions that can be converted to config
configuration.put("EditedExtList", String.join(",", fileUtility
.getEditedExts())); // put a list of the extensions that can be edited to config
configuration.put("UrlConverter", urlConverter);
configuration.put("UrlEditor", urlEditor);
return configuration;
}
@GetMapping("/formats")
@ResponseBody
public ResponseEntity<FormatsList> formats() { // return all the supported formats
FormatsList list = new FormatsList(documentManager.getFormats());
return ResponseEntity.ok(list);
}
}

View File

@ -1,32 +0,0 @@
/**
*
* (c) Copyright Ascensio System SIA 2024
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package com.onlyoffice.integration.documentserver.callbacks;
import com.onlyoffice.integration.dto.Track;
import org.springframework.beans.factory.annotation.Autowired;
// specify the callback handler functions
public interface Callback {
int handle(Track body, String fileName); // handle the callback
int getStatus(); // get document status
@Autowired
default void selfRegistration(CallbackHandler callbackHandler) { // register a callback handler
callbackHandler.register(getStatus(), this);
}
}

View File

@ -1,50 +0,0 @@
/**
*
* (c) Copyright Ascensio System SIA 2024
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package com.onlyoffice.integration.documentserver.callbacks;
import com.onlyoffice.integration.dto.Track;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import java.util.HashMap;
import java.util.Map;
@Service
public class CallbackHandler {
private Logger logger = LoggerFactory.getLogger(CallbackHandler.class);
private Map<Integer, Callback> callbackHandlers = new HashMap<>();
public void register(final int code, final Callback callback) { // register a callback handler
callbackHandlers.put(code, callback);
}
public int handle(final Track body, final String fileName) { // handle a callback
Callback callback = callbackHandlers.get(body.getStatus());
if (callback == null) {
logger.warn("Callback status " + body.getStatus() + " is not supported yet");
return 0;
}
int result = callback.handle(body, fileName);
return result;
}
}

View File

@ -1,35 +0,0 @@
/**
*
* (c) Copyright Ascensio System SIA 2024
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package com.onlyoffice.integration.documentserver.callbacks;
// document status
public enum Status {
EDITING(1), // 1 - document is being edited
SAVE(2), // 2 - document is ready for saving
CORRUPTED(3), // 3 - document saving error has occurred
MUST_FORCE_SAVE(6), // 6 - document is being edited, but the current document state is saved
CORRUPTED_FORCE_SAVE(7); // 7 - error has occurred while force saving the document
private int code;
Status(final int codeParam) {
this.code = codeParam;
}
public int getCode() { // get document status
return this.code;
}
}

View File

@ -1,59 +0,0 @@
/**
*
* (c) Copyright Ascensio System SIA 2024
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package com.onlyoffice.integration.documentserver.callbacks.implementations;
import com.onlyoffice.integration.documentserver.callbacks.Callback;
import com.onlyoffice.integration.documentserver.callbacks.Status;
import com.onlyoffice.integration.documentserver.managers.callback.CallbackManager;
import com.onlyoffice.integration.dto.Action;
import com.onlyoffice.integration.dto.Track;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class EditCallback implements Callback {
@Autowired
private CallbackManager callbackManager;
@Override
public int handle(final Track body,
final String fileName) { // handle the callback when the document is being edited
int result = 0;
Action action = body.getActions().get(0); // get the user ID who is editing the document
if (action.getType().equals(com.onlyoffice.integration.documentserver.models.enums
.Action.edit)) { // if this value is not equal to the user ID
String user = action.getUserid(); // get user ID
if (!body.getUsers().contains(user)) { // if this user is not specified in the body
String key = body.getKey(); // get document key
try {
// create a command request to forcibly save the document being edited without closing it
callbackManager.commandRequest("forcesave", key, null);
} catch (Exception e) {
e.printStackTrace();
result = 1;
}
}
}
return result;
}
@Override
public int getStatus() { // get document status
return Status.EDITING.getCode(); // return status 1 - document is being edited
}
}

View File

@ -1,50 +0,0 @@
/**
*
* (c) Copyright Ascensio System SIA 2024
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package com.onlyoffice.integration.documentserver.callbacks.implementations;
import com.onlyoffice.integration.documentserver.callbacks.Callback;
import com.onlyoffice.integration.documentserver.callbacks.Status;
import com.onlyoffice.integration.documentserver.managers.callback.CallbackManager;
import com.onlyoffice.integration.dto.Track;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class ForcesaveCallback implements Callback {
@Autowired
private CallbackManager callbackManager;
@Override
public int handle(final Track body,
final String fileName) { // handle the callback when the force saving request is performed
int result = 0;
try {
callbackManager.processForceSave(body, fileName); // file force saving process
} catch (Exception ex) {
ex.printStackTrace();
result = 1;
}
return result;
}
@Override
public int getStatus() { // get document status
// return status 6 - document is being edited, but the current document state is saved
return Status.MUST_FORCE_SAVE.getCode();
}
}

View File

@ -1,50 +0,0 @@
/**
*
* (c) Copyright Ascensio System SIA 2024
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package com.onlyoffice.integration.documentserver.callbacks.implementations;
import com.onlyoffice.integration.documentserver.callbacks.Callback;
import com.onlyoffice.integration.documentserver.callbacks.Status;
import com.onlyoffice.integration.documentserver.managers.callback.CallbackManager;
import com.onlyoffice.integration.dto.Track;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class SaveCallback implements Callback {
@Autowired
private CallbackManager callbackManager;
@Override
public int handle(final Track body,
final String fileName) { // handle the callback when the saving request is performed
int result = 0;
try {
callbackManager.processSave(body, fileName); // file saving process
} catch (Exception ex) {
ex.printStackTrace();
result = 1;
}
return result;
}
@Override
public int getStatus() { // get document status
return Status.SAVE.getCode(); // return status 2 - document is ready for saving
}
}

View File

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

View File

@ -19,62 +19,60 @@
package com.onlyoffice.integration.documentserver.managers.callback;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.onlyoffice.integration.documentserver.managers.document.DocumentManager;
import com.onlyoffice.integration.documentserver.managers.jwt.JwtManager;
import com.onlyoffice.integration.documentserver.managers.history.HistoryManager;
import com.onlyoffice.integration.documentserver.storage.FileStorageMutator;
import com.onlyoffice.integration.documentserver.storage.FileStoragePathBuilder;
import com.onlyoffice.integration.documentserver.util.file.FileUtility;
import com.onlyoffice.integration.dto.Action;
import com.onlyoffice.integration.documentserver.util.service.ServiceConverter;
import com.onlyoffice.integration.dto.Track;
import com.onlyoffice.integration.sdk.manager.DocumentManager;
import com.onlyoffice.integration.sdk.manager.UrlManager;
import com.onlyoffice.manager.request.RequestManager;
import com.onlyoffice.model.commandservice.CommandRequest;
import com.onlyoffice.model.commandservice.commandrequest.Command;
import com.onlyoffice.model.convertservice.ConvertRequest;
import com.onlyoffice.model.convertservice.ConvertResponse;
import com.onlyoffice.model.documenteditor.Callback;
import com.onlyoffice.model.documenteditor.callback.Action;
import com.onlyoffice.model.documenteditor.callback.ForcesaveType;
import com.onlyoffice.model.documenteditor.callback.action.Type;
import com.onlyoffice.service.command.CommandService;
import com.onlyoffice.service.convert.ConvertService;
import lombok.SneakyThrows;
import org.apache.http.HttpEntity;
import org.json.simple.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Primary;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static com.onlyoffice.integration.documentserver.util.Constants.FILE_SAVE_TIMEOUT;
// todo: Refactoring
@Component
@Primary
public class DefaultCallbackManager implements CallbackManager {
@Value("${files.docservice.url.site}")
private String docserviceUrlSite;
@Value("${files.docservice.url.command}")
private String docserviceUrlCommand;
@Value("${files.docservice.header}")
private String documentJwtHeader;
@Autowired
private DocumentManager documentManager;
@Autowired
private JwtManager jwtManager;
@Autowired
private FileUtility fileUtility;
@Autowired
private FileStorageMutator storageMutator;
@Autowired
private FileStoragePathBuilder storagePathBuilder;
@Autowired
private ObjectMapper objectMapper;
@Autowired
private ServiceConverter serviceConverter;
private ConvertService convertService;
@Autowired
private RequestManager requestManager;
@Autowired
private CommandService commandService;
@Autowired
private HistoryManager historyManager;
@Autowired
private UrlManager urlManager;
// download file from url
@SneakyThrows
@ -83,23 +81,18 @@ public class DefaultCallbackManager implements CallbackManager {
throw new RuntimeException("Url argument is not specified"); // URL isn't specified
}
URL uri = new URL(url);
java.net.HttpURLConnection connection = (java.net.HttpURLConnection) uri.openConnection();
connection.setConnectTimeout(FILE_SAVE_TIMEOUT);
InputStream stream = connection.getInputStream(); // get input stream of the file information from the URL
return requestManager.executeGetRequest(url, new RequestManager.Callback<byte[]>() {
public byte[] doWork(final Object response) throws IOException {
InputStream stream = ((HttpEntity) response).getContent(); // get input stream of the converted
// file
int statusCode = connection.getResponseCode();
if (statusCode != HttpStatus.OK.value()) { // checking status code
connection.disconnect();
throw new RuntimeException("Document editing service returned status: " + statusCode);
}
if (stream == null) {
throw new RuntimeException("Input stream is null");
}
if (stream == null) {
connection.disconnect();
throw new RuntimeException("Input stream is null");
}
return stream.readAllBytes();
return stream.readAllBytes();
}
});
}
// file saving
@ -112,40 +105,76 @@ public class DefaultCallbackManager implements CallbackManager {
storageMutator.createOrUpdateFile(path, new ByteArrayInputStream(byteArray));
}
@Override
public void processEditing(final Callback callback, final String fileName) {
Action action = callback.getActions().get(0); // get the user ID who is editing the document
if (action.getType().equals(Type.CONNECTED)) { // if this value is not equal to the user ID
String user = action.getUserid(); // get user ID
if (!callback.getUsers().contains(user)) { // if this user is not specified in the body
CommandRequest commandRequest = CommandRequest.builder()
.c(Command.FORCESAVE)
.key(callback.getKey())
.build();
// create a command request to forcibly save the document being edited without closing it
try {
commandService.processCommand(commandRequest, fileName);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
}
@SneakyThrows
public void processSave(final Track body, final String fileName) { // file saving process
String downloadUri = body.getUrl();
String changesUri = body.getChangesurl();
String key = body.getKey();
public void processSave(final Callback callback, final String fileName) { // file saving process
String downloadUri = callback.getUrl();
String changesUri = callback.getChangesurl();
String key = callback.getKey();
String newFileName = fileName;
String curExt = fileUtility.getFileExtension(fileName); // get current file extension
String downloadExt = body.getFiletype(); // get an extension of the downloaded file
String curExt = documentManager.getExtension(fileName); // get current file extension
String downloadExt = callback.getFiletype(); // get an extension of the downloaded file
String storagePath = storagePathBuilder.getFileLocation(newFileName); // get the path to a new file
if (!Paths.get(storagePath).toFile().exists()) {
throw new RuntimeException("{\"error\":1, \"message\":\"file does not exist\"}");
}
downloadUri = urlManager.replaceToInnerDocumentServerUrl(downloadUri);
changesUri = urlManager.replaceToInnerDocumentServerUrl(changesUri);
// todo: Refactoring
// convert downloaded file to the file with the current extension if these extensions aren't equal
if (!curExt.equals(downloadExt)) {
try {
String newFileUri = serviceConverter
.getConvertedData(downloadUri, downloadExt, curExt,
serviceConverter.generateRevisionId(downloadUri), null, false,
null).getUri(); // convert a file and get URL to a new file
if (newFileUri.isEmpty()) {
ConvertRequest convertRequest = ConvertRequest.builder()
.key(documentManager.generateRevisionId(downloadUri))
.url(downloadUri)
.outputtype(curExt)
.async(false)
.build();
// convert a file and get URL to a new file
ConvertResponse convertResponse = convertService.processConvert(convertRequest, fileName);
String newFileUri = convertResponse.getFileUrl();
if (newFileUri == null || newFileUri.isEmpty()) {
newFileName = documentManager
.getCorrectName(fileUtility.getFileNameWithoutExtension(fileName) + "."
.getCorrectName(documentManager.getBaseName(fileName) + "."
+ downloadExt); // get the correct file name if it already exists
} else {
downloadUri = newFileUri;
}
} catch (Exception e) {
newFileName = documentManager
.getCorrectName(fileUtility.getFileNameWithoutExtension(fileName) + "." + downloadExt);
.getCorrectName(documentManager.getBaseName(fileName) + "." + downloadExt);
}
}
byte[] byteArrayFile = getDownloadFile(downloadUri); // download document file
String storagePath = storagePathBuilder.getFileLocation(newFileName); // get the path to a new file
Path lastVersion = Paths.get(storagePathBuilder
.getFileLocation(fileName)); // get the path to the last file version
@ -153,7 +182,7 @@ public class DefaultCallbackManager implements CallbackManager {
Path histDir = Paths.get(storagePathBuilder.getHistoryDir(storagePath)); // get the history directory
storageMutator.createDirectory(histDir); // and create it
String versionDir = documentManager
String versionDir = historyManager
.versionDir(histDir.toAbsolutePath().toString(), // get the file version directory
storagePathBuilder
.getFileVersion(histDir.toAbsolutePath().toString(), false), true);
@ -172,13 +201,13 @@ public class DefaultCallbackManager implements CallbackManager {
.of(versionDir + File.separator + "diff.zip")); // save file changes to the diff.zip archive
JSONObject jsonChanges = new JSONObject(); // create a json object for document changes
jsonChanges.put("changes", body.getHistory().getChanges()); // put the changes to the json object
jsonChanges.put("serverVersion", body.getHistory()
jsonChanges.put("changes", callback.getHistory().getChanges()); // put the changes to the json object
jsonChanges.put("serverVersion", callback.getHistory()
.getServerVersion()); // put the server version to the json object
String history = objectMapper.writeValueAsString(jsonChanges);
if (history == null && body.getHistory() != null) {
history = objectMapper.writeValueAsString(body.getHistory());
if (history == null && callback.getHistory() != null) {
history = objectMapper.writeValueAsString(callback.getHistory());
}
if (history != null && !history.isEmpty()) {
@ -194,82 +223,16 @@ public class DefaultCallbackManager implements CallbackManager {
}
}
// todo: Replace (String method) with (Enum method)
@SneakyThrows
public void commandRequest(final String method,
final String key,
final HashMap meta) { // create a command request
String documentCommandUrl = docserviceUrlSite + docserviceUrlCommand;
public void processForceSave(final Callback callback, final String fileNameParam) { // file force saving process
URL url = new URL(documentCommandUrl);
java.net.HttpURLConnection connection = (java.net.HttpURLConnection) url.openConnection();
HashMap<String, Object> params = new HashMap<String, Object>();
params.put("c", method);
params.put("key", key);
if (meta != null) {
params.put("meta", meta);
}
String headerToken;
// check if a secret key to generate token exists or not
if (jwtManager.tokenEnabled() && jwtManager.tokenUseForRequest()) {
Map<String, Object> payloadMap = new HashMap<>();
payloadMap.put("payload", params);
headerToken = jwtManager.createToken(payloadMap); // encode a payload object into a header token
// add a header Authorization with a header token and Authorization prefix in it
connection.setRequestProperty(documentJwtHeader.equals("")
? "Authorization" : documentJwtHeader, "Bearer " + headerToken);
String token = jwtManager.createToken(params); // encode a payload object into a body token
params.put("token", token);
}
String bodyString = objectMapper.writeValueAsString(params);
byte[] bodyByte = bodyString.getBytes(StandardCharsets.UTF_8);
connection.setRequestMethod("POST"); // set the request method
connection
.setRequestProperty("Content-Type", "application/json; charset=UTF-8"); // set the Content-Type header
connection.setDoOutput(true); // set the doOutput field to true
connection.connect();
try (OutputStream os = connection.getOutputStream()) {
os.write(bodyByte); // write bytes to the output stream
}
InputStream stream = connection.getInputStream(); // get input stream
if (stream == null) {
throw new RuntimeException("Could not get an answer");
}
String jsonString = serviceConverter.convertStreamToString(stream); // convert stream to json string
connection.disconnect();
JSONObject response = serviceConverter.convertStringToJSON(jsonString); // convert json string to json object
// todo: Add errors ENUM
String responseCode = response.get("error").toString();
switch (responseCode) {
case "0":
case "4":
break;
default:
throw new RuntimeException(response.toJSONString());
}
}
@SneakyThrows
public void processForceSave(final Track body, final String fileNameParam) { // file force saving process
String downloadUri = body.getUrl();
String downloadUri = callback.getUrl();
String fileName = fileNameParam;
String curExt = fileUtility.getFileExtension(fileName); // get current file extension
String downloadExt = body.getFiletype(); // get an extension of the downloaded file
String curExt = documentManager.getExtension(fileName); // get current file extension
String downloadExt = callback.getFiletype(); // get an extension of the downloaded file
downloadUri = urlManager.replaceToInnerDocumentServerUrl(downloadUri);
Boolean newFileName = false;
@ -277,11 +240,19 @@ public class DefaultCallbackManager implements CallbackManager {
// todo: Extract function
if (!curExt.equals(downloadExt)) {
try {
// convert file and get URL to a new file
String newFileUri = serviceConverter
.getConvertedData(downloadUri, downloadExt, curExt, serviceConverter
.generateRevisionId(downloadUri), null, false, null).getUri();
if (newFileUri.isEmpty()) {
ConvertRequest convertRequest = ConvertRequest.builder()
.key(documentManager.generateRevisionId(downloadUri))
.url(downloadUri)
.outputtype(curExt)
.async(false)
.build();
// convert a file and get URL to a new file
ConvertResponse convertResponse = convertService.processConvert(convertRequest, fileName);
String newFileUri = convertResponse.getFileUrl();
if (newFileUri == null || newFileUri.isEmpty()) {
newFileName = true;
} else {
downloadUri = newFileUri;
@ -296,32 +267,34 @@ public class DefaultCallbackManager implements CallbackManager {
// todo: Use ENUMS
// todo: Pointless toString conversion
boolean isSubmitForm = body.getForcesavetype().toString().equals("3");
boolean isSubmitForm = callback.getForcesavetype().equals(ForcesaveType.SUBMIT_FORM);
// todo: Extract function
if (isSubmitForm) { // if the form is submitted
if (newFileName) {
// get the correct file name if it already exists
fileName = documentManager
.getCorrectName(fileUtility
.getFileNameWithoutExtension(fileName) + "-form." + downloadExt);
.getCorrectName(documentManager
.getBaseName(fileName) + "-form." + downloadExt);
} else {
fileName = documentManager
.getCorrectName(fileUtility.getFileNameWithoutExtension(fileName) + "-form." + curExt);
.getCorrectName(documentManager.getBaseName(fileName) + "-form." + curExt);
}
forcesavePath = storagePathBuilder.getFileLocation(fileName); // create forcesave path if it doesn't exist
List<Action> actions = body.getActions();
Action action = actions.get(0);
List<com.onlyoffice.model.documenteditor.callback.Action> actions = callback.getActions();
com.onlyoffice.model.documenteditor.callback.Action action = actions.get(0);
String user = action.getUserid(); // get the user ID
// create meta data for the forcesaved file
storageMutator.createMeta(fileName, user, "Filling Form");
try {
String formsDataUrl = body.getFormsdataurl();
String formsDataUrl = callback.getFormsdataurl();
formsDataUrl = urlManager.replaceToInnerDocumentServerUrl(formsDataUrl);
if (formsDataUrl != null && !formsDataUrl.isEmpty()) {
String formsName = documentManager.getCorrectName(fileUtility
.getFileNameWithoutExtension(fileName) + ".txt");
String formsName = documentManager.getCorrectName(documentManager
.getBaseName(fileName) + ".txt");
String formsPath = storagePathBuilder.getFileLocation(formsName);
byte[] byteArrayFormsData = getDownloadFile(formsDataUrl);
@ -336,7 +309,7 @@ public class DefaultCallbackManager implements CallbackManager {
} else {
if (newFileName) {
fileName = documentManager
.getCorrectName(fileUtility.getFileNameWithoutExtension(fileName) + downloadExt);
.getCorrectName(documentManager.getBaseName(fileName) + "." + downloadExt);
}
forcesavePath = storagePathBuilder.getForcesavePath(fileName, false);

View File

@ -1,246 +0,0 @@
/**
*
* (c) Copyright Ascensio System SIA 2024
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package com.onlyoffice.integration.documentserver.managers.document;
import com.onlyoffice.integration.documentserver.storage.FileStorageMutator;
import com.onlyoffice.integration.documentserver.storage.FileStoragePathBuilder;
import com.onlyoffice.integration.documentserver.util.file.FileUtility;
import com.onlyoffice.integration.documentserver.util.service.ServiceConverter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Component;
import java.io.File;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.net.InetAddress;
import java.net.URLEncoder;
import java.net.UnknownHostException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.Map;
import static com.onlyoffice.integration.documentserver.util.Constants.KILOBYTE_SIZE;
@Component
@Primary
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}")
private String downloadUrl;
@Autowired
private FileStorageMutator storageMutator;
@Autowired
private FileStoragePathBuilder storagePathBuilder;
@Autowired
private FileUtility fileUtility;
@Autowired
private ServiceConverter serviceConverter;
// get URL to the created file
public String getCreateUrl(final String fileName, final Boolean sample) {
String fileExt = fileUtility.getFileExtension(fileName);
String url = storagePathBuilder.getServerUrl(true)
+ "/create?fileExt=" + fileExt + "&sample=" + sample;
return url;
}
// get a file name with an index if the file with such a name already exists
public String getCorrectName(final String fileName) {
String baseName = fileUtility.getFileNameWithoutExtension(fileName); // get file name without extension
String ext = fileUtility.getFileExtension(fileName); // get file extension
String name = baseName + "." + ext; // create a full file name
Path path = Paths.get(storagePathBuilder.getFileLocation(name));
// run through all the files with such a name in the storage directory
for (int i = 1; Files.exists(path); i++) {
name = baseName + " (" + i + ")." + ext; // and add an index to the base name
path = Paths.get(storagePathBuilder.getFileLocation(name));
}
return name;
}
// get file URL
public String getFileUri(final String fileName, final 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);
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());
return filePath;
} catch (UnsupportedEncodingException | UnknownHostException e) {
return "";
}
}
// get file URL
public String getHistoryFileUrl(final String fileName, final Integer version, final String file,
final 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 userAddress = forDocumentServer ? "&userAddress" + URLEncoder
.encode(hostAddress, java.nio.charset.StandardCharsets.UTF_8.toString()) : "";
String filePath = serverPath + "/downloadhistory?fileName=" + URLEncoder
.encode(filePathDownload, java.nio.charset.StandardCharsets.UTF_8.toString())
+ "&ver=" + version + "&file=" + file
+ userAddress;
return filePath;
} catch (UnsupportedEncodingException | UnknownHostException e) {
return "";
}
}
// get the callback URL
public String getCallback(final String fileName) {
String serverPath = storagePathBuilder.getServerUrl(true);
String storageAddress = storagePathBuilder.getStorageLocation();
try {
String query = trackUrl + "?fileName="
+ URLEncoder.encode(fileName, java.nio.charset.StandardCharsets.UTF_8.toString())
+ "&userAddress=" + URLEncoder
.encode(storageAddress, java.nio.charset.StandardCharsets.UTF_8.toString());
return serverPath + query;
} catch (UnsupportedEncodingException e) {
return "";
}
}
// get URL to download a file
public String getDownloadUrl(final String fileName, final Boolean isServer) {
String serverPath = storagePathBuilder.getServerUrl(isServer);
String storageAddress = storagePathBuilder.getStorageLocation();
try {
String userAddress = isServer ? "&userAddress=" + URLEncoder
.encode(storageAddress, java.nio.charset.StandardCharsets.UTF_8.toString()) : "";
String query = downloadUrl + "?fileName="
+ URLEncoder.encode(fileName, java.nio.charset.StandardCharsets.UTF_8.toString())
+ userAddress;
return serverPath + query;
} catch (UnsupportedEncodingException e) {
return "";
}
}
// get file information
public ArrayList<Map<String, Object>> getFilesInfo() {
ArrayList<Map<String, Object>> files = new ArrayList<>();
// run through all the stored files
for (File file : storageMutator.getStoredFiles()) {
Map<String, Object> map = new LinkedHashMap<>(); // write all the parameters to the map
map.put("version", storagePathBuilder.getFileVersion(file.getName(), false));
map.put("id", serviceConverter
.generateRevisionId(storagePathBuilder.getStorageLocation()
+ "/" + file.getName() + "/"
+ Paths.get(storagePathBuilder.getFileLocation(file.getName()))
.toFile()
.lastModified()));
map.put("contentLength", new BigDecimal(String.valueOf((file.length() / Double.valueOf(KILOBYTE_SIZE))))
.setScale(2, RoundingMode.HALF_UP) + " KB");
map.put("pureContentLength", file.length());
map.put("title", file.getName());
map.put("updated", String.valueOf(new Date(file.lastModified())));
files.add(map);
}
return files;
}
// get file information by its ID
public ArrayList<Map<String, Object>> getFilesInfo(final String fileId) {
ArrayList<Map<String, Object>> file = new ArrayList<>();
for (Map<String, Object> map : getFilesInfo()) {
if (map.get("id").equals(fileId)) {
file.add(map);
break;
}
}
return file;
}
// get the path to the file version by the history path and file version
public String versionDir(final String path, final Integer version, final boolean historyPath) {
if (!historyPath) {
return storagePathBuilder.getHistoryDir(storagePathBuilder.getFileLocation(path)) + version;
}
return path + File.separator + version;
}
// create demo document
public String createDemo(final String fileExt, final Boolean sample, final String uid, final String uname) {
String demoName = (sample ? "sample." : "new.")
+ fileExt; // create sample or new template file with the necessary extension
String demoPath =
"assets"
+ File.separator
+ "document-templates"
+ File.separator
+ (sample ? "sample" : "new")
+ File.separator
+ demoName;
// get a file name with an index if the file with such a name already exists
String fileName = getCorrectName(demoName);
InputStream stream = Thread.currentThread()
.getContextClassLoader()
.getResourceAsStream(demoPath); // get the input file stream
if (stream == null) {
return null;
}
storageMutator.createFile(Path.of(storagePathBuilder
.getFileLocation(fileName)), stream); // create a file in the specified directory
storageMutator.createMeta(fileName, uid, uname); // create meta information of the demo file
return fileName;
}
}

View File

@ -1,42 +0,0 @@
/**
*
* (c) Copyright Ascensio System SIA 2024
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package com.onlyoffice.integration.documentserver.managers.document;
import java.util.ArrayList;
import java.util.Map;
// specify the document manager functions
public interface DocumentManager {
// get a file name with an index if the file with such a name already exists
String getCorrectName(String fileName);
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, Boolean forDocumentServer); // get URL to download a file
ArrayList<Map<String, Object>> getFilesInfo(); // get file information
ArrayList<Map<String, Object>> getFilesInfo(String fileId); // get file information by its ID
// get the path to the file version by the history path and file version
String versionDir(String path, Integer version, boolean historyPath);
// create demo document
String createDemo(String fileExt, Boolean sample, String uid, String uname) throws Exception;
String getCreateUrl(String fileName, Boolean sample); // get URL to the created file
}

View File

@ -20,14 +20,17 @@ package com.onlyoffice.integration.documentserver.managers.history;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.onlyoffice.integration.documentserver.managers.document.DocumentManager;
import com.onlyoffice.integration.documentserver.managers.jwt.JwtManager;
import com.onlyoffice.integration.documentserver.models.filemodel.Document;
import com.onlyoffice.integration.documentserver.storage.FileStoragePathBuilder;
import com.onlyoffice.integration.documentserver.util.file.FileUtility;
import com.onlyoffice.integration.documentserver.util.service.ServiceConverter;
import com.onlyoffice.integration.sdk.manager.DocumentManager;
import com.onlyoffice.integration.sdk.manager.UrlManager;
import com.onlyoffice.manager.security.JwtManager;
import com.onlyoffice.manager.settings.SettingsManager;
import com.onlyoffice.model.common.User;
import com.onlyoffice.model.documenteditor.HistoryData;
import com.onlyoffice.model.documenteditor.callback.History;
import com.onlyoffice.model.documenteditor.history.Version;
import com.onlyoffice.model.documenteditor.historydata.Previous;
import lombok.SneakyThrows;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.springframework.beans.factory.annotation.Autowired;
@ -35,6 +38,7 @@ import org.springframework.stereotype.Component;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
@ -49,15 +53,9 @@ public class DefaultHistoryManager implements HistoryManager {
@Autowired
private FileStoragePathBuilder storagePathBuilder;
@Autowired
private DocumentManager documentManager;
@Autowired
private JwtManager jwtManager;
@Autowired
private FileUtility fileUtility;
@Autowired
private JSONParser parser;
@ -65,109 +63,13 @@ public class DefaultHistoryManager implements HistoryManager {
private ObjectMapper objectMapper;
@Autowired
private ServiceConverter serviceConverter;
private SettingsManager settingsManager;
// todo: Refactoring
@SneakyThrows
public String[] getHistory(final Document document) { // get document history
@Autowired
private UrlManager urlManager;
// get history directory
String histDir = storagePathBuilder.getHistoryDir(storagePathBuilder.getFileLocation(document.getTitle()));
Integer curVer = storagePathBuilder.getFileVersion(histDir, false); // get current file version
if (curVer > 0) { // check if the current file version is greater than 0
List<Object> hist = new ArrayList<>();
Map<String, Object> histData = new HashMap<>();
for (Integer i = 1; i <= curVer; i++) { // run through all the file versions
Map<String, Object> obj = new HashMap<String, Object>();
Map<String, Object> dataObj = new HashMap<String, Object>();
String verDir = documentManager
.versionDir(histDir, i, true); // get the path to the given file version
String key = i == curVer ? document.getKey() : readFileToEnd(new File(verDir
+ File.separator + "key.txt")); // get document key
obj.put("key", key);
obj.put("version", i);
if (i == 1) { // check if the version number is equal to 1
String createdInfo = readFileToEnd(new File(histDir
+ File.separator + "createdInfo.json")); // get file with meta data
JSONObject json = (JSONObject) parser.parse(createdInfo); // and turn it into json object
// write meta information to the object (user information and creation date)
obj.put("created", json.get("created"));
Map<String, Object> user = new HashMap<String, Object>();
user.put("id", json.get("id"));
user.put("name", json.get("name"));
obj.put("user", user);
}
dataObj.put("fileType", fileUtility
.getFileExtension(document.getTitle()));
dataObj.put("key", key);
dataObj.put("url", i == curVer ? document.getUrl()
: documentManager.getHistoryFileUrl(document.getTitle(), i, "prev." + fileUtility
.getFileExtension(document.getTitle()), true));
if (!document.getDirectUrl().equals("")) {
dataObj.put("directUrl", i == curVer ? document.getDirectUrl()
: documentManager.getHistoryFileUrl(document.getTitle(), i, "prev." + fileUtility
.getFileExtension(document.getTitle()), false));
}
dataObj.put("version", i);
if (i > 1) { //check if the version number is greater than 1
// if so, get the path to the changes.json file
JSONObject changes = (JSONObject) parser.parse(readFileToEnd(new File(documentManager
.versionDir(histDir, i - 1, true) + File.separator + "changes.json")));
JSONObject change = (JSONObject) ((JSONArray) changes.get("changes")).get(0);
// write information about changes to the object
obj.put("changes", changes.get("changes"));
obj.put("serverVersion", changes.get("serverVersion"));
obj.put("created", change.get("created"));
obj.put("user", change.get("user"));
// get the history data from the previous file version
Map<String, Object> prev = (Map<String, Object>) histData.get(Integer.toString(i - 2));
Map<String, Object> prevInfo = new HashMap<String, Object>();
prevInfo.put("fileType", prev.get("fileType"));
prevInfo.put("key", prev.get("key")); // write key and URL information about previous file version
prevInfo.put("url", prev.get("url"));
if (!document.getDirectUrl().equals("")) {
prevInfo.put("directUrl", prev.get("directUrl"));
}
// write information about previous file version to the data object
dataObj.put("previous", prevInfo);
// write the path to the diff.zip archive with differences in this file version
Integer verdiff = i - 1;
dataObj.put("changesUrl", documentManager
.getHistoryFileUrl(document.getTitle(), verdiff, "diff.zip", true));
}
if (jwtManager.tokenEnabled()) {
dataObj.put("token", jwtManager.createToken(dataObj));
}
hist.add(obj);
histData.put(Integer.toString(i - 1), dataObj);
}
// write history information about the current file version to the history object
Map<String, Object> histObj = new HashMap<String, Object>();
histObj.put("currentVersion", curVer);
histObj.put("history", hist);
try {
return new String[]{objectMapper.writeValueAsString(histObj),
objectMapper.writeValueAsString(histData)};
} catch (JsonProcessingException e) {
e.printStackTrace();
}
}
return new String[]{"", ""};
}
@Autowired
private DocumentManager documentManager;
// todo: Refactoring
@SneakyThrows
@ -178,16 +80,14 @@ public class DefaultHistoryManager implements HistoryManager {
Integer curVer = storagePathBuilder.getFileVersion(histDir, false); // get current file version
if (curVer > 0) { // check if the current file version is greater than 0
List<Object> hist = new ArrayList<>();
List<Version> history = new ArrayList<>();
for (Integer i = 1; i <= curVer; i++) { // run through all the file versions
Map<String, Object> obj = new HashMap<String, Object>();
String verDir = documentManager
.versionDir(histDir, i, true); // get the path to the given file version
String verDir = versionDir(histDir, i, true); // get the path to the given file version
String key;
if (i == curVer) {
key = serviceConverter
key = documentManager
.generateRevisionId(storagePathBuilder.getStorageLocation()
+ "/" + fileName + "/"
+ new File(storagePathBuilder.getFileLocation(fileName)).lastModified());
@ -195,8 +95,10 @@ public class DefaultHistoryManager implements HistoryManager {
key = readFileToEnd(new File(verDir + File.separator + "key.txt"));
}
obj.put("key", key);
obj.put("version", i);
Version version = Version.builder()
.key(key)
.version(String.valueOf(i))
.build();
if (i == 1) { // check if the version number is equal to 1
String createdInfo = readFileToEnd(new File(histDir
@ -204,33 +106,35 @@ public class DefaultHistoryManager implements HistoryManager {
JSONObject json = (JSONObject) parser.parse(createdInfo); // and turn it into json object
// write meta information to the object (user information and creation date)
obj.put("created", json.get("created"));
Map<String, Object> user = new HashMap<String, Object>();
user.put("id", json.get("id"));
user.put("name", json.get("name"));
obj.put("user", user);
version.setCreated(String.valueOf(json.get("created")));
version.setUser(User.builder()
.id(String.valueOf(json.get("id")))
.name(String.valueOf(json.get("name")))
.build()
);
}
if (i > 1) { //check if the version number is greater than 1
// if so, get the path to the changes.json file
JSONObject changes = (JSONObject) parser.parse(readFileToEnd(new File(documentManager
.versionDir(histDir, i - 1, true) + File.separator + "changes.json")));
JSONObject change = (JSONObject) ((JSONArray) changes.get("changes")).get(0);
InputStream changesSteam = new FileInputStream(
versionDir(histDir, i - 1, true) + File.separator + "changes.json");
History changes = objectMapper.readValue(changesSteam, History.class);
// write information about changes to the object
obj.put("changes", changes.get("changes"));
obj.put("serverVersion", changes.get("serverVersion"));
obj.put("created", change.get("created"));
obj.put("user", change.get("user"));
version.setChanges(changes.getChanges());
version.setServerVersion(changes.getServerVersion());
version.setCreated(changes.getChanges().get(0).getCreated());
version.setUser(changes.getChanges().get(0).getUser());
}
hist.add(obj);
history.add(version);
}
// write history information about the current file version to the history object
Map<String, Object> histObj = new HashMap<String, Object>();
histObj.put("currentVersion", curVer);
histObj.put("history", hist);
histObj.put("history", history);
try {
return objectMapper.writeValueAsString(histObj);
@ -243,74 +147,65 @@ public class DefaultHistoryManager implements HistoryManager {
// todo: Refactoring
@SneakyThrows
public String getHistoryData(final String fileName, final String version, final Boolean directUrl) {
public String getHistoryData(final String fileName, final String version) {
// get history directory
String histDir = storagePathBuilder.getHistoryDir(storagePathBuilder.getFileLocation(fileName));
Integer curVer = storagePathBuilder.getFileVersion(histDir, false); // get current file version
if (curVer > 0) { // check if the current file version is greater than 0
Map<String, Object> histData = new HashMap<>();
Map<String, HistoryData> historyDataMap = new HashMap<>();
for (Integer i = 1; i <= curVer; i++) { // run through all the file versions
Map<String, Object> dataObj = new HashMap<String, Object>();
String verDir = documentManager
.versionDir(histDir, i, true); // get the path to the given file version
String verDir = versionDir(histDir, i, true); // get the path to the given file version
String key;
if (i == curVer) {
key = serviceConverter
key = documentManager
.generateRevisionId(storagePathBuilder.getStorageLocation()
+ "/" + fileName + "/"
+ new File(storagePathBuilder.getFileLocation(fileName)).lastModified());
} else {
key = readFileToEnd(new File(verDir + File.separator + "key.txt"));
}
HistoryData historyData = HistoryData.builder()
.fileType(documentManager.getExtension(fileName))
.key(key)
.url(i == curVer ? urlManager.getFileUrl(fileName)
: urlManager.getHistoryFileUrl(fileName, i, "prev" + documentManager
.getExtension(fileName), true))
.build();
dataObj.put("fileType", fileUtility
.getFileExtension(fileName).replace(".", ""));
dataObj.put("key", key);
dataObj.put("url", i == curVer ? documentManager.getDownloadUrl(fileName, true)
: documentManager.getHistoryFileUrl(fileName, i, "prev" + fileUtility
.getFileExtension(fileName), true));
if (directUrl) {
dataObj.put("directUrl", i == curVer
? documentManager.getDownloadUrl(fileName, false)
: documentManager.getHistoryFileUrl(fileName, i, "prev" + fileUtility
.getFileExtension(fileName), false));
}
dataObj.put("version", i);
historyData.setVersion(String.valueOf(i));
if (i > 1) { //check if the version number is greater than 1
Integer verdiff = i - 1;
// get the history data from the previous file version
Map<String, Object> prev = (Map<String, Object>) histData.get(Integer.toString(verdiff));
Map<String, Object> prevInfo = new HashMap<String, Object>();
prevInfo.put("fileType", prev.get("fileType"));
prevInfo.put("key", prev.get("key")); // write key and URL information about previous file version
prevInfo.put("url", prev.get("url"));
if (directUrl) {
prevInfo.put("directUrl", prev.get("directUrl"));
}
HistoryData historyDataPrev = historyDataMap.get(Integer.toString(verdiff));
Previous previous = Previous.builder()
.fileType(historyDataPrev.getFileType())
.key(historyDataPrev.getKey())
.url(historyDataPrev.getUrl())
.build();
// write information about previous file version to the data object
dataObj.put("previous", prevInfo);
historyData.setPrevious(previous);
if (diffExists(histDir, verdiff)) {
// write the path to the diff.zip archive with differences in this file version
dataObj.put("changesUrl", documentManager
historyData.setChangesUrl(urlManager
.getHistoryFileUrl(fileName, verdiff, "diff.zip", true));
}
}
if (jwtManager.tokenEnabled()) {
dataObj.put("token", jwtManager.createToken(dataObj));
if (settingsManager.isSecurityEnabled()) {
historyData.setToken(jwtManager.createToken(historyData));
}
histData.put(Integer.toString(i), dataObj);
historyDataMap.put(Integer.toString(i), historyData);
}
try {
return objectMapper.writeValueAsString(histData.get(version));
return objectMapper.writeValueAsString(historyDataMap.get(version));
} catch (JsonProcessingException e) {
e.printStackTrace();
}
@ -318,6 +213,14 @@ public class DefaultHistoryManager implements HistoryManager {
return "";
}
@Override
public String versionDir(final String path, final Integer version, final boolean historyPath) {
if (!historyPath) {
return storagePathBuilder.getHistoryDir(storagePathBuilder.getFileLocation(path)) + version;
}
return path + File.separator + version;
}
// read a file
private String readFileToEnd(final File file) {

View File

@ -21,6 +21,6 @@ package com.onlyoffice.integration.documentserver.managers.history;
// specify the history manager functions
public interface HistoryManager {
String getHistory(String fileName); // get document history
String getHistoryData(String fileName, String version, Boolean directUrl); // get document history data
String getHistoryData(String fileName, String version); // get document history data
String versionDir(String path, Integer version, boolean historyPath);
}

View File

@ -1,130 +0,0 @@
/**
*
* (c) Copyright Ascensio System SIA 2024
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package com.onlyoffice.integration.documentserver.managers.jwt;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.primeframework.jwt.Signer;
import org.primeframework.jwt.Verifier;
import org.primeframework.jwt.domain.JWT;
import org.primeframework.jwt.hmac.HMACSigner;
import org.primeframework.jwt.hmac.HMACVerifier;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import java.util.LinkedHashMap;
import java.util.Map;
@Component
public class DefaultJwtManager implements JwtManager {
@Value("${files.docservice.secret}")
private String tokenSecret;
@Value("${files.docservice.token-use-for-request}")
private String tokenUseForRequest;
@Autowired
private ObjectMapper objectMapper;
@Autowired
private JSONParser parser;
// create document token
public String createToken(final Map<String, Object> payloadClaims) {
try {
// build a HMAC signer using a SHA-256 hash
Signer signer = HMACSigner.newSHA256Signer(tokenSecret);
JWT jwt = new JWT();
for (String key : payloadClaims.keySet()) { // run through all the keys from the payload
jwt.addClaim(key, payloadClaims.get(key)); // and write each claim to the jwt
}
return JWT.getEncoder().encode(jwt, signer); // sign and encode the JWT to a JSON string representation
} catch (Exception e) {
return "";
}
}
// check if the token is enabled
public boolean tokenEnabled() {
return tokenSecret != null && !tokenSecret.isEmpty();
}
public boolean tokenUseForRequest() {
return Boolean.parseBoolean(tokenUseForRequest) && !tokenUseForRequest.isEmpty();
}
// read document token
public JWT readToken(final String token) {
try {
// build a HMAC verifier using the token secret
Verifier verifier = HMACVerifier.newVerifier(tokenSecret);
// verify and decode the encoded string JWT to a rich object
return JWT.getDecoder().decode(token, verifier);
} catch (Exception exception) {
return null;
}
}
// parse the body
public JSONObject parseBody(final String payload, final String header) {
JSONObject body;
try {
Object obj = parser.parse(payload); // get body parameters by parsing the payload
body = (JSONObject) obj;
} catch (Exception ex) {
throw new RuntimeException("{\"error\":1,\"message\":\"JSON Parsing error\"}");
}
if (tokenEnabled() && tokenUseForRequest()) { // check if the token is enabled
String token = (String) body.get("token"); // get token from the body
if (token == null) { // if token is empty
if (header != null && !header.isBlank()) { // and the header is defined
// get token from the header (it is placed after the Bearer prefix if it exists)
token = header.startsWith("Bearer ") ? header.substring("Bearer ".length()) : header;
}
}
if (token == null || token.isBlank()) {
throw new RuntimeException("{\"error\":1,\"message\":\"JWT expected\"}");
}
JWT jwt = readToken(token); // read token
if (jwt == null) {
throw new RuntimeException("{\"error\":1,\"message\":\"JWT validation failed\"}");
}
if (jwt.getObject("payload") != null) { // get payload from the token and check if it is not empty
try {
@SuppressWarnings("unchecked") LinkedHashMap<String, Object> jwtPayload =
(LinkedHashMap<String, Object>) jwt.getObject("payload");
jwt.claims = jwtPayload;
} catch (Exception ex) {
throw new RuntimeException("{\"error\":1,\"message\":\"Wrong payload\"}");
}
}
try {
Object obj = parser.parse(objectMapper.writeValueAsString(jwt.claims));
body = (JSONObject) obj;
} catch (Exception ex) {
throw new RuntimeException("{\"error\":1,\"message\":\"Parsing error\"}");
}
}
return body;
}
}

View File

@ -1,33 +0,0 @@
/**
*
* (c) Copyright Ascensio System SIA 2024
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package com.onlyoffice.integration.documentserver.managers.jwt;
import org.json.simple.JSONObject;
import org.primeframework.jwt.domain.JWT;
import java.util.Map;
// specify the jwt manager functions
public interface JwtManager {
boolean tokenEnabled(); // check if the token is enabled
boolean tokenUseForRequest(); // check if the token is enabled
String createToken(Map<String, Object> payloadClaims); // create document token
JWT readToken(String token); // read document token
JSONObject parseBody(String payload, String header); // parse the body
}

View File

@ -1,70 +0,0 @@
/**
*
* (c) Copyright Ascensio System SIA 2024
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package com.onlyoffice.integration.documentserver.managers.template;
import com.onlyoffice.integration.documentserver.models.enums.DocumentType;
import com.onlyoffice.integration.documentserver.models.filemodel.Template;
import com.onlyoffice.integration.documentserver.managers.document.DocumentManager;
import com.onlyoffice.integration.documentserver.storage.FileStoragePathBuilder;
import com.onlyoffice.integration.documentserver.util.file.FileUtility;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;
import java.util.List;
@Component
@Qualifier("sample")
public class SampleTemplateManager implements TemplateManager {
@Autowired
private DocumentManager documentManager;
@Autowired
private FileStoragePathBuilder storagePathBuilder;
@Autowired
private FileUtility fileUtility;
// create a template document with the specified name
public List<Template> createTemplates(final String fileName) {
List<Template> templates = List.of(
new Template("", "Blank", documentManager
.getCreateUrl(fileName, false)), // create a blank template
new Template(getTemplateImageUrl(fileName), "With sample content", documentManager
.getCreateUrl(fileName,
true)) // create a template with sample content using the template image
);
return templates;
}
// get the template image URL for the specified file
public String getTemplateImageUrl(final String fileName) {
DocumentType fileType = fileUtility.getDocumentType(fileName); // get the file type
String path = storagePathBuilder.getServerUrl(true); // get server URL
if (fileType.equals(DocumentType.word)) { // get URL to the template image for the word document type
return path + "/css/img/file_docx.svg";
} else if (fileType.equals(DocumentType.slide)) { // get URL to the template image for the slide document type
return path + "/css/img/file_pptx.svg";
} else if (fileType.equals(DocumentType.cell)) { // get URL to the template image for the cell document type
return path + "/css/img/file_xlsx.svg";
}
return path + "/css/img/file_docx.svg"; // get URL to the template image for the default document type (word)
}
}

View File

@ -1,36 +0,0 @@
/**
*
* (c) Copyright Ascensio System SIA 2024
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package com.onlyoffice.integration.documentserver.models;
import java.util.List;
import com.onlyoffice.integration.documentserver.models.enums.DocumentType;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
@Getter
@Setter
@ToString
public class Format {
private String name;
private DocumentType type;
private List<String> actions;
private List<String> convert;
private List<String> mime;
}

View File

@ -1,51 +0,0 @@
/**
*
* (c) Copyright Ascensio System SIA 2024
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package com.onlyoffice.integration.documentserver.models.configurations;
import lombok.Getter;
import lombok.Setter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
@Component
@Scope("prototype")
@Getter
@Setter
/* The parameters which allow to customize the editor interface so that it looked like your
other products (if there are any) and change the presence or absence of the additional buttons,
links, change logos and editor owner details. */
public class Customization {
@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 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)
private Boolean compatibleFeatures = false; // the use of functionality only compatible with the OOXML format
private Boolean forcesave = false; /* add the request for the forced file saving to the callback handler
when saving the document within the document editing service */
private Boolean help = true; // if the Help menu button is displayed or hidden
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 = true; // if the Submit form button is displayed or hidden
private Boolean about = true;
private Boolean feedback = true;
}

View File

@ -1,40 +0,0 @@
/**
*
* (c) Copyright Ascensio System SIA 2024
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package com.onlyoffice.integration.documentserver.models.configurations;
import com.onlyoffice.integration.documentserver.models.enums.ToolbarDocked;
import lombok.Getter;
import lombok.Setter;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
@Component
@Scope("prototype")
@Getter
@Setter
/* The parameters which allow to change the settings
which define the behavior of the buttons in the embedded mode */
public class Embedded {
private String embedUrl; /* the absolute URL to the document serving as a source file for the document embedded
into the web page */
private String saveUrl; /* the absolute URL that will allow the document to be saved
onto the user personal computer */
private String shareUrl; // the absolute URL that will allow other users to share this document
private ToolbarDocked toolbarDocked; // the place for the embedded viewer toolbar, can be either top or bottom
}

View File

@ -1,48 +0,0 @@
/**
*
* (c) Copyright Ascensio System SIA 2024
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package com.onlyoffice.integration.documentserver.models.configurations;
import com.onlyoffice.integration.documentserver.storage.FileStoragePathBuilder;
import lombok.Getter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
@Component
@Scope("prototype")
public class Goback { // the settings for the Open file location menu button and upper right corner button
@Autowired
private FileStoragePathBuilder storagePathBuilder;
@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;
}
}

View File

@ -1,45 +0,0 @@
/**
*
* (c) Copyright Ascensio System SIA 2024
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package com.onlyoffice.integration.documentserver.models.configurations;
import lombok.Getter;
import lombok.Setter;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
@Component
@Scope("prototype")
@Getter
@Setter
/* The additional parameters for the document (document owner, folder where the document is stored,
uploading date, sharing settings) */
public class Info {
private String owner = "Me"; // the name of the document owner/creator
private Boolean favorite = null; // the highlighting state of the Favorite icon
private String uploaded = getDate(); // the document uploading date
private String getDate() {
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("EEE MMM dd yyyy", Locale.US);
return simpleDateFormat.format(new Date());
}
}

Some files were not shown because too many files have changed in this diff Show More