Compare commits

..

193 Commits

Author SHA1 Message Date
74d01268e7 Merge pull request #156 from ONLYOFFICE/feature/examples-descriptions
Examples descriptions
2021-05-05 10:12:05 +03:00
e57d6d0495 csharp-mvc: added screenshots 2021-05-05 10:05:02 +03:00
2809fc5408 csharp-mvc: added readme 2021-05-04 18:09:02 +03:00
c391683cb3 integration examples: added readme 2021-05-04 15:39:56 +03:00
0d276a5141 csharp-mvc: changed readme 2021-05-04 15:30:01 +03:00
138673fc80 ruby: added readme 2021-05-04 14:32:01 +03:00
18ad1fa8c6 python: added readme 2021-05-04 14:21:40 +03:00
7606f5f9bd php: added readme 2021-05-04 13:45:58 +03:00
16a3578c15 nodejs: added readme 2021-05-04 11:55:04 +03:00
3bb3f6e878 java: added readme 2021-05-04 11:21:17 +03:00
942c455af8 csharp: added readme 2021-04-30 15:00:48 +03:00
f183f8fc30 Merge pull request #155 from ONLYOFFICE/feature/description-user-rights
Feature/description user rights
2021-04-27 11:31:40 +03:00
6898f65fd7 nodejs, csharp: fix tabulation 2021-04-27 09:59:27 +03:00
99a7c667b3 ruby: add description for user rights 2021-04-27 01:05:59 +03:00
69c16e0441 python: add description for user rights 2021-04-27 00:56:45 +03:00
f691ac8069 php: add description for user rights 2021-04-27 00:46:08 +03:00
48ce83c494 csharp-mvc: add description for user rights 2021-04-27 00:34:23 +03:00
0309203b72 csharp: add description for user rights 2021-04-27 00:24:22 +03:00
a2b10800fc java: add description for user rights 2021-04-27 00:05:27 +03:00
06a48dcd4a nodejs: add description for user rights 2021-04-27 00:03:05 +03:00
7204c49b85 Merge pull request #154 from ONLYOFFICE/feature/users
Feature/users
2021-04-26 13:08:55 +03:00
c39aacbc6c ruby: add favorite and permissions at user list 2021-04-26 13:01:40 +03:00
0dec9d930d python: add favorite and permissions at user list 2021-04-26 12:51:36 +03:00
da92bf531d php: add favorite and permissions at user list 2021-04-26 12:40:18 +03:00
22ca55b4c3 csharp-mvc: add favorite and permissions at user list 2021-04-26 12:32:39 +03:00
f42480dfd2 csharp: add favorite and permissions at user list 2021-04-26 12:32:13 +03:00
a655bf002a java: add favorite and permissions at user list 2021-04-26 11:59:38 +03:00
d55e9beabe nodejs: add favorite and permissions at user list 2021-04-26 11:47:03 +03:00
a852056e87 php: fix function createMeta() 2021-04-23 18:00:16 +03:00
f908bba727 csharp: add list users 2021-04-23 17:39:41 +03:00
c679f7ddd3 csharp-mvc: add list users 2021-04-23 17:17:35 +03:00
ebdd865f73 php: add list users 2021-04-23 17:12:15 +03:00
2132798ee3 ruby: add list users 2021-04-23 17:11:52 +03:00
9ff5523631 python: add list users 2021-04-23 11:53:27 +03:00
6d44c1d2de java: add list users 2021-04-23 10:40:48 +03:00
49a9f10972 nodejs: add list users 2021-04-23 10:37:43 +03:00
0b0cdd395c nodejs, java, php, csharp, csharp-mvc, python, ruby: forbidden download, print and copy for uid-3 2021-04-22 16:27:52 +03:00
d8590783d8 Merge pull request #153 from ONLYOFFICE/bugfix/edit-button
nodejs, java, php, csharp, csharp-mvc, python, ruby
2021-04-22 11:34:47 +03:00
ba9d927fc0 nodejs, java, php, csharp, csharp-mvc, python, ruby: remove edit button for not OOXML 2021-04-22 11:29:59 +03:00
8f5797cd72 Merge pull request #152 from ONLYOFFICE/feature/jwt-download-files
Feature/jwt download files
2021-04-22 09:47:08 +03:00
3706659949 csharp: fix merge feature/comments-for-examples 2021-04-21 18:20:39 +03:00
495435c8ff Merge remote-tracking branch 'remotes/origin/develop' into feature/jwt-download-files
# Conflicts:
#	web/documentserver-example/csharp-mvc/Helpers/DocManagerHelper.cs
#	web/documentserver-example/csharp-mvc/Models/FileModel.cs
#	web/documentserver-example/csharp-mvc/WebEditor.ashx.cs
#	web/documentserver-example/csharp/DocEditor.aspx.cs
#	web/documentserver-example/csharp/WebEditor.ashx.cs
#	web/documentserver-example/java/src/main/java/controllers/IndexServlet.java
#	web/documentserver-example/java/src/main/java/entities/FileModel.java
#	web/documentserver-example/java/src/main/java/helpers/DocumentManager.java
#	web/documentserver-example/nodejs/helpers/docManager.js
#	web/documentserver-example/php/doceditor.php
#	web/documentserver-example/php/webeditor-ajax.php
#	web/documentserver-example/python/src/utils/docManager.py
#	web/documentserver-example/python/src/views/actions.py
#	web/documentserver-example/ruby/app/controllers/home_controller.rb
#	web/documentserver-example/ruby/app/models/document_helper.rb
#	web/documentserver-example/ruby/app/models/file_model.rb
2021-04-21 17:53:53 +03:00
5928ed1756 Merge pull request #151 from ONLYOFFICE/feature/user-permissions
Feature/user permissions
2021-04-21 17:32:25 +03:00
9125aca0ae Merge remote-tracking branch 'remotes/origin/master' into develop
# Conflicts:
#	Readme.md
2021-04-21 17:16:52 +03:00
15bba720d4 Merge pull request #150 from ONLYOFFICE/feature/comments-for-examples
Comments for examples
2021-04-21 17:13:15 +03:00
1364654e2b php: rever fileName 2021-04-21 17:12:30 +03:00
fac010d4bd php: revert symbol $ 2021-04-21 16:33:59 +03:00
82adaf6ad0 java: revert variable fileName 2021-04-21 16:10:16 +03:00
8d34ff2ed2 ruby: add jwt for download files 2021-04-21 15:54:21 +03:00
fb38127ebc python: add jwt for download files 2021-04-21 14:55:45 +03:00
27093c5c7a csharp: add jwt for download files 2021-04-21 13:13:52 +03:00
a2116bf3f7 csharp-mvc: add jwt for download files 2021-04-21 12:42:22 +03:00
1a825b9f17 php: add jwt for download files 2021-04-21 11:31:45 +03:00
0ba090e5ba java: add jwt for download files 2021-04-21 11:31:26 +03:00
fe803efd35 nodejs: added comments 2021-04-20 17:33:49 +03:00
f2714cb554 csharp-mvs: added comments 2021-04-20 17:33:49 +03:00
0997d2fef5 csharp: added comments 2021-04-20 17:33:48 +03:00
56a65a9f3e ruby: added comments 2021-04-20 17:33:48 +03:00
026237d286 php: added comments 2021-04-20 17:33:48 +03:00
beaffd40de java: added comments 2021-04-20 17:33:39 +03:00
592d8addc2 nodejs: add jwt for download files 2021-04-20 16:45:33 +03:00
6a1ecf8d0b python: added comments for python example 2021-04-20 15:46:41 +03:00
aff257ac8d Merge pull request #148 from ONLYOFFICE/feature/create-url
Feature/create url
2021-04-20 08:52:45 +03:00
47478fc3c5 ruby: forbidden to download, print and copy for uid-2 2021-04-19 18:31:59 +03:00
4ec3b7fb58 python: forbidden to download, print and copy for uid-2 2021-04-19 18:28:55 +03:00
03635575ab php: forbidden to download, print and copy for uid-2 2021-04-19 18:24:34 +03:00
389023cefb csharp: forbidden to download, print and copy for uid-2 2021-04-19 18:21:47 +03:00
1c5b0df480 csharp-mvc: forbidden to download, print and copy for uid-2 2021-04-19 18:17:14 +03:00
5f14f206bb java: forbidden to download, print and copy for uid-2 2021-04-19 18:01:33 +03:00
3bcfc0e714 nodejs: forbidden to download, print and copy for uid-2 2021-04-19 18:01:08 +03:00
2e2a45266d welcome moved to https://github.com/ONLYOFFICE/document-server-package/tree/master/common/documentserver-example/welcome 2021-04-19 12:25:37 +03:00
c48039970a Merge pull request #147 from ONLYOFFICE/feature/edit-buttons
Feature/edit buttons
2021-04-19 10:50:45 +03:00
1c8b4442d3 Merge pull request #146 from ONLYOFFICE/feature/reload-page
Feature/reload page
2021-04-19 10:47:40 +03:00
ea47d65231 python: add editorConfig.createUrl 2021-04-18 18:23:59 +03:00
487c54e471 ruby: add editorConfig.createUrl 2021-04-18 18:23:59 +03:00
b417633c3f csharp-mvc: add editorConfig.createUrl 2021-04-18 18:23:59 +03:00
9332035b33 csharp: add editorConfig.createUrl 2021-04-18 18:23:58 +03:00
f2bc452196 php: add editorConfig.createUrl 2021-04-18 18:23:58 +03:00
d3c89ba6cf java: add editorConfig.createUrl 2021-04-18 18:23:57 +03:00
2f7a2bd545 nodejs: add editorConfig.createUrl 2021-04-18 18:23:57 +03:00
55f7adcdc7 ruby: reload files list after closing upload dialog by Close button 2021-04-16 18:34:12 +03:00
b5cb5d864b python: reload files list after closing upload dialog by Close button 2021-04-16 18:33:38 +03:00
d9d0147990 csharp-mvc: reload files list after closing upload dialog by Close button 2021-04-16 18:33:03 +03:00
f0fef85852 csharp: reload files list after closing upload dialog by Close button 2021-04-16 18:32:14 +03:00
d8d068d260 php: reload files list after closing upload dialog by Close button 2021-04-16 18:31:20 +03:00
9db75e7f4e java: reload files list after closing upload dialog by Close button 2021-04-16 18:30:44 +03:00
72ec12d297 ruby: edit link only for editable format 2021-04-16 16:08:18 +03:00
6ea6e35d54 python: edit link only for editable format 2021-04-16 16:07:50 +03:00
ac4ef8fca5 csharp-mvc: edit link only for editable format 2021-04-16 16:04:42 +03:00
b94225e3e1 csharp: edit link only for editable format 2021-04-16 16:03:54 +03:00
cfec08c9d1 php: edit link only for editable format 2021-04-16 16:02:35 +03:00
dbf0d8bd67 java: edit link only for editable format 2021-04-16 16:01:24 +03:00
5dedcedb60 nodejs, java, php, csharp, csharp-mvc, python, ruby: bugfix window conversion 2021-04-16 10:38:26 +03:00
0dcdad7dad python: update readme version python 3.9+ 2021-04-15 11:23:37 +03:00
4fa5b7d864 Merge pull request #145 from ONLYOFFICE/feature/pass-for-convert
Feature/pass for convert
2021-04-15 09:35:47 +03:00
a85ea5c551 ruby: add password for convert 2021-04-14 18:13:09 +03:00
492b8b6c81 ruby: change api/convert method to post 2021-04-14 17:51:40 +03:00
a899483e5c python: add password for convert 2021-04-14 15:40:23 +03:00
7d766da6f0 python: change api/convert method to post 2021-04-14 15:30:13 +03:00
1f7b085455 csharp-mvc: add password for convert 2021-04-14 15:07:55 +03:00
d6db3cae2b csharp-mvc: change api/convert method to post 2021-04-14 14:47:22 +03:00
c89fa0e869 csharp: add password for convert 2021-04-14 14:46:30 +03:00
83395efc2b csharp: change api/convert method to post 2021-04-14 13:26:52 +03:00
e51b331736 php: add password for convert 2021-04-14 12:37:06 +03:00
7ed7263bc3 php: change api/convert method to post 2021-04-14 11:52:40 +03:00
376de19dae nodejs: add password for convert 2021-04-14 11:11:12 +03:00
71a70f335e nodejs: change api/convert method to post 2021-04-14 11:00:23 +03:00
388e473e3f java: add password for convert 2021-04-14 10:40:26 +03:00
e3c5f2008b java: change api/convert method to post 2021-04-14 10:40:25 +03:00
8751461695 Merge pull request #144 from ONLYOFFICE/feature/edit-button
Feature/edit button
2021-04-12 10:16:02 +03:00
2277c060bb nodejs: fix punctuation 2021-04-12 09:58:06 +03:00
ef064992f2 ruby: fix onRequestEditRights 2021-04-11 19:47:22 +03:00
e71acd9947 ruby: permissions.edit add condition view 2021-04-11 19:46:33 +03:00
f22c698cb6 csharp-mvc: fix onRequestEditRights 2021-04-11 19:45:26 +03:00
f788379eb5 csharp-mvc: permissions.edit add condition view 2021-04-11 19:44:37 +03:00
6eaa948d3a csharp: permissions.edit add condition view 2021-04-11 19:43:44 +03:00
b8af9b7d95 python: permissions.edit add condition view 2021-04-11 19:42:58 +03:00
56ec61ff43 php: permissions.edit add condition view 2021-04-11 19:42:21 +03:00
c46028c026 java: permissions.edit add condition view 2021-04-11 19:41:08 +03:00
77c9817dba nodejs: permissions.edit add condition view 2021-04-11 19:40:24 +03:00
ebc6a8a344 Merge pull request #143 from ONLYOFFICE/bugfix/history-user
Bugfix/history user
2021-04-09 13:29:13 +03:00
22d71b8923 ruby: fix null user 2021-04-09 13:16:09 +03:00
3bd85fd747 ruby: fix filling file createdInfo.json 2021-04-09 13:15:28 +03:00
9f5c4b479b python: fix null user 2021-04-09 13:01:43 +03:00
8a0a1d3a42 csharp: fix null user 2021-04-09 12:51:32 +03:00
9d46cb6b4e csharp-mvc: fix null user 2021-04-09 12:42:54 +03:00
243b9daafc java: fix null user 2021-04-09 12:33:23 +03:00
54565a4848 nodejs: fix null user 2021-04-09 12:14:32 +03:00
18d2a7f511 Merge pull request #142 from ONLYOFFICE/bugfix/php-vulnerability
Bugfix/php vulnerability
2021-04-06 13:49:39 +03:00
ab5163f237 php: xss with user name 2021-04-06 13:46:42 +03:00
8ab2ba4edc php: not used parameters 2021-04-06 13:45:04 +03:00
4996de1aea php: revert local configuration 2021-04-06 10:23:30 +03:00
5e6d45cfd0 nodejs, java, php, csharp, csharp-mvc, python, ruby: changed min-height page 2021-04-05 18:02:21 +03:00
b67bc6164a Merge pull request #138 from ONLYOFFICE/feature/start-button
welcome: add check available for start button
2021-03-31 10:22:12 +03:00
0a909ed4f7 welcome: add check available for start button 2021-03-30 18:27:20 +03:00
f55bbab827 Merge pull request #137 from ONLYOFFICE/feature/update-dependencies
ruby: update dependencies
2021-03-30 12:22:22 +03:00
193b0aeb80 ruby: update dependencies 2021-03-30 12:15:33 +03:00
abe807f288 Merge pull request #135 from ONLYOFFICE/feature/fix-filename
Feature/fix filename
2021-03-30 12:06:34 +03:00
db8d816660 Merge pull request #134 from ONLYOFFICE/feature/redesign
Feature/redesign
2021-03-30 12:05:20 +03:00
1aa00012bf Merge pull request #136 from ONLYOFFICE/feature/welcome-redesign
Feature/welcome redesign
2021-03-30 11:44:23 +03:00
4f44082456 Merge pull request #129 from ONLYOFFICE/dependabot/bundler/web/documentserver-example/ruby/nokogiri-1.11.1
build(deps): bump nokogiri from 1.10.10 to 1.11.1 in /web/documentserver-example/ruby
2021-03-30 10:54:14 +03:00
578ecec9af csharp-mvc: ext to lowercase 2021-03-29 18:28:52 +03:00
25804d0c0a csharp: ext to lowercase 2021-03-29 18:16:53 +03:00
6b27f4c221 php: ext to lowercase 2021-03-29 17:59:45 +03:00
bfa0984daf ruby: extname to downcase 2021-03-29 17:31:39 +03:00
b4d19b2f1e nodejs: fix function getFileName 2021-03-29 17:00:18 +03:00
ce4a6ec67e add button start 2021-03-26 14:39:19 +03:00
ba172dd5d4 java: fix view embedded 2021-03-25 22:11:13 +03:00
1fb48547ed csharp: fix documentType 2021-03-25 22:10:44 +03:00
7884f3c64c Merge remote-tracking branch 'remotes/origin/develop' into feature/redesign
# Conflicts:
#	web/documentserver-example/nodejs/views/index.ejs
#	web/documentserver-example/python/templates/index.html
2021-03-25 21:31:22 +03:00
4f2d7f0a3f nodejs: fix punctuation 2021-03-25 21:27:43 +03:00
d4e984e6b3 nodejs, java, php, python, csharp, csharp-mvc, ruby: fix remove upload name 2021-03-25 21:24:04 +03:00
93df5adba2 nodejs, java: fix css 2021-03-25 16:47:18 +03:00
87089d3fd1 nodejs, java, php: fix quotes 2021-03-25 16:42:35 +03:00
8ca58370e9 ruby: redesign window upload 2021-03-25 16:31:48 +03:00
599da25503 ruby: added tooltips 2021-03-25 15:27:32 +03:00
1bfe1b383b ruby: redesign 2021-03-25 15:15:35 +03:00
0645fba83d python: redesign window upload 2021-03-25 10:58:56 +03:00
7dade2ff46 python: added tooltips 2021-03-24 21:17:27 +03:00
d2b5335de9 python: redesign 2021-03-24 21:09:35 +03:00
4a617b516b php: redesign window upload 2021-03-24 14:00:33 +03:00
f4331cbd0a php: added tooltips 2021-03-24 10:40:38 +03:00
3665ead0b7 php: redesign 2021-03-23 22:25:49 +03:00
1baf3617b0 csharp-mvc: redesign window upload 2021-03-23 15:46:38 +03:00
367629d01f csharp-mvc: added tooltips 2021-03-23 14:39:38 +03:00
76b4693a54 csharp-mvc: redesign 2021-03-23 14:28:09 +03:00
f54e505aad fix readme 2021-03-23 11:38:20 +03:00
d8452548f0 apache to license 2021-03-23 11:36:18 +03:00
1dda4bbe5e csharp: redesign window upload 2021-03-22 23:11:50 +03:00
899df4f39f csharp: added tooltips 2021-03-22 21:17:33 +03:00
c416712ac3 csharp: redesign 2021-03-22 16:42:25 +03:00
b5b7cd91c4 Merge pull request #132 from ONLYOFFICE/feature/fill-forms
Feature/fill forms
2021-03-22 12:47:47 +03:00
e8c17005bb java: redesign window upload 2021-03-21 21:31:15 +03:00
53ec97b0c8 nodejs: redesign window upload 2021-03-21 15:59:49 +03:00
0646e25240 java: added tooltips 2021-03-19 16:05:33 +03:00
e7445dbc46 ruby: added postfix -form isSubmitForm 2021-03-19 15:02:05 +03:00
42b24e4307 python: added postfix -form isSubmitForm 2021-03-19 14:53:34 +03:00
1ba0577521 csharp-mvc: added postfix -form isSubmitForm 2021-03-19 14:43:58 +03:00
3335a135a0 csharp: added postfix -form isSubmitForm 2021-03-19 14:34:25 +03:00
c2a75b3e28 php: added postfix -form isSubmitForm 2021-03-19 14:15:23 +03:00
4e2fe9e607 java: added postfix -form isSubmitForm 2021-03-19 14:13:43 +03:00
3eb2061b9f nodejs: added postfix -form isSubmitForm 2021-03-19 13:50:26 +03:00
fcdcefe662 nodejs: revert local configuration 2021-03-18 15:32:55 +03:00
8aa32308c0 java: redesign 2021-03-18 11:55:42 +03:00
94beb67552 nodejs: added tooltips 2021-03-16 23:22:49 +03:00
3c1eab070d nodejs: redesign 2021-03-16 00:06:26 +03:00
714b514f66 Copyright 2021 2021-03-15 11:54:47 +03:00
89e6ac8571 Merge remote-tracking branch 'remotes/origin/release/v6.3.0' into develop 2021-03-05 11:20:57 +03:00
9f9ac0c30d Merge remote-tracking branch 'origin/release/v6.3.0' into develop 2021-03-04 16:10:51 +03:00
879d8f64fb build(deps): bump nokogiri in /web/documentserver-example/ruby
Bumps [nokogiri](https://github.com/sparklemotion/nokogiri) from 1.10.10 to 1.11.1.
- [Release notes](https://github.com/sparklemotion/nokogiri/releases)
- [Changelog](https://github.com/sparklemotion/nokogiri/blob/main/CHANGELOG.md)
- [Commits](https://github.com/sparklemotion/nokogiri/compare/v1.10.10...v1.11.1)

Signed-off-by: dependabot[bot] <support@github.com>
2021-03-01 09:21:06 +00:00
539023bd25 Rename images 2020-11-26 11:45:06 +03:00
0ada5484bb Rename icons on welcome page 2020-11-26 11:41:37 +03:00
b4e4a7ba53 redesign welcome page 2020-11-26 11:29:00 +03:00
339 changed files with 10842 additions and 5783 deletions

View File

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

View File

@ -0,0 +1,17 @@
# Integration examples
## To start integrating document editors into your own website you need to do the following:
1. Download [Document Server installation](https://www.onlyoffice.com/developer-edition-request.aspx?from=api.onlyoffice.com) and set it up on your local server.
2. Select the programming language and clone the source code for the sample of online editors integration into your web site.
3. [Edit the configuration files](https://api.onlyoffice.com/editors/advanced) in the sample changing the default path for the one to the editors installed at step 1 and other advanced parameters available for editor configuration.
4. In case the example and Document Server are installed on different computers, make sure that your server with the example installed has access to the Document Server with the address which you specify instead of **documentserver** in the configuration files. And you must also make sure that the Document Server in its turn has access to the server with the example installed with the address which you specify instead of **example.com** in the configuration files.
Please note that the integration examples are used to demonstrate document editors functions and the ways to connect **Document Server** to your own application. **DO NOT USE** these examples on your own server without **PROPER CODE MODIFICATIONS**!
The result should look like the [demo preview](https://api.onlyoffice.com/editors/demopreview#DemoPreview) on our web site.
If you have any further questions, please contact us at [integration@onlyoffice.com](mailto:integration@onlyoffice.com).

View File

@ -1,6 +1,6 @@
/**
*
* (c) Copyright Ascensio System SIA 2020
* (c) Copyright Ascensio System SIA 2021
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -22,8 +22,10 @@ namespace OnlineEditorsExampleMVC
{
public class BundleConfig
{
// register bundles
public static void RegisterBundles(BundleCollection bundles)
{
// create a jquery script bundle
bundles.Add(new ScriptBundle("~/bundles/jquery").Include(
"~/Scripts/jquery-{version}.js",
"~/Scripts/jquery-ui.js",
@ -33,15 +35,18 @@ namespace OnlineEditorsExampleMVC
"~/Scripts/jquery.dropdownToggle.js"
));
// create the main script bundle
bundles.Add(new ScriptBundle("~/bundles/scripts").Include(
"~/Scripts/jscript.js"
));
// create a style bundle
bundles.Add(new StyleBundle("~/Content/css").Include(
"~/Content/stylesheet.css",
"~/Content/jquery-ui.css"
));
// create an editor style bundle
bundles.Add(new StyleBundle("~/Content/editor").Include(
"~/Content/editor.css"
));

View File

@ -1,6 +1,6 @@
/**
*
* (c) Copyright Ascensio System SIA 2020
* (c) Copyright Ascensio System SIA 2021
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -22,6 +22,7 @@ namespace OnlineEditorsExampleMVC
{
public class FilterConfig
{
// register global filters
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new HandleErrorAttribute());

View File

@ -1,6 +1,6 @@
/**
*
* (c) Copyright Ascensio System SIA 2020
* (c) Copyright Ascensio System SIA 2021
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -23,10 +23,12 @@ namespace OnlineEditorsExampleMVC
{
public class RouteConfig
{
// register routes
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
// create a route map
routes.MapRoute(
name: "Default",
url: "{action}",

View File

@ -1,6 +1,6 @@
/**
*
* (c) Copyright Ascensio System SIA 2020
* (c) Copyright Ascensio System SIA 2021
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

View File

@ -1,6 +1,6 @@
/**
*
* (c) Copyright Ascensio System SIA 2020
* (c) Copyright Ascensio System SIA 2021
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 197 B

View File

@ -0,0 +1,3 @@
<svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M0.294404 0.294466C-0.0961199 0.68499 -0.0998005 1.32183 0.290724 1.71236L5.57837 7L5.57841 7.00005L0.29081 12.2877C-0.0997145 12.6782 -0.0960336 13.315 0.294491 13.7055C0.685015 14.0961 1.32186 14.0997 1.71238 13.7092L6.99999 8.42162L12.2876 13.7092C12.6781 14.0997 13.315 14.0961 13.7055 13.7055C14.096 13.315 14.0997 12.6782 13.7092 12.2877L8.42156 7.00005L8.42161 7L13.7093 1.71236C14.0998 1.32183 14.0961 0.68499 13.7056 0.294466C13.315 -0.0960591 12.6782 -0.0997395 12.2877 0.290785L7.00003 5.57843L6.99999 5.57847L6.99994 5.57843L1.7123 0.290785C1.32177 -0.0997395 0.684928 -0.0960591 0.294404 0.294466Z" fill="#AAAAAA"/>
</svg>

After

Width:  |  Height:  |  Size: 781 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 232 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 631 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 d="M10.3765 15.128C9.98789 15.5187 9.35642 15.5214 8.96449 15.134L6.14517 12.3473C5.75561 11.9622 5.12876 11.9622 4.7392 12.3473L4.72038 12.3659C4.32403 12.7576 4.32441 13.3978 4.72124 13.7891L8.96526 17.974C9.35702 18.3603 9.98726 18.3576 10.3757 17.9679L20.2877 8.02323C20.6801 7.6296 20.67 6.9855 20.2729 6.59668C19.8804 6.21243 19.2454 6.21063 18.8581 6.60005L10.3765 15.128Z" fill="#8BB825"/>
</svg>

After

Width:  |  Height:  |  Size: 507 B

View File

@ -0,0 +1,3 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M7.99857 1.6C4.46508 1.6 1.6 4.46548 1.6 8.00029C1.6 9.70508 2.26458 11.2515 3.35202 12.3999C4.52033 13.6337 6.16874 14.4 7.99857 14.4C11.5348 14.4 14.4 11.5335 14.4 8.00029C14.4 4.46592 11.5348 1.6 7.99857 1.6ZM0 8.00029C0 3.58219 3.58105 0 7.99857 0C12.4184 0 16 3.58219 16 8.00029C16 12.4172 12.4184 16 7.99857 16C5.71117 16 3.64805 15.0395 2.19023 13.5C0.83265 12.0663 0 10.1304 0 8.00029ZM7 4H9V9H7V4ZM9 10H7V12H9V10Z" fill="#CB0000"/>
</svg>

After

Width:  |  Height:  |  Size: 593 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 682 B

View File

@ -0,0 +1,8 @@
<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 0H21.674C22.4697 0 23.2327 0.316071 23.7953 0.87868L29.1213 6.20465C29.6839 6.76726 30 7.53032 30 8.32597V37C30 38.6569 28.6569 40 27 40H3C1.34315 40 0 38.6569 0 37V3Z" fill="#3779A6"/>
<path d="M22.9167 0L30.0001 7.08333H25.9167C24.2599 7.08333 22.9167 5.74019 22.9167 4.08333V0Z" fill="#1D5880"/>
<path d="M6.17627 14.7059H23.8233V15.8823H6.17627V14.7059Z" fill="white"/>
<path d="M6.17627 18.5294H23.8233V19.7059H6.17627V18.5294Z" fill="white"/>
<path d="M6.17627 22.3529H23.8233V23.5294H6.17627V22.3529Z" fill="white"/>
<path d="M6.17627 26.1765H23.8233V27.3529H6.17627V26.1765Z" fill="white"/>
</svg>

After

Width:  |  Height:  |  Size: 738 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 728 B

View File

@ -0,0 +1,8 @@
<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 0H22.9167L30 7.08333V37C30 38.6569 28.6569 40 27 40H3C1.34315 40 0 38.6569 0 37V3Z" fill="#F36700"/>
<path d="M22.9167 0L30.0001 7.08333H25.9168C24.2599 7.08333 22.9167 5.74019 22.9167 4.08333V0Z" fill="#AB531F"/>
<path d="M6.17627 16.1275H23.8233V17.3039H6.17627V16.1275Z" fill="white"/>
<path d="M6.17627 28.7745L6.17627 16.1275L7.35274 16.1275L7.35274 28.7745H6.17627Z" fill="white"/>
<path d="M23.8233 16.1275V28.7745H22.6469V16.1275L23.8233 16.1275Z" fill="white"/>
<path d="M6.17627 27.598H23.8233V28.7745H6.17627L6.17627 27.598Z" fill="white"/>
</svg>

After

Width:  |  Height:  |  Size: 691 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

View File

@ -0,0 +1,6 @@
<svg width="30" height="40" viewBox="0 0 30 40" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M30 7.44186L22 0H3C1.22739 0 0 0.822551 0 2.32558V37.2093C0 38.7123 1.22739 40 3 40H27C28.7726 40 30 38.7123 30 37.2093V7.44186Z" fill="#D0D5DA"/>
<path d="M24.1042 7.27273H29.9631L22 0V5.32334C22 6.4105 22.949 7.27273 24.1042 7.27273Z" fill="#646464"/>
<path d="M16.9562 22.3485H12.9746V17.803H10.9839L14.9654 14.1667L18.947 17.803H16.9562V22.3485Z" fill="#646464"/>
<path d="M20.9378 23.7121C20.9378 24.1666 20.4401 24.6212 19.9424 24.6212H9.98848C9.49078 24.6212 8.99309 24.1666 8.99309 23.7121V22.3485C8.99309 21.8939 9.49078 21.4394 9.98848 21.4394H10.9839V20.0757H9.49078C8.49539 20.0757 7.5 20.9848 7.5 21.8939V24.1666C7.5 25.0757 8.61982 25.9848 9.49078 25.9848H20.4401C21.3111 25.9848 22.4309 25.0757 22.4309 24.1666V21.8939C22.4309 20.9848 21.4355 20.0757 20.4401 20.0757H18.947V21.4394H19.9424C20.4401 21.4394 20.9378 21.8939 20.9378 22.3485V23.7121Z" fill="#646464"/>
</svg>

After

Width:  |  Height:  |  Size: 992 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 744 B

View File

@ -0,0 +1,12 @@
<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 0H22.9167L30 7.08333V37C30 38.6569 28.6569 40 27 40H3C1.34315 40 0 38.6569 0 37V3Z" fill="#78A73B"/>
<path d="M22.9167 0L30.0001 7.08333H25.9168C24.2599 7.08333 22.9167 5.74019 22.9167 4.08333V0Z" fill="#5A7D2B"/>
<path d="M6.17644 15.2941H23.8235V16.4706H6.17644V15.2941Z" fill="white"/>
<path d="M6.17644 19.1177H23.8235V20.2941H6.17644V19.1177Z" fill="white"/>
<path d="M6.17644 22.9412H23.8235V24.1177H6.17644V22.9412Z" fill="white"/>
<path d="M6.17644 26.7647H23.8235V27.9412H6.17644V26.7647Z" fill="white"/>
<path d="M5.88232 27.9412L5.88232 15.2941L7.0588 15.2941L7.0588 27.9412H5.88232Z" fill="white"/>
<path d="M11.4706 27.9412L11.4706 15.2941L12.647 15.2941V27.9412H11.4706Z" fill="white"/>
<path d="M17.0588 27.9412L17.0588 15.2941L18.2353 15.2941V27.9412H17.0588Z" fill="white"/>
<path d="M22.647 27.9412V15.2941H23.8235V27.9412H22.647Z" fill="white"/>
</svg>

After

Width:  |  Height:  |  Size: 1004 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

View File

@ -0,0 +1,12 @@
<svg width="17" height="16" viewBox="0 0 17 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M2.84616 1H10.8462L14.8462 5V15H2.84616V1Z" fill="white"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M14.8462 5L10.8462 1H2.84616V15H14.8462V5ZM10.8462 0L15.8462 5V16H1.84616V0H10.8462Z" fill="#BFBFBF"/>
<rect x="3.84616" y="10" width="10" height="4" fill="#3779A6"/>
<path d="M3.84616 4H4.84616V5H3.84616V4Z" fill="#BFBFBF"/>
<path d="M3.84616 6H4.84616V7H3.84616V6Z" fill="#BFBFBF"/>
<path d="M4.84616 8H3.84616V9H4.84616V8Z" fill="#BFBFBF"/>
<path d="M12.8462 8H5.84616V9H12.8462V8Z" fill="#BFBFBF"/>
<path d="M7.84616 6H5.84616V7H7.84616V6Z" fill="#BFBFBF"/>
<path d="M12.8462 4H5.84616V5H12.8462V4Z" fill="#BFBFBF"/>
<path opacity="0.3" d="M9.84616 1H10.8462V4H14.8462L15.8462 5H9.84616V1Z" fill="#333333"/>
</svg>

After

Width:  |  Height:  |  Size: 832 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

View File

@ -0,0 +1,12 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M2 1H10L14 5V15H2V1Z" fill="white"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M14 5L10 1H2V15H14V5ZM10 0L15 5V16H1V0H10Z" fill="#BFBFBF"/>
<rect x="3" y="10" width="10" height="4" fill="#F36700"/>
<path d="M3 4H4V5H3V4Z" fill="#BFBFBF"/>
<path d="M3 6H4V7H3V6Z" fill="#BFBFBF"/>
<path d="M4 8H3V9H4V8Z" fill="#BFBFBF"/>
<path d="M12 8H5V9H12V8Z" fill="#BFBFBF"/>
<path d="M7 6H5V7H7V6Z" fill="#BFBFBF"/>
<path d="M12 4H5V5H12V4Z" fill="#BFBFBF"/>
<path opacity="0.3" d="M9 1H10V4H14L15 5H9V1Z" fill="#333333"/>
</svg>

After

Width:  |  Height:  |  Size: 631 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

View File

@ -0,0 +1,12 @@
<svg width="17" height="16" viewBox="0 0 17 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M2.84592 1H10.8459L14.8459 5V15H2.84592V1Z" fill="white"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M14.8459 5L10.8459 1H2.84592V15H14.8459V5ZM10.8459 0L15.8459 5V16H1.84592V0H10.8459Z" fill="#BFBFBF"/>
<rect x="3.84592" y="10" width="10" height="4" fill="#78A73B"/>
<path d="M3.84592 4H4.84592V5H3.84592V4Z" fill="#BFBFBF"/>
<path d="M3.84592 6H4.84592V7H3.84592V6Z" fill="#BFBFBF"/>
<path d="M4.84592 8H3.84592V9H4.84592V8Z" fill="#BFBFBF"/>
<path d="M12.8459 8H5.84592V9H12.8459V8Z" fill="#BFBFBF"/>
<path d="M7.84592 6H5.84592V7H7.84592V6Z" fill="#BFBFBF"/>
<path d="M12.8459 4H5.84592V5H12.8459V4Z" fill="#BFBFBF"/>
<path opacity="0.3" d="M9.84592 1H10.8459V4H14.8459L15.8459 5H9.84592V1Z" fill="#333333"/>
</svg>

After

Width:  |  Height:  |  Size: 832 B

View File

@ -0,0 +1,3 @@
<svg width="12" height="12" viewBox="0 0 12 12" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M6 12C9.31371 12 12 9.31371 12 6C12 2.68629 9.31371 0 6 0C2.68629 0 0 2.68629 0 6C0 9.31371 2.68629 12 6 12ZM5 6C5 5.44772 5.44772 5 6 5C6.55228 5 7 5.44772 7 6V9C7 9.55229 6.55228 10 6 10C5.44772 10 5 9.55229 5 9V6ZM6 2C5.44772 2 5 2.44772 5 3C5 3.55228 5.44772 4 6 4C6.55228 4 7 3.55228 7 3C7 2.44772 6.55228 2 6 2Z" fill="#D0D5DA"/>
</svg>

After

Width:  |  Height:  |  Size: 488 B

View File

@ -1,15 +1,15 @@
<svg width="248" height="53" viewBox="0 0 248 53" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M24.9111 46.0096L7.13565 37.771C5.62145 37.0517 5.62145 35.9401 7.13565 35.2863L13.3241 32.4093L24.8453 37.771C26.3595 38.4902 28.7954 38.4902 30.2437 37.771L41.7648 32.4093L47.9533 35.2863C49.4675 36.0055 49.4675 37.1171 47.9533 37.771L30.1779 46.0096C28.7954 46.6635 26.3595 46.6635 24.9111 46.0096Z" fill="#FF6F3D"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M24.9111 35.8748L7.13565 27.6361C5.62145 26.9169 5.62145 25.8053 7.13565 25.1514L13.1925 22.3398L24.9111 27.7669C26.4253 28.4861 28.8612 28.4861 30.3096 27.7669L42.0282 22.3398L48.085 25.1514C49.5992 25.8707 49.5992 26.9823 48.085 27.6361L30.3096 35.8748C28.7953 36.594 26.3595 36.594 24.9111 35.8748Z" fill="#95C038"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M24.9111 26.0014L7.13565 17.7628C5.62145 17.0435 5.62145 15.9319 7.13565 15.2781L24.9111 7.03944C26.4253 6.32019 28.8612 6.32019 30.3096 7.03944L48.085 15.2781C49.5992 15.9973 49.5992 17.1089 48.085 17.7628L30.3096 26.0014C28.7953 26.6553 26.3595 26.6553 24.9111 26.0014Z" fill="#5DC0E8"/>
<path d="M60.085 26.4189C60.085 23.0116 61.0651 20.44 63.0906 18.7685C65.0509 17.0327 67.4031 16.197 70.0821 16.197C72.7611 16.197 75.048 17.0327 77.0083 18.7685C78.9685 20.5043 79.9486 23.0116 79.9486 26.4832C79.9486 29.8906 78.9685 32.4621 77.0083 34.1336C75.048 35.8695 72.6958 36.7052 70.0821 36.7052C67.4031 36.7052 65.1162 35.8695 63.0906 34.1336C61.0651 32.3978 60.085 29.8263 60.085 26.4189ZM64.3975 26.4189C64.3975 28.7976 64.8548 30.4692 65.7043 31.5621C66.619 32.655 67.5992 33.3622 68.6446 33.6193C68.906 33.6836 69.102 33.7479 69.3634 33.7479C69.5594 33.7479 69.8208 33.8122 70.0168 33.8122C70.2781 33.8122 70.4742 33.8122 70.7355 33.7479C70.9969 33.7479 71.1929 33.6836 71.4543 33.6193C72.4997 33.3622 73.4798 32.655 74.3293 31.5621C75.1787 30.4692 75.6361 28.7334 75.6361 26.4832C75.6361 24.1688 75.1787 22.4973 74.3293 21.4044C73.4798 20.3115 72.4997 19.6043 71.4543 19.3471C71.1929 19.2828 70.9315 19.2186 70.7355 19.2186C70.4742 19.2186 70.2781 19.1543 70.0168 19.1543C69.7554 19.1543 69.5594 19.1543 69.3634 19.2186C69.1673 19.2186 68.906 19.2828 68.6446 19.3471C67.5992 19.6043 66.619 20.3115 65.7043 21.4044C64.8548 22.3687 64.3975 24.1045 64.3975 26.4189Z" fill="white"/>
<path d="M82.105 16.3898H87.4629L94.5198 28.9905L95.5652 31.755H95.6306L95.5652 28.1548V16.3898H99.6817V36.4481H94.3237L87.2669 23.3331L86.2215 21.0829H86.1561L86.2215 24.6188V36.4481H82.105V16.3898Z" fill="white"/>
<path d="M103.929 16.3898H108.045V33.0407H116.147V36.4481H103.929V16.3898Z" fill="white"/>
<path d="M113.599 16.3898H118.369L122.551 23.3974L123.204 24.8117H123.335L123.988 23.3974L128.235 16.3898H132.613L125.23 28.2833V36.4481H121.113V28.219L113.599 16.3898Z" fill="white"/>
<path d="M132.091 26.4189C132.091 23.0116 133.071 20.44 135.096 18.7685C137.057 17.0327 139.409 16.197 142.088 16.197C144.767 16.197 147.054 17.0327 149.014 18.7685C150.974 20.5043 151.954 23.0116 151.954 26.4832C151.954 29.8906 150.974 32.4621 149.014 34.1336C147.054 35.8695 144.702 36.7052 142.088 36.7052C139.409 36.7052 137.122 35.8695 135.096 34.1336C133.136 32.3978 132.091 29.8263 132.091 26.4189ZM136.403 26.4189C136.403 28.7976 136.861 30.4692 137.71 31.5621C138.625 32.655 139.54 33.3622 140.65 33.6193C140.912 33.6836 141.108 33.7479 141.369 33.7479C141.565 33.7479 141.827 33.8122 142.023 33.8122C142.284 33.8122 142.48 33.8122 142.741 33.7479C143.003 33.7479 143.199 33.6836 143.46 33.6193C144.506 33.3622 145.486 32.655 146.335 31.5621C147.185 30.4692 147.642 28.7334 147.642 26.4832C147.642 24.1688 147.185 22.4973 146.335 21.4044C145.486 20.3115 144.506 19.6043 143.46 19.3471C143.199 19.2828 142.937 19.2186 142.741 19.2186C142.48 19.2186 142.284 19.1543 142.023 19.1543C141.761 19.1543 141.565 19.1543 141.369 19.2186C141.173 19.2186 140.912 19.2828 140.65 19.3471C139.605 19.6043 138.625 20.3115 137.71 21.4044C136.861 22.3687 136.403 24.1045 136.403 26.4189Z" fill="white"/>
<path d="M154.829 16.3898H166.198V19.7329H158.946V24.6188H165.872V28.0262H158.946V36.4481H154.829V16.3898Z" fill="white"/>
<path d="M169.27 16.3898H180.639V19.7329H173.386V24.6188H180.312V28.0262H173.386V36.4481H169.27V16.3898Z" fill="white"/>
<path d="M183.057 36.4481V16.3898H187.173V36.4481H183.057Z" fill="white"/>
<path d="M205.311 16.8397V20.3113C204.592 20.0542 203.873 19.8613 203.089 19.7327C202.305 19.6041 201.39 19.5398 200.476 19.5398C198.319 19.5398 196.686 20.1827 195.51 21.5328C194.334 22.8186 193.746 24.4901 193.746 26.4831C193.746 28.4117 194.268 30.019 195.379 31.3048C196.49 32.5905 198.058 33.2977 200.084 33.2977C200.802 33.2977 201.521 33.2334 202.371 33.1692C203.22 33.0406 204.069 32.8477 204.984 32.462L205.246 35.8693C205.115 35.9336 204.919 35.9979 204.723 36.0622C204.462 36.1265 204.2 36.1907 203.873 36.255C203.351 36.3836 202.697 36.4479 201.913 36.5765C201.129 36.6408 200.345 36.7051 199.496 36.7051C199.365 36.7051 199.234 36.7051 199.169 36.7051C199.038 36.7051 198.908 36.7051 198.842 36.7051C196.49 36.5765 194.334 35.6764 192.373 34.1335C190.413 32.5263 189.433 30.019 189.433 26.6759C189.433 23.3972 190.413 20.8256 192.308 19.0255C194.203 17.2254 196.817 16.3254 200.018 16.3254C200.868 16.3254 201.652 16.3254 202.305 16.3897C203.024 16.454 203.677 16.5825 204.396 16.7111C204.527 16.7754 204.723 16.7754 204.854 16.8397C204.984 16.7754 205.115 16.8397 205.311 16.8397Z" fill="white"/>
<path d="M208.578 16.3899H220.797V19.5401H212.76V24.5546H220.013V27.6405H212.76V33.298H220.797V36.4481H208.578V16.3899Z" fill="white"/>
</svg>
<svg width="153" height="28" viewBox="0 0 153 28" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M13.3403 27.6567L0.801116 21.8897C-0.267039 21.3862 -0.267039 20.6081 0.801116 20.1504L5.16662 18.1365L13.2939 21.8897C14.362 22.3932 16.0804 22.3932 17.1021 21.8897L25.2294 18.1365L29.5949 20.1504C30.663 20.6539 30.663 21.432 29.5949 21.8897L17.0556 27.6567C16.0804 28.1144 14.362 28.1144 13.3403 27.6567Z" fill="#FF6F3D"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M13.3403 20.5623L0.801116 14.7953C-0.267039 14.2918 -0.267039 13.5137 0.801116 13.056L5.07373 11.0879L13.3403 14.8868C14.4085 15.3903 16.1268 15.3903 17.1485 14.8868L25.4151 11.0879L29.6877 13.056C30.7559 13.5595 30.7559 14.3376 29.6877 14.7953L17.1485 20.5623C16.0804 21.0658 14.362 21.0658 13.3403 20.5623Z" fill="#95C038"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M13.3403 13.651L0.801116 7.88393C-0.267039 7.38045 -0.267039 6.60236 0.801116 6.14466L13.3403 0.377605C14.4085 -0.125868 16.1268 -0.125868 17.1485 0.377605L29.6877 6.14466C30.7559 6.64813 30.7559 7.42622 29.6877 7.88393L17.1485 13.651C16.0804 14.1087 14.362 14.1087 13.3403 13.651Z" fill="#5DC0E8"/>
<path d="M38.1528 13.9433C38.1528 11.5581 38.8442 9.75803 40.2731 8.58797C41.6559 7.3729 43.3152 6.78787 45.2051 6.78787C47.0949 6.78787 48.7081 7.3729 50.0909 8.58797C51.4737 9.80304 52.1651 11.5581 52.1651 13.9883C52.1651 16.3734 51.4737 18.1735 50.0909 19.3436C48.7081 20.5586 47.0488 21.1437 45.2051 21.1437C43.3152 21.1437 41.702 20.5586 40.2731 19.3436C38.8442 18.1285 38.1528 16.3284 38.1528 13.9433ZM41.195 13.9433C41.195 15.6084 41.5176 16.7784 42.1168 17.5435C42.7621 18.3085 43.4535 18.8035 44.191 18.9835C44.3754 19.0285 44.5137 19.0735 44.698 19.0735C44.8363 19.0735 45.0207 19.1185 45.159 19.1185C45.3433 19.1185 45.4816 19.1185 45.666 19.0735C45.8504 19.0735 45.9886 19.0285 46.173 18.9835C46.9105 18.8035 47.6019 18.3085 48.2011 17.5435C48.8003 16.7784 49.123 15.5633 49.123 13.9883C49.123 12.3682 48.8003 11.1981 48.2011 10.4331C47.6019 9.66803 46.9105 9.173 46.173 8.99299C45.9886 8.94799 45.8043 8.90299 45.666 8.90299C45.4816 8.90299 45.3433 8.85798 45.159 8.85798C44.9746 8.85798 44.8363 8.85798 44.698 8.90299C44.5598 8.90299 44.3754 8.94799 44.191 8.99299C43.4535 9.173 42.7621 9.66803 42.1168 10.4331C41.5176 11.1081 41.195 12.3232 41.195 13.9433Z" fill="white"/>
<path d="M53.6863 6.92288H57.4659L62.444 15.7434L63.1814 17.6785H63.2275L63.1814 15.1583V6.92288H66.0853V20.9636H62.3057L57.3276 11.7831L56.5901 10.2081H56.544L56.5901 12.6832V20.9636H53.6863V6.92288Z" fill="white"/>
<path d="M69.0813 6.92288H71.9852V18.5785H77.7007V20.9636H69.0813V6.92288Z" fill="white"/>
<path d="M75.9031 6.92288H79.2679L82.2178 11.8281L82.6787 12.8182H82.7709L83.2319 11.8281L86.2279 6.92288H89.3161L84.1076 15.2483V20.9636H81.2038V15.2033L75.9031 6.92288Z" fill="white"/>
<path d="M88.9473 13.9433C88.9473 11.5581 89.6387 9.75803 91.0675 8.58797C92.4503 7.3729 94.1097 6.78787 95.9995 6.78787C97.8893 6.78787 99.5026 7.3729 100.885 8.58797C102.268 9.80304 102.96 11.5581 102.96 13.9883C102.96 16.3734 102.268 18.1735 100.885 19.3436C99.5026 20.5586 97.8432 21.1437 95.9995 21.1437C94.1097 21.1437 92.4964 20.5586 91.0675 19.3436C89.6848 18.1285 88.9473 16.3284 88.9473 13.9433ZM91.9894 13.9433C91.9894 15.6084 92.3121 16.7784 92.9113 17.5435C93.5566 18.3085 94.2019 18.8035 94.9855 18.9835C95.1698 19.0285 95.3081 19.0735 95.4925 19.0735C95.6308 19.0735 95.8151 19.1185 95.9534 19.1185C96.1378 19.1185 96.2761 19.1185 96.4604 19.0735C96.6448 19.0735 96.7831 19.0285 96.9675 18.9835C97.7049 18.8035 98.3963 18.3085 98.9955 17.5435C99.5948 16.7784 99.9174 15.5633 99.9174 13.9883C99.9174 12.3682 99.5948 11.1981 98.9955 10.4331C98.3963 9.66803 97.7049 9.173 96.9675 8.99299C96.7831 8.94799 96.5987 8.90299 96.4604 8.90299C96.2761 8.90299 96.1378 8.85798 95.9534 8.85798C95.769 8.85798 95.6308 8.85798 95.4925 8.90299C95.3542 8.90299 95.1698 8.94799 94.9855 8.99299C94.248 9.173 93.5566 9.66803 92.9113 10.4331C92.3121 11.1081 91.9894 12.3232 91.9894 13.9433Z" fill="white"/>
<path d="M104.988 6.92288H113.008V9.26301H107.891V12.6832H112.777V15.0683H107.891V20.9636H104.988V6.92288Z" fill="white"/>
<path d="M115.174 6.92288H123.195V9.26301H118.078V12.6832H122.964V15.0683H118.078V20.9636H115.174V6.92288Z" fill="white"/>
<path d="M124.9 20.9636V6.92288H127.804V20.9636H124.9Z" fill="white"/>
<path d="M140.599 7.2378V9.66793C140.092 9.48792 139.585 9.35291 139.032 9.26291C138.478 9.1729 137.833 9.1279 137.188 9.1279C135.667 9.1279 134.515 9.57792 133.685 10.523C132.855 11.423 132.44 12.5931 132.44 13.9882C132.44 15.3382 132.809 16.4633 133.593 17.3633C134.376 18.2634 135.482 18.7584 136.911 18.7584C137.418 18.7584 137.925 18.7134 138.525 18.6684C139.124 18.5784 139.723 18.4434 140.368 18.1734L140.553 20.5585C140.46 20.6035 140.322 20.6485 140.184 20.6935C140 20.7385 139.815 20.7835 139.585 20.8285C139.216 20.9185 138.755 20.9635 138.202 21.0535C137.649 21.0985 137.096 21.1436 136.497 21.1436C136.404 21.1436 136.312 21.1436 136.266 21.1436C136.174 21.1436 136.082 21.1436 136.036 21.1436C134.376 21.0535 132.855 20.4235 131.472 19.3435C130.09 18.2184 129.398 16.4633 129.398 14.1232C129.398 11.828 130.09 10.0279 131.426 8.76788C132.763 7.50781 134.607 6.87778 136.865 6.87778C137.464 6.87778 138.018 6.87778 138.478 6.92278C138.986 6.96778 139.446 7.05779 139.953 7.14779C140.046 7.19279 140.184 7.19279 140.276 7.2378C140.368 7.19279 140.46 7.2378 140.599 7.2378Z" fill="white"/>
<path d="M142.903 6.92294H151.523V9.12806H145.853V12.6383H150.97V14.7984H145.853V18.7586H151.523V20.9637H142.903V6.92294Z" fill="white"/>
</svg>

Before

Width:  |  Height:  |  Size: 5.5 KiB

After

Width:  |  Height:  |  Size: 5.5 KiB

View File

@ -0,0 +1,5 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<g opacity="0.3">
<path d="M10.3826 15.3872C9.9926 15.7862 9.35162 15.7889 8.95828 15.3933L6.15133 12.5701C5.76034 12.1768 5.12403 12.1768 4.73304 12.5701L4.70185 12.6015C4.31371 12.9918 4.31409 13.6225 4.7027 14.0124L8.95904 18.2831C9.35223 18.6776 9.99196 18.6749 10.3817 18.277L20.3062 8.14519C20.6903 7.75301 20.6865 7.12447 20.2976 6.73701L20.273 6.71257C19.8791 6.32014 19.2408 6.32437 18.8521 6.722L10.3826 15.3872Z" fill="#444444"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 549 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

View File

@ -1,6 +1,6 @@
/**
*
* (c) Copyright Ascensio System SIA 2020
* (c) Copyright Ascensio System SIA 2021
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -20,323 +20,416 @@
height: 100%;
width: 100%;
}
body {
background: #fff;
color: #333;
font-family: 'Open Sans', Tahoma,sans-serif;
background: #FFFFFF;
color: #333333;
font-family: Open Sans;
font-size: 12px;
font-style: normal;
font-weight: normal;
height: 100%;
margin: 0;
overflow-y: overlay;
padding: 0;
text-decoration: none;
}
form {
height: 100%;
}
div {
margin: 0;
padding: 0;
}
a, a:hover, a:visited {
color: #333;
a,
a:hover,
a:visited {
color: #333333;
cursor: pointer;
}
header {
background: #333333;
height: 72px;
margin: 0 auto;
min-width: 1152px;
width: auto;
}
.top-panel {
background: #3D4A6B;
height: 80px;
width: 100%;
header img {
margin: 22px 0 22px 32px;
}
.top-panel img {
margin: 12px 0 0 16px;
.center {
margin: 0 auto 0;
width: 1152px;
}
.main {
height: calc(100% - 136px);
min-height: 536px;
}
.table-main {
border-spacing: 0;
height: 100%;
min-height: 536px;
}
.section {
height: 100%;
padding: 0;
vertical-align: top;
}
.main-panel {
margin: 80px auto;
width: 600px;
box-sizing: border-box;
-moz-box-sizing: border-box;
height: 100%;
list-style: none;
padding: 48px 32px 24px;
position: relative;
width: 896px;
}
.portal-name {
font-size: 20px;
color: #FF6F3D;
font-size: 24px;
font-weight: bold;
line-height: 133%;
letter-spacing: -0.02em;
}
.portal-descr {
display: inline-block;
line-height: 20px;
margin-bottom: 24px;
width: 600px;
}
.save-original {
color: #929597;
line-height: 20px;
margin-left: 16px;
white-space: nowrap;
width: 272px;
}
label .checkbox {
vertical-align: middle;
}
.question {
background: url("images/question_small.png") no-repeat center center transparent;
cursor: pointer;
display: inline-block;
height: 16px;
width: 16px;
}
#hint {
background-color: #FFFFFF;
border: 1px solid #8E908F;
display: none;
margin: 4px 0 0 -32px;
max-width: 415px;
padding: 10px 15px 15px;
word-wrap: break-word;
z-index: 255;
}
.corner {
background: url("images/corner.png") no-repeat scroll 0 0 transparent;
height: 6px;
left: 35px;
margin-top: -15px;
position: absolute;
width: 9px;
z-index: 261;
}
.try-descr {
font-size: 16px;
white-space : nowrap;
line-height: 160%;
margin-top: 16px;
}
.header-list {
font-weight: bold;
font-size: 16px;
line-height: 133%;
letter-spacing: -0.02em;
}
label .checkbox {
margin: 0 5px 3px 0;
vertical-align: middle;
cursor: pointer;
}
.try-editor-list {
list-style: none;
margin: 0 0 16px;
padding: 0;
}
.try-editor-list li {
float: left;
margin: 0 15px;
width: 100px;
cursor: pointer;
}
.try-editor {
background-color: transparent;
background-position: center 0;
background-repeat: no-repeat;
display: block;
font-size: 14px;
font-weight: bold;
height: 45px;
padding-top: 100px;
text-align: center;
text-decoration: none;
}
.try-editor.word {
background-image: url("images/file_docx.png");
}
.try-editor.cell {
background-image: url("images/file_xlsx.png");
}
.try-editor.slide {
background-image: url("images/file_pptx.png");
}
.create-sample {
display: inline-block;
margin-left: 75px;
}
.button, .button:visited, .button:hover, .button:active {
display: inline-block;
font-weight: normal;
text-align: center;
text-decoration: none;
vertical-align: middle;
cursor:pointer;
border-radius: 3px;
-moz-border-radius: 3px;
-webkit-border-radius: 3px;
touch-callout: none;
-o-touch-callout: none;
-moz-touch-callout: none;
-webkit-touch-callout: none;
user-select: none;
-o-user-select: none;
-moz-user-select: none;
-webkit-user-select: none;
font-size: 12px;
line-height: 16px;
margin-right: 3px;
padding: 4px 12px;
color: #fff;
background: #3D96C6;
border-width: 1px;
border-style: solid;
border-color: #3D96C6;
}
.button.disable {
cursor: default;
background: #BADDEF;
border: 1px solid #BADDEF;
}
.button.gray {
background: #888;
border: 1px solid #E9EAEA;
}
.upload-panel {
border-right: 1px solid #D1D1D1;
float: left;
margin-right: 25px;
}
.file-upload {
background: url("images/file_upload.png") no-repeat center 0 transparent;
cursor: pointer;
display: inline-block;
font-size: 14px;
font-weight: bold;
height: 45px;
margin: 0 40px 16px;
overflow: hidden;
padding-top: 100px;
position: relative;
text-align: center;
width: 100px;
}
.file-upload input {
cursor: pointer;
opacity: 0;
position: absolute;
right: 0;
top: 0;
transform: translate(555px, 60px) scale(8);
}
.create-panel {
float: left;
}
.upload-panel,
.create-panel {
padding: 10px 0;
}
#mainProgress {
color: #979b9f;
display: none;
margin: 15px;
}
#mainProgress #embeddedView {
display: none;
}
#mainProgress.embedded #embeddedView {
display: block;
}
#mainProgress.embedded #uploadSteps {
display: none;
}
.error-message {
background: url("images/alert.png") no-repeat scroll 4px 10px #FFECE3;
color: #666668 !important;
display: none;
font-size: 13px;
font-weight: normal;
margin: 5px 0;
padding: 10px 10px 10px 30px;
vertical-align: middle;
}
#mainProgress .error-message a {
color: #666668;
}
.step {
background-repeat: no-repeat;
background-position: left center;
background-color: transparent;
color: #979B9F;
font-size: 14px;
line-height: 30px;
padding-left: 25px;
}
.current {
background-image: url("images/loader16.gif");
color: #333;
}
.done {
background-image: url("images/done.png");
color: #333;
}
.error {
background-image: url("images/alert.png");
}
.step-descr {
display: block;
margin-left: 45px;
}
#mainProgress .step-descr a {
color: #979B9F;
}
.progress-descr {
color: #333;
}
#loadScripts {
display: none;
}
#iframeScripts {
position: absolute;
visibility: hidden;
}
.bottom-panel {
bottom: 0;
position: fixed;
text-align: right;
width: 100%;
}
.help-block span {
font-size: 16px;
line-height: 26px;
}
.stored-list {
border-top: 1px solid #D1D1D1;
list-style: none;
margin: 0;
padding: 0;
}
.stored-list li {
border-bottom: 1px solid #D1D1D1;
line-height: 28px;
padding: 0 8px;
}
.try-editor-list li {
margin-bottom: 12px
}
.try-editor {
background-color: transparent;
background-repeat: no-repeat;
display: block;
font-size: 14px;
line-height: 40px;
padding-left: 42px;
text-decoration: none;
}
.try-editor.word {
background-image: url("images/file_docx.svg");
}
.try-editor.cell {
background-image: url("images/file_xlsx.svg");
}
.try-editor.slide {
background-image: url("images/file_pptx.svg");
}
.create-sample {
color: #666666;
line-height: 24px;
}
.button,
.button:visited,
.button:hover,
.button:active {
align-items: center;
border-radius: 3px;
box-sizing: border-box;
cursor: pointer;
display: inline-block;
font-weight: 600;
letter-spacing: 0.08em;
line-height: 133%;
padding: 8px 20px;
text-align: center;
text-decoration: none;
text-transform: uppercase;
vertical-align: middle;
user-select: none;
-o-touch-callout: none;
-moz-touch-callout: none;
-webkit-touch-callout: none;
-o-user-select: none;
-moz-user-select: none;
-webkit-user-select: none;
}
.button.orange {
background: #FF6F3D;
border: 1px solid #FF6F3D;
color: #FFFFFF;
}
.button.orange.disable {
background: #EDC2B3;
border: 1px solid #EDC2B3;
cursor: default;
}
.button.orange:not(.disable):hover {
background: #ff7a4b;
}
.button.gray {
border: 1px solid #AAAAAA;
margin-left: 8px;
}
.button.gray.disable {
border: 1px solid #E5E5E5;
color: #B5B5B5;
cursor: default;
}
.button.gray:not(.disable):hover {
border: 1px solid #FF6F3D;
color: #FF6F3D;
}
.upload-panel {
float: left;
padding: 24px 0;
}
.file-upload {
background: url("images/file_upload.svg") no-repeat 0 transparent;
cursor: pointer;
display: block;
font-size: 14px;
line-height: 40px;
overflow: hidden;
padding-left: 42px;
position: relative;
width: 150px;
}
.file-upload input {
cursor: pointer;
height: 40px;
margin: 0;
opacity: 0;
opacity: 0;
position: absolute;
right: 0;
top: 0;
transform: translate(0px, -21px) scale(2);
width: 192px;
}
.create-panel {
float: left;
padding: 16px 0;
}
.upload-panel,
.create-panel {
width: 100%;
border-bottom: 1px solid #D0D5DA;
}
#mainProgress {
color: #333333;
display: none;
font-size: 12px;
margin: 30px 40px;
}
#mainProgress .uploadFileName {
background-position: left center;
background-repeat: no-repeat;
display: block;
font-size: 14px;
line-height: 160%;
overflow: hidden;
padding-left: 28px;
text-overflow: ellipsis;
white-space: nowrap;
}
#mainProgress .describeUpload {
line-height: 150%;
letter-spacing: -0.02em;
padding: 16px 0;
}
#mainProgress #embeddedView {
display: none;
}
#mainProgress.embedded #embeddedView {
display: block;
}
#mainProgress.embedded #uploadSteps {
display: none;
}
.error-message {
background: url("images/error.svg") no-repeat scroll 4px 10px;
color: #CB0000;
display: none;
line-height: 160%;
letter-spacing: -0.02em;
margin: 5px 0;
padding: 10px 10px 10px 30px;
vertical-align: middle;
word-wrap: break-word;
}
.step {
background-repeat: no-repeat;
background-position: left center;
background-color: transparent;
font-weight: bold;
line-height: 167%;
padding-left: 35px;
}
.current {
background-image: url("images/loader16.gif");
}
.done {
background-image: url("images/done.svg");
}
.error {
background-image: url("images/notdone.svg");
}
.step-descr {
display: block;
margin-left: 35px;
font-size: 11px;
line-height: 188%;
}
.progress-descr {
letter-spacing: -0.02em;
line-height: 150%;
}
#loadScripts {
display: none;
}
#iframeScripts {
position: absolute;
visibility: hidden;
}
footer {
background: #333333;
color: #AAAAAA;
height: 64px;
min-width: 1152px;
width: auto;
}
footer table {
border-spacing: 0;
}
footer table tr {
height: 64px;
}
footer table td {
padding-left: 32px;
}
footer a,
footer a:hover,
footer a:visited {
color: #FF6F3D;
font-size: 14px;
line-height: 120%;
}
footer a:hover {
text-decoration: none;
}
.copy {
padding-left: 510px;
}
.help-block {
margin: 48px 32px 24px;
}
.help-block span {
font-size: 14px;
font-weight: 600;
line-height: 19px;
}
.stored-list {
list-style: none;
padding: 0;
position: relative;
height: 100%;
}
.stored-edit {
background-color: transparent;
background-position: left center;
background-repeat: no-repeat;
display: inline-block;
line-height: 16px;
max-width: 450px;
margin-bottom: -6px;
height: 16px;
max-width: 250px;
overflow: hidden;
padding: 4px 0 1px 34px;
padding: 8px 0 1px 26px;
text-decoration: none;
text-overflow: ellipsis;
white-space: nowrap;
}
.stored-edit.word {
background-image: url("images/icon_docx.png");
.stored-edit.word,
.uploadFileName.word {
background-image: url("images/icon_docx.svg");
}
.stored-edit.cell {
background-image: url("images/icon_xlsx.png");
.stored-edit.cell,
.uploadFileName.cell {
background-image: url("images/icon_xlsx.svg");
}
.stored-edit.slide {
background-image: url("images/icon_pptx.png");
.stored-edit.slide,
.uploadFileName.slide {
background-image: url("images/icon_pptx.svg");
}
.stored-edit span {
@ -348,28 +441,31 @@ label .checkbox {
text-decoration: underline;
}
.blockTitle {
background-color: #E2E2E2 !important;
background-color: #333333 !important;
border: none !important;
border-radius: 0 !important;
-moz-border-radius: 0 !important;
-webkit-border-radius: 0 !important;
color: #333 !important;
color: #F5F5F5 !important;
font-size: 16px !important;
font-weight: normal !important;
padding: 15px 25px !important;
font-weight: 600 !important;
line-height: 133%;
letter-spacing: -0.02em;
padding: 14px 16px 14px 46px !important;
}
.dialog-close {
background: url("images/close.png") no-repeat scroll left top #E2E2E2;
background: url("images/close.svg") no-repeat scroll left top;
cursor: pointer;
float: right;
font-size: 1px;
height: 12px;
height: 14px;
line-height: 1px;
margin-top: 4px;
width: 12px;
width: 14px;
}
.blockPage {
border: none !important;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.5);
@ -387,11 +483,6 @@ label .checkbox {
visibility: hidden;
}
/*Icon table*/
#tableRow {
vertical-align: top;
}
.tableRow {
background: transparent;
-moz-transition: all 0.2s ease-in-out;
@ -401,16 +492,17 @@ label .checkbox {
transition: all 0.2s ease-in-out;
}
.tableRow:hover {
background-color: #ebebeb;
}
.tableRow:hover {
background-color: #ECECEC;
}
.tableHeader {
padding-top: 10px;
}
.tableHeader tr {
background: transparent;
color: #333;
cursor: default;
font-family: 'Open Sans', sans-serif;
font-size: 13px;
height: 40px;
-khtml-user-select: none;
user-select: none;
@ -419,19 +511,39 @@ label .checkbox {
}
.tableHeaderCell {
padding: 2px 1px 2px 5px;
border-bottom: 1px solid #CCCCCC;
padding: 2px 4px;
text-align: center;
}
.tableHeaderCellFileName {
text-align: left;
width: 37%;
}
.tableHeaderCellEditors {
width: 29%;
}
.tableHeaderCellViewers {
width: 11%;
}
.tableHeaderCellDownload {
width: 13%;
text-align: right;
padding-right: 20px;
}
.tableHeaderCellRemove {
text-align: left;
}
.contentCells {
padding: 4px 1px 4px 5px;
border-bottom: 1px solid #EFEFEF;
font-family: 'Open Sans', sans-serif;
font-size: 16px;
border-bottom: 1px solid #e5e5e5;
padding: 4px;
white-space: nowrap;
-khtml-user-select: none;
user-select: none;
@ -439,59 +551,134 @@ label .checkbox {
-webkit-user-select: none;
}
.contentCells a {
text-decoration: none;
}
.contentCells-shift {
padding-right: 30px;
padding-right: 44px;
}
.contentCells-icon {
width: 6%;
}
.contentCellsSmall {
padding: 5px 1px 5px 6px;
font-family: 'Open Sans', sans-serif;
font-size: 13px;
border-bottom: 1px solid #e5e5e5;
white-space: nowrap;
text-align: center;
}
.primaryRow {
background-color: #e9e9e9;
}
.secondaryRow {
background-color: #F9F9F9;
width: 4%;
}
.select-user {
margin-left: 15px;
color: #444444;
font-family: Open Sans;
font-size: 12px !important;
font-weight: normal !important;
line-height: 16px !important;
}
.info {
cursor: pointer;
padding: 3px 5px;
position: absolute;
}
.tooltip {
background: #FFFFFF;
border-radius: 5px;
box-shadow: 0px 7px 25px rgba(85, 85, 85, 0.15);
color: #666666;
line-height: 160%;
max-width: 455px;
padding: 14px;
position: absolute;
}
.tooltip ul {
margin: 0;
}
.arrow {
border-top: 8px solid transparent;
border-bottom: 8px solid transparent;
border-right: 8px solid #FFFFFF;
position: absolute;
transform: translate(-50%, -50%);
}
.user-block-table {
height: 100%;
padding-top: 14px;
width: 100%;
}
.user-block-table td {
background-color: #F4F4F4;
border-bottom: 1px solid white;
padding: 12px 0;
}
#user, #language {
width: 130px;
.user-block-table td {
background-color: #F4F4F4;
padding-top: 10px;
}
.icon-download {
margin-bottom: -5px;
.user-block-table td select {
border: 1px solid #D0D5DA;
box-sizing: border-box;
border-radius: 3px;
cursor: pointer;
margin-top: 5px;
padding: 2px 5px;
width: 100%;
}
.icon-delete {
cursor: pointer;
margin-bottom: -6px;
}
}
.left-panel {
width: 256px;
background: #F5F5F5;
}
.scroll-table-body {
bottom: 0;
left: 0;
margin-top: 0px;
overflow-x: auto;
position: absolute;
right: 0;
top: 71px;
scrollbar-color: #D0D5DA transparent;
scrollbar-width: thin;
}
.scroll-table-body::-webkit-scrollbar {
width: 4px;
}
.scroll-table-body::-webkit-scrollbar-thumb {
background: #D0D5DA;
border-radius: 3px;
}
.descrFilePass {
display: block;
font-weight: bold;
line-height: 167%;
}
#filePass {
border: 1px solid #D0D5DA;
border-radius: 3px;
box-sizing: border-box;
display: inline-block;
height: 33px;
letter-spacing: -0.02em;
line-height: 150%;
margin-right: 8px;
outline: none;
padding: 7px 8px;
vertical-align: bottom;
user-select: none;
-moz-user-select: none;
-webkit-user-select: none;
width: 250px;
}
.errorInput {
border-color: #CB0000 !important;
}
.errorPass {
color: #CB0000;
display: block;
line-height: 160%;
letter-spacing: -0.02em;
word-wrap: break-word;
}

View File

@ -1,6 +1,6 @@
/**
*
* (c) Copyright Ascensio System SIA 2020
* (c) Copyright Ascensio System SIA 2021
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -30,22 +30,26 @@ namespace OnlineEditorsExampleMVC.Controllers
return View();
}
// viewing file in the editor
public ActionResult Editor(string fileName, string editorsMode, string editorsType)
{
var file = new FileModel
{
Mode = editorsMode,
Type = editorsType,
FileName = Path.GetFileName(fileName)
Mode = editorsMode, // editor mode: edit or view
Type = editorsType, // editor type: desktop, mobile, embedded
FileName = Path.GetFileName(fileName) // file name
};
return View("Editor", file);
}
// creating a sample document
public ActionResult Sample(string fileExt, bool? sample)
{
var fileName = DocManagerHelper.CreateDemo(fileExt, sample ?? false);
DocManagerHelper.CreateMeta(fileName, Request.Cookies.GetOrDefault("uid", ""), Request.Cookies.GetOrDefault("uname", ""));
var fileName = DocManagerHelper.CreateDemo(fileExt, sample ?? false); // create a sample document
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 }));
return null;
}

View File

@ -1,6 +1,6 @@
/**
*
* (c) Copyright Ascensio System SIA 2020
* (c) Copyright Ascensio System SIA 2021
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

View File

@ -1,6 +1,6 @@
/**
*
* (c) Copyright Ascensio System SIA 2020
* (c) Copyright Ascensio System SIA 2021
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -30,6 +30,7 @@ namespace OnlineEditorsExampleMVC.Helpers
{
public class DocManagerHelper
{
// get max file size
public static long MaxFileSize
{
get
@ -40,31 +41,37 @@ namespace OnlineEditorsExampleMVC.Helpers
}
}
// get all the supported file extensions
public static List<string> FileExts
{
get { return ViewedExts.Concat(EditedExts).Concat(ConvertExts).ToList(); }
}
// get file extensions that can be viewed
public static List<string> ViewedExts
{
get { return (WebConfigurationManager.AppSettings["files.docservice.viewed-docs"] ?? "").Split(new char[] { '|', ',' }, StringSplitOptions.RemoveEmptyEntries).ToList(); }
}
// get file extensions that can be edited
public static List<string> EditedExts
{
get { return (WebConfigurationManager.AppSettings["files.docservice.edited-docs"] ?? "").Split(new char[] { '|', ',' }, StringSplitOptions.RemoveEmptyEntries).ToList(); }
}
// get file extensions that can be converted
public static List<string> ConvertExts
{
get { return (WebConfigurationManager.AppSettings["files.docservice.convert-docs"] ?? "").Split(new char[] { '|', ',' }, StringSplitOptions.RemoveEmptyEntries).ToList(); }
}
// get current user host address
public static string CurUserHostAddress(string userAddress = null)
{
return Regex.Replace(userAddress ?? HttpContext.Current.Request.UserHostAddress, "[^0-9a-zA-Z.=]", "_");
}
// get the storage path of the file
public static string StoragePath(string fileName, string userAddress = null)
{
var directory = HttpRuntime.AppDomainAppPath + CurUserHostAddress(userAddress) + "\\";
@ -75,14 +82,17 @@ namespace OnlineEditorsExampleMVC.Helpers
return directory + Path.GetFileName(fileName);
}
// get the path to the forcesaved file version
public static string ForcesavePath(string fileName, string userAddress, Boolean create)
{
// create the directory to this file version
var directory = HttpRuntime.AppDomainAppPath + CurUserHostAddress(userAddress) + "\\";
if (!Directory.Exists(directory))
{
return "";
}
// create the directory to the history of this file version
directory = directory + Path.GetFileName(fileName) + "-hist" + "\\";
if (!Directory.Exists(directory))
{
@ -108,45 +118,52 @@ namespace OnlineEditorsExampleMVC.Helpers
return directory;
}
// get the history directory
public static string HistoryDir(string storagePath)
{
return storagePath += "-hist";
}
// get the path to the file version by the history path and file version
public static string VersionDir(string histPath, int version)
{
return Path.Combine(histPath, version.ToString());
}
// get the path to the file version by the file name, user address and file version
public static string VersionDir(string fileName, string userAddress, int version)
{
return VersionDir(HistoryDir(StoragePath(fileName, userAddress)), version);
}
// get the file version by the history path
public static int GetFileVersion(string historyPath)
{
if (!Directory.Exists(historyPath)) return 0;
return Directory.EnumerateDirectories(historyPath).Count() + 1;
if (!Directory.Exists(historyPath)) return 0; // if the history path doesn't exist, then the file version is 0
return Directory.EnumerateDirectories(historyPath).Count() + 1; // take only directories from the history folder and count them
}
// get the file version by the file name and user address
public static int GetFileVersion(string fileName, string userAddress)
{
return GetFileVersion(HistoryDir(StoragePath(fileName, userAddress)));
}
// get a file name with an index if the file with such a name already exists
public static string GetCorrectName(string fileName, string userAddress = null)
{
var baseName = Path.GetFileNameWithoutExtension(fileName);
var ext = Path.GetExtension(fileName);
var ext = Path.GetExtension(fileName).ToLower();
var name = baseName + ext;
for (var i = 1; File.Exists(StoragePath(name, userAddress)); i++)
for (var i = 1; File.Exists(StoragePath(name, userAddress)); i++) // run through all the files with such a name in the storage directory
{
name = baseName + " (" + i + ")" + ext;
name = baseName + " (" + i + ")" + ext; // and add an index to the base name
}
return name;
}
// get all the stored files from the user host address
public static List<FileInfo> GetStoredFiles()
{
var directory = HttpRuntime.AppDomainAppPath + WebConfigurationManager.AppSettings["storage-path"] + CurUserHostAddress(null) + "\\";
@ -154,34 +171,39 @@ namespace OnlineEditorsExampleMVC.Helpers
var directoryInfo = new DirectoryInfo(directory);
// take files from the root directory
List<FileInfo> storedFiles = directoryInfo.GetFiles("*.*", SearchOption.TopDirectoryOnly).ToList();
return storedFiles;
}
// create demo document
public static string CreateDemo(string fileExt, bool withContent)
{
var demoName = (withContent ? "sample." : "new.") + fileExt;
var demoPath = "assets\\" + (withContent ? "sample\\" : "new\\");
var demoName = (withContent ? "sample." : "new.") + fileExt; // create sample or new template file with the necessary extension
var demoPath = "assets\\" + (withContent ? "sample\\" : "new\\"); // get the path to the sample document
var fileName = GetCorrectName(demoName);
var fileName = GetCorrectName(demoName); // get a file name with an index if the file with such a name already exists
File.Copy(HttpRuntime.AppDomainAppPath + demoPath + demoName, StoragePath(fileName));
File.Copy(HttpRuntime.AppDomainAppPath + demoPath + demoName, StoragePath(fileName)); // copy file to the storage directory
return fileName;
}
// create meta information
public static void CreateMeta(string fileName, string uid, string uname, string userAddress = null)
{
var histDir = HistoryDir(StoragePath(fileName, userAddress));
var histDir = HistoryDir(StoragePath(fileName, userAddress)); // create history directory
Directory.CreateDirectory(histDir);
// create createdInfo.json file with meta information in the history directory (creation time, user id and name)
File.WriteAllText(Path.Combine(histDir, "createdInfo.json"), new JavaScriptSerializer().Serialize(new Dictionary<string, object> {
{ "created", DateTime.Now.ToString("yyyy'-'MM'-'dd HH':'mm':'ss") },
{ "id", string.IsNullOrEmpty(uid) ? "uid-1" : uid },
{ "name", string.IsNullOrEmpty(uname) ? "John Smith" : uname }
{ "id", uid },
{ "name", uname }
}));
}
// get file url
public static string GetFileUri(string fileName, Boolean forDocumentServer)
{
var uri = new UriBuilder(GetServerUrl(forDocumentServer))
@ -195,6 +217,7 @@ namespace OnlineEditorsExampleMVC.Helpers
return uri.ToString();
}
// get the path url
public static string GetPathUri(string path)
{
var uri = new UriBuilder(GetServerUrl(true))
@ -207,6 +230,7 @@ namespace OnlineEditorsExampleMVC.Helpers
return uri.ToString();
}
// get the server url
public static string GetServerUrl(Boolean forDocumentServer)
{
if (forDocumentServer && !WebConfigurationManager.AppSettings["files.docservice.url.example"].Equals(""))
@ -224,6 +248,7 @@ namespace OnlineEditorsExampleMVC.Helpers
}
}
// get the callback url
public static string GetCallback(string fileName)
{
var callbackUrl = new UriBuilder(GetServerUrl(true))
@ -239,27 +264,59 @@ namespace OnlineEditorsExampleMVC.Helpers
return callbackUrl.ToString();
}
public static string GetCreateUrl(FileUtility.FileType fileType)
{
var createUrl = new UriBuilder(GetServerUrl(false))
{
Path =
HttpRuntime.AppDomainAppVirtualPath
+ (HttpRuntime.AppDomainAppVirtualPath.EndsWith("/") ? "" : "/")
+ "Sample",
Query = "fileExt=" + DocManagerHelper.GetInternalExtension(fileType).Trim('.')
};
return createUrl.ToString();
}
public static string GetDownloadUrl(string fileName)
{
var downloadUrl = new UriBuilder(GetServerUrl(true))
{
Path =
HttpRuntime.AppDomainAppVirtualPath
+ (HttpRuntime.AppDomainAppVirtualPath.EndsWith("/") ? "" : "/")
+ "webeditor.ashx",
Query = "type=download"
+ "&fileName=" + HttpUtility.UrlEncode(fileName)
+ "&userAddress=" + HttpUtility.UrlEncode(HttpContext.Current.Request.UserHostAddress)
};
return downloadUrl.ToString();
}
// get an editor internal extension
public static string GetInternalExtension(FileUtility.FileType fileType)
{
switch (fileType)
{
case FileUtility.FileType.Word:
case FileUtility.FileType.Word: // .docx for word file type
return ".docx";
case FileUtility.FileType.Cell:
case FileUtility.FileType.Cell: // .xlsx for cell file type
return ".xlsx";
case FileUtility.FileType.Slide:
case FileUtility.FileType.Slide: // .pptx for slide file type
return ".pptx";
default:
return ".docx";
return ".docx"; // the default file type is .docx
}
}
// get file information
public static List<Dictionary<string, object>> GetFilesInfo(string fileId = null)
{
var files = new List<Dictionary<string, object>>();
// run through all the stored files
foreach (var file in GetStoredFiles())
{
// write all the parameters to the map
var dictionary = new Dictionary<string, object>();
dictionary.Add("version", GetFileVersion(file.Name, null));
dictionary.Add("id", ServiceConverter.GenerateRevisionId(DocManagerHelper.CurUserHostAddress() + "/" + file.Name + "/" + File.GetLastWriteTime(DocManagerHelper.StoragePath(file.Name, null)).GetHashCode()));
@ -268,6 +325,7 @@ namespace OnlineEditorsExampleMVC.Helpers
dictionary.Add("title", file.Name);
dictionary.Add("updated", file.LastWriteTime.ToString());
// get file information by its id
if (fileId != null)
{
if (fileId.Equals(dictionary["id"]))

View File

@ -1,6 +1,6 @@
/**
*
* (c) Copyright Ascensio System SIA 2020
* (c) Copyright Ascensio System SIA 2021
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -69,7 +69,7 @@ namespace OnlineEditorsExampleMVC.Helpers
/// <param name="documentRevisionId">Key for caching on service</param>
/// <param name="isAsync">Perform conversions asynchronously</param>
/// <param name="convertedDocumentUri">Uri to the converted document</param>
/// <returns>The percentage of completion of conversion</returns>
/// <returns>The percentage of conversion completion</returns>
/// <example>
/// string convertedDocumentUri;
/// GetConvertedUri("http://helpcenter.onlyoffice.com/content/GettingStarted.pdf", ".pdf", ".docx", "http://helpcenter.onlyoffice.com/content/GettingStarted.pdf", false, out convertedDocumentUri);
@ -81,44 +81,53 @@ namespace OnlineEditorsExampleMVC.Helpers
string toExtension,
string documentRevisionId,
bool isAsync,
out string convertedDocumentUri)
out string convertedDocumentUri,
string filePass = null)
{
convertedDocumentUri = string.Empty;
fromExtension = string.IsNullOrEmpty(fromExtension) ? Path.GetExtension(documentUri) : fromExtension;
// check if the fromExtension parameter is defined; if not, get it from the document url
fromExtension = string.IsNullOrEmpty(fromExtension) ? Path.GetExtension(documentUri).ToLower() : fromExtension;
// check if the file name parameter is defined; if not, get random uuid for this file
var title = Path.GetFileName(documentUri);
title = string.IsNullOrEmpty(title) ? Guid.NewGuid().ToString() : title;
// get document key
documentRevisionId = string.IsNullOrEmpty(documentRevisionId)
? documentUri
: documentRevisionId;
documentRevisionId = GenerateRevisionId(documentRevisionId);
// specify request parameters
var request = (HttpWebRequest)WebRequest.Create(DocumentConverterUrl);
request.Method = "POST";
request.ContentType = "application/json";
request.Accept = "application/json";
request.Timeout = ConvertTimeout;
// write all the necessary parameters to the body object
var body = new Dictionary<string, object>() {
{ "async", isAsync },
{ "filetype", fromExtension.Trim('.') },
{ "key", documentRevisionId },
{ "outputtype", toExtension.Trim('.') },
{ "title", title },
{ "url", documentUri }
{ "url", documentUri },
{ "password", filePass }
};
if (JwtManager.Enabled)
{
// create payload object
var payload = new Dictionary<string, object>
{
{ "payload", body }
};
var payloadToken = JwtManager.Encode(payload);
var bodyToken = JwtManager.Encode(body);
var payloadToken = JwtManager.Encode(payload); // encode the payload object to the payload token
var bodyToken = JwtManager.Encode(body); // encode the body object to the body token
// create header token
string JWTheader = WebConfigurationManager.AppSettings["files.docservice.header"].Equals("") ? "Authorization" : WebConfigurationManager.AppSettings["files.docservice.header"];
request.Headers.Add(JWTheader, "Bearer " + payloadToken);
@ -127,20 +136,20 @@ namespace OnlineEditorsExampleMVC.Helpers
var bytes = Encoding.UTF8.GetBytes(new JavaScriptSerializer().Serialize(body));
request.ContentLength = bytes.Length;
using (var requestStream = request.GetRequestStream())
using (var requestStream = request.GetRequestStream()) // get the request stream
{
requestStream.Write(bytes, 0, bytes.Length);
requestStream.Write(bytes, 0, bytes.Length); // and write the serialized body object to it
}
string dataResponse;
using (var response = request.GetResponse())
using (var stream = response.GetResponseStream())
using (var stream = response.GetResponseStream()) // get the response stream
{
if (stream == null) throw new Exception("Response is null");
using (var reader = new StreamReader(stream))
{
dataResponse = reader.ReadToEnd();
dataResponse = reader.ReadToEnd(); // and read it
}
}
@ -154,9 +163,10 @@ namespace OnlineEditorsExampleMVC.Helpers
/// <returns>Supported key</returns>
public static string GenerateRevisionId(string expectedKey)
{
// if the expected key length is greater than 20, it is hashed and a fixed length value is stored in the string format
if (expectedKey.Length > 20) expectedKey = expectedKey.GetHashCode().ToString();
var key = Regex.Replace(expectedKey, "[^0-9-.a-zA-Z_=]", "_");
return key.Substring(key.Length - Math.Min(key.Length, 20));
return key.Substring(key.Length - Math.Min(key.Length, 20)); // the resulting key length is 20 or less
}
#endregion
@ -168,7 +178,7 @@ namespace OnlineEditorsExampleMVC.Helpers
/// </summary>
/// <param name="jsonDocumentResponse">The resulting json from editing service</param>
/// <param name="responseUri">Uri to the converted document</param>
/// <returns>The percentage of completion of conversion</returns>
/// <returns>The percentage of conversion completion</returns>
private static int GetResponseUri(string jsonDocumentResponse, out string responseUri)
{
if (string.IsNullOrEmpty(jsonDocumentResponse)) throw new ArgumentException("Invalid param", "jsonDocumentResponse");
@ -176,21 +186,22 @@ namespace OnlineEditorsExampleMVC.Helpers
var responseFromService = Json.Decode(jsonDocumentResponse);
if (jsonDocumentResponse == null) throw new WebException("Invalid answer format");
var errorElement = responseFromService.error;
if (errorElement != null) ProcessResponseError(Convert.ToInt32(errorElement));
var errorElement = responseFromService.error; // if an error occurs
if (errorElement != null) ProcessResponseError(Convert.ToInt32(errorElement)); // then get an error message
// check if the conversion is completed and save the result to a variable
var isEndConvert = responseFromService.endConvert;
int resultPercent;
responseUri = string.Empty;
if (isEndConvert)
if (isEndConvert) // if the conversion is completed
{
responseUri = responseFromService.fileUrl;
responseUri = responseFromService.fileUrl; // get the file url
resultPercent = 100;
}
else
else // if the conversion isn't completed
{
resultPercent = responseFromService.percent;
resultPercent = responseFromService.percent; // get the percentage value
if (resultPercent >= 100) resultPercent = 99;
}
@ -222,7 +233,7 @@ namespace OnlineEditorsExampleMVC.Helpers
break;
case -5:
// public const int c_nErrorUnexpectedGuid = -5;
errorMessage = String.Format(errorMessageTemplate, "Error unexpected guid");
errorMessage = String.Format(errorMessageTemplate, "Incorrect password");
break;
case -4:
// public const int c_nErrorDownloadError = -4;

View File

@ -1,6 +1,6 @@
/**
*
* (c) Copyright Ascensio System SIA 2020
* (c) Copyright Ascensio System SIA 2021
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -34,26 +34,30 @@ namespace OnlineEditorsExampleMVC.Helpers
static JwtManager()
{
Secret = WebConfigurationManager.AppSettings["files.docservice.secret"] ?? "";
Enabled = !string.IsNullOrEmpty(Secret);
Serializer = new JavaScriptSerializer();
Secret = WebConfigurationManager.AppSettings["files.docservice.secret"] ?? ""; // get token secret from the config parameters
Enabled = !string.IsNullOrEmpty(Secret); // check if the token is enabled
Serializer = new JavaScriptSerializer(); // define java script serializer
}
// encode a payload object into a token using a secret key
public static string Encode(IDictionary<string, object> payload)
{
// define the hashing algorithm and the token type
var header = new Dictionary<string, object>
{
{ "alg", "HS256" },
{ "typ", "JWT" }
};
var encHeader = Base64UrlEncode(Serializer.Serialize(header));
var encPayload = Base64UrlEncode(Serializer.Serialize(payload));
var hashSum = Base64UrlEncode(CalculateHash(encHeader, encPayload));
// three parts of token
var encHeader = Base64UrlEncode(Serializer.Serialize(header)); // header
var encPayload = Base64UrlEncode(Serializer.Serialize(payload)); // payload
var hashSum = Base64UrlEncode(CalculateHash(encHeader, encPayload)); // signature
return string.Format("{0}.{1}.{2}", encHeader, encPayload, hashSum);
}
// decode a token into a payload object using a secret key
public static string Decode(string token)
{
if (!Enabled || string.IsNullOrEmpty(token)) return "";
@ -61,11 +65,12 @@ namespace OnlineEditorsExampleMVC.Helpers
var split = token.Split('.');
if (split.Length != 3) return "";
var hashSum = Base64UrlEncode(CalculateHash(split[0], split[1]));
if (hashSum != split[2]) return "";
return Base64UrlDecode(split[1]);
var hashSum = Base64UrlEncode(CalculateHash(split[0], split[1])); // get signature
if (hashSum != split[2]) return ""; // and check if it is equal to the signature from the token
return Base64UrlDecode(split[1]); // decode payload
}
// generate a hash code based on a key using the HMAC method
private static byte[] CalculateHash(string encHeader, string encPayload)
{
using (var hasher = new HMACSHA256(Encoding.UTF8.GetBytes(Secret)))
@ -75,17 +80,20 @@ namespace OnlineEditorsExampleMVC.Helpers
}
}
// encode a string into the base64 value
private static string Base64UrlEncode(string str)
{
return Base64UrlEncode(Encoding.UTF8.GetBytes(str));
}
// encode bytes into the base64 value
private static string Base64UrlEncode(byte[] bytes)
{
return Convert.ToBase64String(bytes)
.TrimEnd('=').Replace('+', '-').Replace('/', '_');
}
// decode a base64 value into the string
private static string Base64UrlDecode(string payload)
{
var b64 = payload.Replace('_', '/').Replace('-', '+');

View File

@ -1,6 +1,6 @@
/**
*
* (c) Copyright Ascensio System SIA 2020
* (c) Copyright Ascensio System SIA 2021
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -30,11 +30,13 @@ namespace OnlineEditorsExampleMVC.Helpers
{
public class TrackManager
{
// read request body
public static Dictionary<string, object> readBody(HttpContext context)
{
string body;
try
{
// read request body by streams and check if it is correct
using (var receiveStream = context.Request.InputStream)
using (var readStream = new StreamReader(receiveStream))
{
@ -50,27 +52,29 @@ namespace OnlineEditorsExampleMVC.Helpers
var jss = new JavaScriptSerializer();
var fileData = jss.Deserialize<Dictionary<string, object>>(body);
// check if the document token is enabled
if (JwtManager.Enabled)
{
string JWTheader = WebConfigurationManager.AppSettings["files.docservice.header"].Equals("") ? "Authorization" : WebConfigurationManager.AppSettings["files.docservice.header"];
string token = null;
// if the document token is in the data
if (fileData.ContainsKey("token"))
{
token = JwtManager.Decode(fileData["token"].ToString());
token = JwtManager.Decode(fileData["token"].ToString()); // decode it
}
else if (context.Request.Headers.AllKeys.Contains(JWTheader, StringComparer.InvariantCultureIgnoreCase))
else if (context.Request.Headers.AllKeys.Contains(JWTheader, StringComparer.InvariantCultureIgnoreCase)) // if the Authorization header exists
{
var headerToken = context.Request.Headers.Get(JWTheader).Substring("Bearer ".Length);
token = JwtManager.Decode(headerToken);
token = JwtManager.Decode(headerToken); // decode its part after Authorization prefix
}
else
else // otherwise, an error occurs
{
context.Response.Write("{\"error\":1,\"message\":\"JWT expected\"}");
}
if (token != null && !token.Equals(""))
if (token != null && !token.Equals("")) // invalid signature error
{
fileData = (Dictionary<string, object>)jss.Deserialize<Dictionary<string, object>>(token)["payload"];
}
@ -83,21 +87,25 @@ namespace OnlineEditorsExampleMVC.Helpers
return fileData;
}
// file saving process
public static int processSave(Dictionary<string, object> fileData, string fileName, string userAddress)
{
var downloadUri = (string)fileData["url"];
string curExt = Path.GetExtension(fileName);
string downloadExt = Path.GetExtension(downloadUri) ?? "";
string curExt = Path.GetExtension(fileName).ToLower(); // get current file extension
string downloadExt = Path.GetExtension(downloadUri).ToLower() ?? ""; // get the extension of the downloaded file
var newFileName = fileName;
// convert downloaded file to the file with the current extension if these extensions aren't equal
if (!curExt.Equals(downloadExt, StringComparison.InvariantCultureIgnoreCase))
{
try
{
// convert file and give url to a new file
string newFileUri;
var result = ServiceConverter.GetConvertedUri(downloadUri, downloadExt, curExt, ServiceConverter.GenerateRevisionId(downloadUri), false, out newFileUri);
if (string.IsNullOrEmpty(newFileUri))
{
// get the correct file name if it already exists
newFileName = DocManagerHelper.GetCorrectName(Path.GetFileNameWithoutExtension(fileName) + downloadExt, userAddress);
}
else
@ -111,17 +119,18 @@ namespace OnlineEditorsExampleMVC.Helpers
}
}
var storagePath = DocManagerHelper.StoragePath(newFileName, userAddress);
var histDir = DocManagerHelper.HistoryDir(storagePath);
var storagePath = DocManagerHelper.StoragePath(newFileName, userAddress); // get the file path
var histDir = DocManagerHelper.HistoryDir(storagePath); // get the path to the history directory
if (!Directory.Exists(histDir)) Directory.CreateDirectory(histDir);
var versionDir = DocManagerHelper.VersionDir(histDir, DocManagerHelper.GetFileVersion(histDir));
if (!Directory.Exists(versionDir)) Directory.CreateDirectory(versionDir);
var versionDir = DocManagerHelper.VersionDir(histDir, DocManagerHelper.GetFileVersion(histDir)); // get the path to the file version
if (!Directory.Exists(versionDir)) Directory.CreateDirectory(versionDir); // if the path doesn't exist, create it
// get the path to the previous file version and move it to the storage directory
File.Move(DocManagerHelper.StoragePath(fileName, userAddress), Path.Combine(versionDir, "prev" + curExt));
DownloadToFile(downloadUri, storagePath);
DownloadToFile((string)fileData["changesurl"], Path.Combine(versionDir, "diff.zip"));
DownloadToFile(downloadUri, storagePath); // save file to the storage directory
DownloadToFile((string)fileData["changesurl"], Path.Combine(versionDir, "diff.zip")); // save file changes to the diff.zip archive
var hist = fileData.ContainsKey("changeshistory") ? (string)fileData["changeshistory"] : null;
if (string.IsNullOrEmpty(hist) && fileData.ContainsKey("history"))
@ -132,37 +141,40 @@ namespace OnlineEditorsExampleMVC.Helpers
if (!string.IsNullOrEmpty(hist))
{
File.WriteAllText(Path.Combine(versionDir, "changes.json"), hist);
File.WriteAllText(Path.Combine(versionDir, "changes.json"), hist); // write the history changes to the changes.json file
}
File.WriteAllText(Path.Combine(versionDir, "key.txt"), (string)fileData["key"]);
File.WriteAllText(Path.Combine(versionDir, "key.txt"), (string)fileData["key"]); // write the key value to the key.txt file
string forcesavePath = DocManagerHelper.ForcesavePath(newFileName, userAddress, false);
if (!forcesavePath.Equals(""))
string forcesavePath = DocManagerHelper.ForcesavePath(newFileName, userAddress, false); // get the path to the forcesaved file version
if (!forcesavePath.Equals("")) // if the forcesaved file version exists
{
File.Delete(forcesavePath);
File.Delete(forcesavePath); // remove it
}
return 0;
}
// file force saving process
public static int processForceSave(Dictionary<string, object> fileData, string fileName, string userAddress)
{
var downloadUri = (string)fileData["url"];
string curExt = Path.GetExtension(fileName);
string downloadExt = Path.GetExtension(downloadUri);
var newFileName = fileName;
string curExt = Path.GetExtension(fileName).ToLower(); // get current file extension
string downloadExt = Path.GetExtension(downloadUri).ToLower(); // get the extension of the downloaded file
Boolean newFileName = false;
// convert downloaded file to the file with the current extension if these extensions aren't equal
if (!curExt.Equals(downloadExt))
{
try
{
// convert file and give url to a new file
string newFileUri;
var result = ServiceConverter.GetConvertedUri(downloadUri, downloadExt, curExt, ServiceConverter.GenerateRevisionId(downloadUri), false, out newFileUri);
if (string.IsNullOrEmpty(newFileUri))
{
newFileName = DocManagerHelper.GetCorrectName(Path.GetFileNameWithoutExtension(fileName) + downloadExt, userAddress);
newFileName = true;
}
else
{
@ -171,27 +183,34 @@ namespace OnlineEditorsExampleMVC.Helpers
}
catch (Exception)
{
newFileName = DocManagerHelper.GetCorrectName(Path.GetFileNameWithoutExtension(fileName) + downloadExt, userAddress);
newFileName = true;
}
}
string forcesavePath = "";
Boolean isSubmitForm = fileData["forcesavetype"].ToString().Equals("3");
Boolean isSubmitForm = fileData["forcesavetype"].ToString().Equals("3"); // SubmitForm
if (isSubmitForm)
if (isSubmitForm) // if the form is submitted
{
if (newFileName.Equals(fileName))
if (newFileName)
{
newFileName = DocManagerHelper.GetCorrectName(fileName, userAddress);
fileName = DocManagerHelper.GetCorrectName(Path.GetFileNameWithoutExtension(fileName) + "-form" + downloadExt, userAddress); // get the correct file name if it already exists
} else
{
fileName = DocManagerHelper.GetCorrectName(Path.GetFileNameWithoutExtension(fileName) + "-form" + curExt, userAddress);
}
forcesavePath = DocManagerHelper.StoragePath(newFileName, userAddress);
forcesavePath = DocManagerHelper.StoragePath(fileName, userAddress);
}
else
{
forcesavePath = DocManagerHelper.ForcesavePath(newFileName, userAddress, false);
if (forcesavePath.Equals(""))
if (newFileName)
{
forcesavePath = DocManagerHelper.ForcesavePath(newFileName, userAddress, true);
fileName = DocManagerHelper.GetCorrectName(Path.GetFileNameWithoutExtension(fileName) + downloadExt, userAddress);
}
forcesavePath = DocManagerHelper.ForcesavePath(fileName, userAddress, false);
if (forcesavePath.Equals("")) // create forcesave path if it doesn't exist
{
forcesavePath = DocManagerHelper.ForcesavePath(fileName, userAddress, true);
}
}
@ -202,13 +221,14 @@ namespace OnlineEditorsExampleMVC.Helpers
var jss = new JavaScriptSerializer();
var actions = jss.Deserialize<List<object>>(jss.Serialize(fileData["actions"]));
var action = jss.Deserialize<Dictionary<string, object>>(jss.Serialize(actions[0]));
var user = action["userid"].ToString();
DocManagerHelper.CreateMeta(newFileName, user, "Filling Form", userAddress);
var user = action["userid"].ToString(); // get the user id
DocManagerHelper.CreateMeta(fileName, user, "Filling Form", userAddress); // create meta data for the forcesaved file
}
return 0;
}
// create a command request
public static void commandRequest(string method, string key)
{
string documentCommandUrl = WebConfigurationManager.AppSettings["files.docservice.url.site"] + WebConfigurationManager.AppSettings["files.docservice.url.command"];
@ -222,6 +242,7 @@ namespace OnlineEditorsExampleMVC.Helpers
{ "key", key }
};
// check if a secret key to generate token exists or not
if (JwtManager.Enabled)
{
var payload = new Dictionary<string, object>
@ -229,10 +250,10 @@ namespace OnlineEditorsExampleMVC.Helpers
{ "payload", body }
};
var payloadToken = JwtManager.Encode(payload);
var bodyToken = JwtManager.Encode(body);
var payloadToken = JwtManager.Encode(payload); // encode a payload object into a header token
var bodyToken = JwtManager.Encode(body); // encode body into a body token
string JWTheader = WebConfigurationManager.AppSettings["files.docservice.header"].Equals("") ? "Authorization" : WebConfigurationManager.AppSettings["files.docservice.header"];
request.Headers.Add(JWTheader, "Bearer " + payloadToken);
request.Headers.Add(JWTheader, "Bearer " + payloadToken); // add a header Authorization with a header token and Authorization prefix in it
body.Add("token", bodyToken);
}
@ -241,21 +262,23 @@ namespace OnlineEditorsExampleMVC.Helpers
request.ContentLength = bytes.Length;
using (var requestStream = request.GetRequestStream())
{
// write bytes to the output stream
requestStream.Write(bytes, 0, bytes.Length);
}
string dataResponse;
using (var response = request.GetResponse())
using (var response = request.GetResponse()) // get the response
using (var stream = response.GetResponseStream())
{
if (stream == null) throw new Exception("Response is null");
using (var reader = new StreamReader(stream))
{
dataResponse = reader.ReadToEnd();
dataResponse = reader.ReadToEnd(); // and read it
}
}
// convert stream to json string
var jss = new JavaScriptSerializer();
var responseObj = jss.Deserialize<Dictionary<string, object>>(dataResponse);
if (!responseObj["error"].ToString().Equals("0"))
@ -264,13 +287,14 @@ namespace OnlineEditorsExampleMVC.Helpers
}
}
// save file information from the url to the file specified
private static void DownloadToFile(string url, string path)
{
if (string.IsNullOrEmpty(url)) throw new ArgumentException("url");
if (string.IsNullOrEmpty(path)) throw new ArgumentException("path");
if (string.IsNullOrEmpty(url)) throw new ArgumentException("url"); // url isn't specified
if (string.IsNullOrEmpty(path)) throw new ArgumentException("path"); // file isn't specified
var req = (HttpWebRequest)WebRequest.Create(url);
using (var stream = req.GetResponse().GetResponseStream())
using (var stream = req.GetResponse().GetResponseStream()) // get input stream of the file information from the url
{
if (stream == null) throw new Exception("stream is null");
const int bufferSize = 4096;
@ -281,7 +305,7 @@ namespace OnlineEditorsExampleMVC.Helpers
int readed;
while ((readed = stream.Read(buffer, 0, bufferSize)) != 0)
{
fs.Write(buffer, 0, readed);
fs.Write(buffer, 0, readed); // write bytes to the output stream
}
}
}

View File

@ -0,0 +1,104 @@
/**
*
* (c) Copyright Ascensio System SIA 2021
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
using System.Collections.Generic;
namespace OnlineEditorsExampleMVC.Helpers
{
public class Users
{
static List<string> descr_user_1 = new List<string>()
{
"File author by default",
"He doesnt belong to any of the groups",
"He can review all the changes",
"The file favorite state is undefined"
};
static List<string> descr_user_2 = new List<string>()
{
"He belongs to Group2",
"He can review only his own changes or the changes made by the users who dont belong to any of the groups",
"This file is favorite"
};
static List<string> descr_user_3 = new List<string>()
{
"He belongs to Group3",
"He can review only the changes made by the users from Group2",
"This file isnt favorite",
"He cant copy data from the file into the clipboard",
"He cant download the file",
"He cant print the file"
};
static List<string> descr_user_0 = new List<string>()
{
"The user without a name. The name is requested upon the editor opening",
"He doesnt belong to any of the groups",
"He can review all the changes",
"The file favorite state is undefined"
};
private static List<User> users = new List<User>() {
new User("uid-1", "John Smith", "smith@mail.ru", null, null, null, new List<string>(), descr_user_1),
new User("uid-2", "Mark Pottato", "pottato@mail.ru", "group-2", new List<string>() { "group-2", "" }, true, new List<string>(), descr_user_2),
new User("uid-3", "Hamish Mitchell", "mitchell@mail.ru", "group-3", new List<string>() { "group-2" }, false, new List<string>() { "copy", "download", "print" }, descr_user_3),
new User("uid-0", null, null, null, null, null, new List<string>(), descr_user_0)
};
public static User getUser(string id)
{
foreach(User user in users)
{
if (user.id.Equals(id)) return user;
}
return users[0];
}
public static List<User> getAllUsers()
{
return users;
}
}
public class User
{
public string id;
public string name;
public string email;
public string group;
public List<string> reviewGroups;
public bool? favorite;
public List<string> deniedPermissions;
public List<string> descriptions;
public User(string id, string name, string email, string group, List<string> reviewGroups, bool? favorite, List<string> deniedPermissions, List<string> descriptions)
{
this.id = id;
this.name = name;
this.email = email;
this.group = group;
this.reviewGroups = reviewGroups;
this.favorite = favorite;
this.deniedPermissions = deniedPermissions;
this.descriptions = descriptions;
}
}
}

View File

@ -4,6 +4,7 @@ namespace OnlineEditorsExampleMVC.Helpers
{
public static class Utils
{
// get the request header or return the default one
public static string GetOrDefault(this HttpRequest request, string header, string def)
{
var value = request[header];
@ -11,6 +12,7 @@ namespace OnlineEditorsExampleMVC.Helpers
return def;
}
// get a cookie from the cookie collection or return the default one
public static string GetOrDefault(this HttpCookieCollection cookies, string cookie, string def)
{
var cook = cookies[cookie];

View File

@ -1,6 +1,6 @@
/**
*
* (c) Copyright Ascensio System SIA 2020
* (c) Copyright Ascensio System SIA 2021
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -27,73 +27,76 @@ using OnlineEditorsExampleMVC.Helpers;
namespace OnlineEditorsExampleMVC.Models
{
// create file model
public class FileModel
{
public string Mode { get; set; }
public string Type { get; set; }
public string Mode { get; set; } // editor mode
public string Type { get; set; } // editor type
// get file url for Document Server
public string FileUri
{
get { return DocManagerHelper.GetFileUri(FileName, true); }
}
// get file url for user
public string FileUriUser
{
get { return DocManagerHelper.GetFileUri(FileName, false); }
}
public string FileName { get; set; }
public string FileName { get; set; } // file name
// get document type
public string DocumentType
{
get { return FileUtility.GetFileType(FileName).ToString().ToLower(); }
}
// get document key
public string Key
{
get { return ServiceConverter.GenerateRevisionId(DocManagerHelper.CurUserHostAddress() + "/" + FileName + "/" + File.GetLastWriteTime(DocManagerHelper.StoragePath(FileName, null)).GetHashCode()); }
}
// get the callback url
public string CallbackUrl
{
get { return DocManagerHelper.GetCallback(FileName); }
}
public string CreateUrl
{
get { return DocManagerHelper.GetCreateUrl(FileUtility.GetFileType(FileName)); }
}
public string DownloadUrl
{
get { return DocManagerHelper.GetDownloadUrl(FileName); }
}
// get the document config
public string GetDocConfig(HttpRequest request, UrlHelper url)
{
var jss = new JavaScriptSerializer();
var ext = Path.GetExtension(FileName);
var editorsMode = Mode ?? "edit";
var ext = Path.GetExtension(FileName).ToLower(); // get file extension
var editorsMode = Mode ?? "edit"; // get editor mode
var canEdit = DocManagerHelper.EditedExts.Contains(ext);
var mode = canEdit && editorsMode != "view" ? "edit" : "view";
var submitForm = canEdit && (editorsMode.Equals("edit") || editorsMode.Equals("fillForms"));
var canEdit = DocManagerHelper.EditedExts.Contains(ext); // check if the file with such an extension can be edited
var mode = canEdit && editorsMode != "view" ? "edit" : "view"; // set the mode parameter: change it to view if the document can't be edited
var submitForm = canEdit && (editorsMode.Equals("edit") || editorsMode.Equals("fillForms")); // check if the Submit form button is displayed or not
var userId = request.Cookies.GetOrDefault("uid", "uid-1");
var uname = userId.Equals("uid-0") ? null : request.Cookies.GetOrDefault("uname", "John Smith");
string userGroup = null;
List<string> reviewGroups = null;
if (userId.Equals("uid-2"))
{
userGroup = "group-2";
reviewGroups = new List<string>() { "group-2", "" };
}
if (userId.Equals("uid-3"))
{
userGroup = "group-3";
reviewGroups = new List<string>() { "group-2" };
}
var id = request.Cookies.GetOrDefault("uid", null);
var user = Users.getUser(id); // get the user
object favorite = null;
if (!string.IsNullOrEmpty(request.Cookies.GetOrDefault("uid", null)))
{
favorite = request.Cookies.GetOrDefault("uid", null).Equals("uid-2");
}
// favorite icon state
bool? favorite = user.favorite;
var actionLink = request.GetOrDefault("actionLink", null);
var actionData = string.IsNullOrEmpty(actionLink) ? null : jss.DeserializeObject(actionLink);
var actionLink = request.GetOrDefault("actionLink", null); // get the action link (comment or bookmark) if it exists
var actionData = string.IsNullOrEmpty(actionLink) ? null : jss.DeserializeObject(actionLink); // get action data for the action link
// specify the document config
var config = new Dictionary<string, object>
{
{ "type", Type ?? "desktop" },
@ -102,7 +105,7 @@ namespace OnlineEditorsExampleMVC.Models
"document", new Dictionary<string, object>
{
{ "title", FileName },
{ "url", FileUri },
{ "url", DownloadUrl },
{ "fileType", ext.Trim('.') },
{ "key", Key },
{
@ -114,16 +117,19 @@ namespace OnlineEditorsExampleMVC.Models
}
},
{
// the permission for the document to be edited and downloaded or not
"permissions", new Dictionary<string, object>
{
{ "comment", editorsMode != "view" && editorsMode != "fillForms" && editorsMode != "embedded" && editorsMode != "blockcontent" },
{ "download", true },
{ "edit", canEdit && (editorsMode == "edit" || editorsMode == "filter") || editorsMode == "blockcontent" },
{ "copy", !user.deniedPermissions.Contains("copy") },
{ "download", !user.deniedPermissions.Contains("download") },
{ "edit", canEdit && (editorsMode == "edit" || editorsMode == "view" || editorsMode == "filter" || editorsMode == "blockcontent") },
{ "print", !user.deniedPermissions.Contains("print") },
{ "fillForms", editorsMode != "view" && editorsMode != "comment" && editorsMode != "embedded" && editorsMode != "blockcontent" },
{ "modifyFilter", editorsMode != "filter" },
{ "modifyContentControl", editorsMode != "blockcontent" },
{ "review", editorsMode == "edit" || editorsMode == "review" },
{ "reviewGroups", reviewGroups }
{ "review", canEdit && (editorsMode == "edit" || editorsMode == "review") },
{ "reviewGroups", user.reviewGroups }
}
}
}
@ -134,35 +140,39 @@ namespace OnlineEditorsExampleMVC.Models
{ "actionLink", actionData },
{ "mode", mode },
{ "lang", request.Cookies.GetOrDefault("ulang", "en") },
{ "callbackUrl", CallbackUrl },
{ "callbackUrl", CallbackUrl }, // absolute URL to the document storage service
{ "createUrl", CreateUrl },
{
// the user currently viewing or editing the document
"user", new Dictionary<string, object>
{
{ "id", userId },
{ "name", uname },
{ "group", userGroup }
{ "id", user.id },
{ "name", user.name },
{ "group", user.group }
}
},
{
// the parameters for the embedded document type
"embedded", new Dictionary<string, object>
{
{ "saveUrl", FileUriUser },
{ "embedUrl", FileUriUser },
{ "shareUrl", FileUriUser },
{ "toolbarDocked", "top" }
{ "saveUrl", FileUriUser }, // the absolute URL that will allow the document to be saved onto the user personal computer
{ "embedUrl", FileUriUser }, // the absolute URL to the document serving as a source file for the document embedded into the web page
{ "shareUrl", FileUriUser }, // the absolute URL that will allow other users to share this document
{ "toolbarDocked", "top" } // the place for the embedded viewer toolbar (top or bottom)
}
},
{
// the parameters for the editor interface
"customization", new Dictionary<string, object>
{
{ "about", true },
{ "feedback", true },
{ "forcesave", false },
{ "submitForm", submitForm },
{ "about", true }, // the About section display
{ "feedback", true }, // the Feedback & Support menu button display
{ "forcesave", false }, // adds the request for the forced file saving to the callback handler
{ "submitForm", submitForm }, // if the Submit form button is displayed or not
{
"goback", new Dictionary<string, object>
"goback", new Dictionary<string, object> // settings for the Open file location menu button and upper right corner button
{
{ "url", url.Action("Index", "Home") }
{ "url", url.Action("Index", "Home") } // the absolute URL to the website address which will be opened when clicking the Open file location menu button
}
}
}
@ -171,8 +181,10 @@ namespace OnlineEditorsExampleMVC.Models
}
};
// if the secret key to generate token exists
if (JwtManager.Enabled)
{
// encode the document config into a token
var token = JwtManager.Encode(config);
config.Add("token", token);
}
@ -180,6 +192,7 @@ namespace OnlineEditorsExampleMVC.Models
return jss.Serialize(config);
}
// get the document history
public void GetHistory(out string history, out string historyData)
{
var jss = new JavaScriptSerializer();
@ -188,31 +201,31 @@ namespace OnlineEditorsExampleMVC.Models
history = null;
historyData = null;
if (DocManagerHelper.GetFileVersion(histDir) > 0)
if (DocManagerHelper.GetFileVersion(histDir) > 0) // if the file was modified (the file version is greater than 0)
{
var currentVersion = DocManagerHelper.GetFileVersion(histDir);
var hist = new List<Dictionary<string, object>>();
var histData = new Dictionary<string, object>();
for (var i = 1; i <= currentVersion; i++)
for (var i = 1; i <= currentVersion; i++) // run through all the file versions
{
var obj = new Dictionary<string, object>();
var dataObj = new Dictionary<string, object>();
var verDir = DocManagerHelper.VersionDir(histDir, i);
var verDir = DocManagerHelper.VersionDir(histDir, i); // get the path to the given file version
var key = i == currentVersion ? Key : File.ReadAllText(Path.Combine(verDir, "key.txt"));
var key = i == currentVersion ? Key : File.ReadAllText(Path.Combine(verDir, "key.txt")); // get document key
obj.Add("key", key);
obj.Add("version", i);
if (i == 1)
if (i == 1) // check if the version number is equal to 1
{
var infoPath = Path.Combine(histDir, "createdInfo.json");
var infoPath = Path.Combine(histDir, "createdInfo.json"); // get meta data of this file
if (File.Exists(infoPath))
{
var info = jss.Deserialize<Dictionary<string, object>>(File.ReadAllText(infoPath));
obj.Add("created", info["created"]);
obj.Add("created", info["created"]); // write meta information to the object (user information and creation date)
obj.Add("user", new Dictionary<string, object>() {
{ "id", info["id"] },
{ "name", info["name"] },
@ -221,23 +234,27 @@ namespace OnlineEditorsExampleMVC.Models
}
dataObj.Add("key", key);
// write file url to the data object
dataObj.Add("url", i == currentVersion ? FileUri : DocManagerHelper.GetPathUri(Directory.GetFiles(verDir, "prev.*")[0].Substring(HttpRuntime.AppDomainAppPath.Length)));
dataObj.Add("version", i);
if (i > 1)
if (i > 1) // check if the version number is greater than 1 (the file was modified)
{
// get the path to the changes.json file
var changes = jss.Deserialize<Dictionary<string, object>>(File.ReadAllText(Path.Combine(DocManagerHelper.VersionDir(histDir, i - 1), "changes.json")));
var change = ((Dictionary<string, object>)((ArrayList)changes["changes"])[0]);
// write information about changes to the object
obj.Add("changes", changes["changes"]);
obj.Add("serverVersion", changes["serverVersion"]);
obj.Add("created", change["created"]);
obj.Add("user", change["user"]);
var prev = (Dictionary<string, object>)histData[(i - 2).ToString()];
dataObj.Add("previous", new Dictionary<string, object>() {
{ "key", prev["key"] },
var prev = (Dictionary<string, object>)histData[(i - 2).ToString()]; // get the history data from the previous file version
dataObj.Add("previous", new Dictionary<string, object>() { // write information about previous file version to the data object
{ "key", prev["key"] }, // write key and url information about previous file version
{ "url", prev["url"] },
});
// write the path to the diff.zip archive with differences in this file version
dataObj.Add("changesUrl", DocManagerHelper.GetPathUri(Path.Combine(DocManagerHelper.VersionDir(histDir, i - 1), "diff.zip").Substring(HttpRuntime.AppDomainAppPath.Length)));
}
if(JwtManager.Enabled)
@ -245,10 +262,11 @@ namespace OnlineEditorsExampleMVC.Models
var token = JwtManager.Encode(dataObj);
dataObj.Add("token", token);
}
hist.Add(obj);
histData.Add((i - 1).ToString(), dataObj);
hist.Add(obj); // add object dictionary to the hist list
histData.Add((i - 1).ToString(), dataObj); // write data object information to the history data
}
// write history information about the current file version to the history object
history = jss.Serialize(new Dictionary<string, object>()
{
{ "currentVersion", currentVersion },
@ -258,10 +276,12 @@ namespace OnlineEditorsExampleMVC.Models
}
}
// get a document which will be compared with the current document
public void GetCompareFileData(out string compareConfig)
{
var jss = new JavaScriptSerializer();
// get the path to the compared file
var compareFileUrl = new UriBuilder(DocManagerHelper.GetServerUrl(true))
{
Path = HttpRuntime.AppDomainAppVirtualPath
@ -270,25 +290,28 @@ namespace OnlineEditorsExampleMVC.Models
Query = "type=assets&fileName=" + HttpUtility.UrlEncode("sample.docx")
};
// create an object with the information about the compared file
var dataCompareFile = new Dictionary<string, object>
{
{ "fileType", "docx" },
{ "url", compareFileUrl.ToString() }
};
if (JwtManager.Enabled)
if (JwtManager.Enabled) // if the secret key to generate token exists
{
var compareFileToken = JwtManager.Encode(dataCompareFile);
dataCompareFile.Add("token", compareFileToken);
var compareFileToken = JwtManager.Encode(dataCompareFile); // encode the dataCompareFile object into the token
dataCompareFile.Add("token", compareFileToken); // and add it to the dataCompareFile object
}
compareConfig = jss.Serialize(dataCompareFile);
}
// get a logo config
public void GetLogoConfig(out string logoUrl)
{
var jss = new JavaScriptSerializer();
// get the path to the logo image
var mailMergeUrl = new UriBuilder(DocManagerHelper.GetServerUrl(true))
{
Path = HttpRuntime.AppDomainAppVirtualPath
@ -296,25 +319,28 @@ namespace OnlineEditorsExampleMVC.Models
+ "Content\\images\\logo.png"
};
// create a logo config
var logoConfig = new Dictionary<string, object>
{
{ "fileType", "png"},
{ "url", mailMergeUrl.ToString()}
};
if (JwtManager.Enabled)
if (JwtManager.Enabled) // if the secret key to generate token exists
{
var token = JwtManager.Encode(logoConfig);
logoConfig.Add("token", token);
var token = JwtManager.Encode(logoConfig); // encode logoConfig into the token
logoConfig.Add("token", token); // and add it to the logo config
}
logoUrl = jss.Serialize(logoConfig).Replace("{", "").Replace("}", "");
}
// get a mail merge config
public void GetMailMergeConfig(out string dataMailMergeRecipients)
{
var jss = new JavaScriptSerializer();
// get the path to the recipients data for mail merging
var mailMergeUrl = new UriBuilder(DocManagerHelper.GetServerUrl(true))
{
Path =
@ -324,16 +350,17 @@ namespace OnlineEditorsExampleMVC.Models
Query = "type=csv"
};
// create a mail merge config
var mailMergeConfig = new Dictionary<string, object>
{
{ "fileType", "csv" },
{ "url", mailMergeUrl.ToString()}
};
if (JwtManager.Enabled)
if (JwtManager.Enabled) // if the secret key to generate token exists
{
var mailmergeToken = JwtManager.Encode(mailMergeConfig);
mailMergeConfig.Add("token", mailmergeToken);
var mailmergeToken = JwtManager.Encode(mailMergeConfig); // encode mailMergeConfig into the token
mailMergeConfig.Add("token", mailmergeToken); // and add it to the mail merge config
}
dataMailMergeRecipients = jss.Serialize(mailMergeConfig);

View File

@ -1,6 +1,6 @@
/**
*
* (c) Copyright Ascensio System SIA 2020
* (c) Copyright Ascensio System SIA 2021
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -30,17 +30,19 @@ namespace OnlineEditorsExampleMVC.Models
Slide
}
// get file type
public static FileType GetFileType(string fileName)
{
var ext = Path.GetExtension(fileName).ToLower();
if (ExtsDocument.Contains(ext)) return FileType.Word;
if (ExtsSpreadsheet.Contains(ext)) return FileType.Cell;
if (ExtsPresentation.Contains(ext)) return FileType.Slide;
if (ExtsDocument.Contains(ext)) return FileType.Word; // word type for document extensions
if (ExtsSpreadsheet.Contains(ext)) return FileType.Cell; // cell type for spreadsheet extensions
if (ExtsPresentation.Contains(ext)) return FileType.Slide; // slide type for presentation extensions
return FileType.Word;
return FileType.Word; // the default type is word
}
// document extensions
public static readonly List<string> ExtsDocument = new List<string>
{
".doc", ".docx", ".docm",
@ -50,6 +52,7 @@ namespace OnlineEditorsExampleMVC.Models
".pdf", ".djvu", ".fb2", ".epub", ".xps"
};
// spreadsheet extensions
public static readonly List<string> ExtsSpreadsheet = new List<string>
{
".xls", ".xlsx", ".xlsm",
@ -57,6 +60,7 @@ namespace OnlineEditorsExampleMVC.Models
".ods", ".fods", ".ots", ".csv"
};
// presentation extensions
public static readonly List<string> ExtsPresentation = new List<string>
{
".pps", ".ppsx", ".ppsm",

View File

@ -109,6 +109,7 @@
<Compile Include="Helpers\DocManagerHelper.cs" />
<Compile Include="Helpers\DocumentConverter.cs" />
<Compile Include="Helpers\JwtManager.cs" />
<Compile Include="Helpers\Users.cs" />
<Compile Include="Helpers\Utils.cs" />
<Compile Include="Models\FileModel.cs" />
<Compile Include="Models\FileUtility.cs" />

View File

@ -7,7 +7,7 @@ using System.Runtime.InteropServices;
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Ascensio System SIA")]
[assembly: AssemblyProduct("OnlineEditorsExampleMVC")]
[assembly: AssemblyCopyright("Ascensio System SIA 2020")]
[assembly: AssemblyCopyright("Ascensio System SIA 2021")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]

View File

@ -0,0 +1,49 @@
## How to integrate online editors into your own web site on .Net (C# MVC)
### Introduction
To integrate **ONLYOFFICE online editors** into your own website on **.Net (C# MVC)** you need to download and install ONLYOFFICE editors on your local server and use the [.Net (C# MVC) example](https://api.onlyoffice.com/editors/demopreview) for their integration.
Please note that the integration examples are used to demonstrate document editors functions and the ways to connect **Document Server** to your own application. **DO NOT USE** these examples on your own server without **PROPER CODE MODIFICATIONS**!
This guide will show you the sequence of actions to integrate the editors successfully.
### Step 1. Download and Install Document Server
First, download the [**ONLYOFFICE Editors**](https://api.onlyoffice.com/editors/demopreview) (the ONLYOFFICE Document Server).
See the detailed guide to learn how to install Document Server [for Windows](https://helpcenter.onlyoffice.com/installation/docs-developer-install-windows.aspx?from=api_csharp_example), [for Linux](https://helpcenter.onlyoffice.com/installation/docs-developer-install-ubuntu.aspx?from=api_csharp_example), or [for Docker](https://helpcenter.onlyoffice.com/server/developer-edition/docker/docker-installation.aspx?from=api_csharp_example).
### Step 2. Download the .Net (C# MVC) code for the editors integration
Download the [.Net (C# MVC) example](https://api.onlyoffice.com/editors/demopreview) from our site.
You need to connnect the editors to your web site. For that specify the path to the editors installation in the *settings.config* file:
```
<add key="files.docservice.url.site" value="https://documentserver/" />
```
where the **documentserver** is the name of the server with the ONLYOFFICE Document Server installed.
If you want to experiment with the editor configuration, modify the [parameters](https://api.onlyoffice.com/editors/advanced) it the *DocEditor.aspx* file.
### Step 3. Install the prerequisites
To run your website with the editors successfully, check if your system meets the necessary system requirements:
* Microsoft .NET Framework: version 4.5 (download it from the [official Microsoft website](https://www.microsoft.com/en-US/download/details.aspx?id=30653));
* Internet Information Services: version 7 or later.
### Step 4. Running your web site with the editors
1. Run the Internet Information Service (IIS) manager
Start -> ControlPanel -> System and Security -> Administrative Tools -> Internet Information Services (IIS) Manager
2. Add your web site in the IIS Manager
On the **Connections** panel right-click the **Sites** node in the tree, then click **Add Website**.
![add](screenshots/add.png)
3. In the **Add Website** dialog box specify the name of the folder with the .Net (C# MVC) project in the **Site name** box.
Specify the path to the folder with your project in the **Physical Path** box.
Specify the unique value used only for this website in the **Port** box.
![sitename](screenshots/sitename.png)
4. Check for the .NET platform version specified in IIS manager for you web site. Choose **v4.0.** version.
Click the **Application Pool** -> right-click the platform name -> **Set application Pool defaults** -> **.NET CLR version**
![platform](screenshots/platform.png)
5. Browse your web site with the IIS manager:
Right-click the site -> **Manage Website** -> **Browse**
![browse](screenshots/browse.png)
### Step 5. Checking accessibility
In case the example and Document Server are installed on different computers, make sure that your server with the example installed has access to the Document Server with the address which you specify instead of **documentserver** in the configuration files. And you must also make sure that the Document Server in its turn has access to the server with the example installed with the address which you specify instead of **example.com** in the configuration files.
If you integrated the editors successfully the result should look like the [demo preview](https://api.onlyoffice.com/editors/demopreview#DemoPreview) on our site.

View File

@ -1,16 +0,0 @@
For the ONLYOFFICE Applications example to work properly you need to do the following:
1. Download and extract the Example.zip into a directory selected for it, for instance, C:\OnlyofficeExample
2. Run the IIS Manager (C:\Windows\system32\inetsrv\InetMgr.exe or Start -> All Programs -> Administrative Tools -> Internet Information Services (IIS) Manager for Windows Server 2003)
3. Add the unpacked Example to the list of sites with the physical path to the C:\OnlyofficeExample (or the one you selected) folder.
4. Make sure that the user account under which the IIS NetworkService process is executed has the write access rights for the C:\OnlyofficeExample\App_Data folder (this is significant for the IIS later than 6.0).
5. Make the created ONLYOFFIC<49> Applications example available through IP or domain name so that it could be connected from the web by the document service for proper document rendering.

View File

@ -1,6 +1,6 @@
/**
*
* (c) Copyright Ascensio System SIA 2020
* (c) Copyright Ascensio System SIA 2021
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

View File

@ -1,6 +1,6 @@
/**
*
* (c) Copyright Ascensio System SIA 2020
* (c) Copyright Ascensio System SIA 2021
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -19,6 +19,8 @@
if (typeof jQuery != "undefined") {
jq = jQuery.noConflict();
mustReload = false;
jq(function () {
jq('#fileupload').fileupload({
dataType: 'json',
@ -28,14 +30,16 @@ if (typeof jQuery != "undefined") {
jq(".current").removeClass("current");
jq("#step1").addClass("current");
jq("#mainProgress .error-message").hide().find("span").text("");
jq("#blockPassword").hide();
jq("#mainProgress").removeClass("embedded");
jq("#uploadFileName").text("");
jq.blockUI({
theme: true,
title: "Getting ready to load the file" + "<div class=\"dialog-close\"></div>",
title: "File upload" + "<div class=\"dialog-close\"></div>",
message: jq("#mainProgress"),
overlayCSS: { "background-color": "#aaa" },
themedCSS: { width: "656px", top: "20%", left: "50%", marginLeft: "-328px" }
themedCSS: { width: "539px", top: "20%", left: "50%", marginLeft: "-269px" }
});
jq("#beginEdit, #beginView, #beginEmbedded").addClass("disable");
@ -55,9 +59,12 @@ if (typeof jQuery != "undefined") {
}
jq("#hiddenFileName").val(response.filename);
jq("#uploadFileName").text(response.filename);
jq("#uploadFileName").addClass(response.documentType);
mustReload = true;
jq("#step1").addClass("done").removeClass("current");
jq("#step2").addClass("current");
checkConvert();
}
@ -67,7 +74,7 @@ if (typeof jQuery != "undefined") {
});
var timer = null;
var checkConvert = function () {
var checkConvert = function (filePass = null) {
if (timer != null) {
clearTimeout(timer);
}
@ -75,41 +82,56 @@ if (typeof jQuery != "undefined") {
if (!jq("#mainProgress").is(":visible")) {
return;
}
jq("#step2").addClass("current");
jq("#filePass").val("");
var fileName = jq("#hiddenFileName").val();
var posExt = fileName.lastIndexOf('.');
posExt = 0 <= posExt ? fileName.substring(posExt).trim().toLowerCase() : '';
if (ConverExtList.indexOf(posExt) == -1) {
jq("#step2").addClass("done").removeClass("current");
loadScripts();
return;
}
timer = setTimeout(function () {
var requestAddress = UrlConverter
+ "&filename=" + encodeURIComponent(jq("#hiddenFileName").val());
jq.ajax({
async: true,
contentType: "text/xml",
type: "get",
url: requestAddress,
type: "post",
dataType: "json",
data: JSON.stringify({ filename: fileName, filePass: filePass }),
url: UrlConverter,
complete: function (data) {
var responseText = data.responseText;
var response = jq.parseJSON(responseText);
if (response.error) {
jq(".current").removeClass("current");
jq(".step:not(.done)").addClass("error");
jq("#mainProgress .error-message").show().find("span").text(response.error);
jq('#hiddenFileName').val("");
return;
if (response.error.includes("Incorrect password")) {
jq(".current").removeClass("current");
jq("#step2").addClass("error");
jq("#blockPassword").show();
if (filePass) {
jq("#filePass").addClass("errorInput");
jq(".errorPass").text("The password is incorrect, please try again.");
}
return;
} else {
jq(".current").removeClass("current");
jq(".step:not(.done)").addClass("error");
jq("#mainProgress .error-message").show().find("span").text(response.error);
jq('#hiddenFileName').val("");
return;
}
}
jq("#hiddenFileName").val(response.filename);
if (response.step && response.step < 100) {
checkConvert();
checkConvert(filePass);
} else {
jq("#step2").addClass("done").removeClass("current");
loadScripts();
}
}
@ -121,7 +143,6 @@ if (typeof jQuery != "undefined") {
if (!jq("#mainProgress").is(":visible")) {
return;
}
jq("#step2").addClass("done").removeClass("current");
jq("#step3").addClass("current");
if (jq("#loadScripts").is(":empty")) {
@ -172,13 +193,29 @@ if (typeof jQuery != "undefined") {
userSel.on("change", function () {
setCookie("uid", userSel.val());
setCookie("uname", userSel.find("option:selected").text())
});
langSel.on("change", function () {
setCookie("ulang", langSel.val());
});
};
jq(document).on("click", "#enterPass", function () {
var filePass = jq("#filePass").val();
if (filePass) {
jq("#step2").removeClass("error");
jq("#blockPassword").hide();
checkConvert(filePass);
} else {
jq("#filePass").addClass("errorInput");
jq(".errorPass").text("Password can't be blank.");
}
});
jq(document).on("click", "#skipPass", function () {
jq("#blockPassword").hide();
loadScripts();
});
jq(document).on("click", "#beginEdit:not(.disable)", function () {
var fileId = encodeURIComponent(jq('#hiddenFileName').val());
var url = UrlEditor + "?fileName=" + fileId;
@ -197,7 +234,7 @@ if (typeof jQuery != "undefined") {
jq(document).on("click", "#beginEmbedded:not(.disable)", function () {
var fileId = encodeURIComponent(jq('#hiddenFileName').val());
var url = UrlEditor + "?mode=embedded&fileName=" + fileId;
var url = UrlEditor + "?editorsType=embedded&editorsMode=embedded&fileName=" + fileId;
jq("#mainProgress").addClass("embedded");
jq("#beginEmbedded").addClass("disable");
@ -209,6 +246,9 @@ if (typeof jQuery != "undefined") {
jq('#hiddenFileName').val("");
jq("#embeddedView").attr("src", "");
jq.unblockUI();
if (mustReload) {
document.location.reload();
}
});
jq(document).on("click", ".try-editor", function (e) {
@ -238,8 +278,30 @@ if (typeof jQuery != "undefined") {
});
});
jq.dropdownToggle({
switcherSelector: ".question",
dropdownID: "hint"
jq(".info").mouseover(function (event) {
var target = event.target;
var id = target.dataset.id ? target.dataset.id : target.id;
var tooltip = target.dataset.tooltip;
jq("<div class='tooltip'>" + tooltip + "</div><div class='arrow'></div>").appendTo("body");
var left = jq("#" + id).offset().left + jq("#" + id).outerWidth();
var topElement = jq("#" + id).offset().top;
var halfHeightElement = jq("#" + id).outerHeight() / 2;
var heightToFooter = jq("footer").offset().top - (topElement + halfHeightElement);
var halfHeightTooltip = jq("div.tooltip").outerHeight() / 2;
if (heightToFooter > (halfHeightTooltip + 10)) {
var top = topElement + halfHeightElement - halfHeightTooltip;
} else {
var top = jq("footer").offset().top - jq("div.tooltip").outerHeight() - 10;
}
jq("div.tooltip").css({ "top": top, "left": left + 10 });
jq("div.arrow").css({ "top": topElement + halfHeightElement, "left": left + 6 });
}).mouseout(function () {
jq("div.tooltip").remove();
jq("div.arrow").remove();
});
}

View File

@ -14,7 +14,7 @@
<meta name="mobile-web-app-capable" content="yes" />
<!--
*
* (c) Copyright Ascensio System SIA 2020
* (c) Copyright Ascensio System SIA 2021
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -52,28 +52,34 @@
console.log(message);
};
// the application is loaded into the browser
var onAppReady = function () {
innerAlert("Document editor ready");
};
// the document is modified
var onDocumentStateChange = function (event) {
var title = document.title.replace(/\*$/g, "");
document.title = title + (event.data ? "*" : "");
};
// the user is trying to switch the document from the viewing into the editing mode
var onRequestEditRights = function () {
location.href = location.href.replace(RegExp("action=view\&?", "i"), "");
location.href = location.href.replace(RegExp("editorsMode=view\&?", "i"), "");
};
// an error or some other specific event occurs
var onError = function (event) {
if (event)
innerAlert(event.data);
};
// the document is opened for editing with the old document.key value
var onOutdatedVersion = function (event) {
location.reload(true);
};
// replace the link to the document which contains a bookmark
var replaceActionLink = function(href, linkParam) {
var link;
var actionIndex = href.indexOf("&actionLink=");
@ -90,38 +96,43 @@
return link;
}
// the user is trying to get link for opening the document which contains a bookmark, scrolling to the bookmark position
var onMakeActionLink = function (event) {
var actionData = event.data;
var linkParam = JSON.stringify(actionData);
docEditor.setActionLink(replaceActionLink(location.href, linkParam));
docEditor.setActionLink(replaceActionLink(location.href, linkParam)); // set the link to the document which contains a bookmark
};
// the meta information of the document is changed via the meta command
var onMetaChange = function (event) {
var favorite = !!event.data.favorite;
var title = document.title.replace(/^\☆/g, "");
document.title = (favorite ? "☆" : "") + title;
docEditor.setFavorite(favorite);
docEditor.setFavorite(favorite); // change the Favorite icon state
};
// the user is trying to insert an image by clicking the Image from Storage button
var onRequestInsertImage = function (event) {
<% string logoUrl;%>
<% Model.GetLogoConfig(out logoUrl); %>
docEditor.insertImage({
docEditor.insertImage({ // insert an image into the file
"c": event.data.c,
<%= logoUrl%>
})
};
// the user is trying to select document for comparing by clicking the Document from Storage button
var onRequestCompareFile = function () {
<% string compareFileData; %>
<% Model.GetCompareFileData(out compareFileData); %>
docEditor.setRevisedFile(<%=compareFileData%>);
docEditor.setRevisedFile(<%=compareFileData%>); // select a document for comparing
};
// the user is trying to select recipients data by clicking the Mail merge button
var onRequestMailMergeRecipients = function (event) {
<% string dataMailMergeRecipients; %>
<% Model.GetMailMergeConfig(out dataMailMergeRecipients); %>
docEditor.setMailMergeRecipients(<%= dataMailMergeRecipients%>);
docEditor.setMailMergeRecipients(<%= dataMailMergeRecipients%>); // insert recipient data for mail merge into the file
};
var config = <%= Model.GetDocConfig(Request, Url) %>;
@ -146,14 +157,17 @@
<% Model.GetHistory(out hist, out histData); %>
<% if (!string.IsNullOrEmpty(hist) && !string.IsNullOrEmpty(histData))
{ %>
// the user is trying to show the document version history
config.events['onRequestHistory'] = function () {
docEditor.refreshHistory(<%= hist %>);
docEditor.refreshHistory(<%= hist %>); // show the document version history
};
// the user is trying to click the specific document version in the document version history
config.events['onRequestHistoryData'] = function (event) {
var ver = event.data;
var histData = <%= histData %>;
docEditor.setHistoryData(histData[ver - 1]);
docEditor.setHistoryData(histData[ver - 1]); // send the link to the document for viewing the version history
};
// the user is trying to go back to the document from viewing the document version history
config.events['onRequestHistoryClose '] = function () {
document.location.reload();
};

View File

@ -1,10 +1,11 @@
<%@ Page Title="ONLYOFFICE" Language="C#" Inherits="System.Web.Mvc.ViewPage" %>
<%@ Import Namespace="System.IO" %>
<%@ Import Namespace="System.Web.Configuration" %>
<%@ Import Namespace="OnlineEditorsExampleMVC.Helpers" %>
<%@ Import Namespace="OnlineEditorsExampleMVC.Models" %>
<!DOCTYPE html>
<!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">
@ -13,7 +14,7 @@
<meta name="viewport" content="width=device-width" />
<!--
*
* (c) Copyright Ascensio System SIA 2020
* (c) Copyright Ascensio System SIA 2021
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -37,258 +38,303 @@
<%: Styles.Render("~/Content/css") %>
</head>
<body>
<div class="top-panel">
<a href="">
<img src ="content/images/logo.svg" alt="ONLYOFFICE" />
</a>
</div>
<div class="main-panel">
<span class="portal-name">ONLYOFFICE Document Editors</span>
<br />
<br />
<span class="portal-descr">Get started with a demo-sample of ONLYOFFICE Document Editors, the first html5-based editors. You may upload your own documents for testing using the "Upload file" button and selecting the necessary files on your PC.</span>
<header>
<div class="center">
<a href="">
<img src ="content/images/logo.svg" alt="ONLYOFFICE" />
</a>
</div>
</header>
<table class="user-block-table" cellspacing="0" cellpadding="0">
<div class="center main">
<table class="table-main">
<tbody>
<tr>
<td width="30%" valign="middle">
<span class="select-user">Username:</span>
<select class="select-user" id="user">
<option value="uid-1">John Smith</option>
<option value="uid-2">Mark Pottato</option>
<option value="uid-3">Hamish Mitchell</option>
<option value="uid-0">anonymous</option>
</select>
<td class="left-panel section">
<div class="help-block">
<span>Create new</span>
<div class="clearFix">
<div class="create-panel">
<ul class="try-editor-list clearFix" data-link="<%= Url.Action("sample", "Home") %>">
<li>
<a class="try-editor word" data-type="docx">Document</a>
</li>
<li>
<a class="try-editor cell" data-type="xlsx">Spreadsheet</a>
</li>
<li>
<a class="try-editor slide" data-type="pptx">Presentation</a>
</li>
</ul>
<label class="create-sample">
<input id="createSample" class="checkbox" type="checkbox" />With sample content
</label>
</div>
<div class="upload-panel clearFix">
<a class="file-upload">Upload file
<input type="file" id="fileupload" name="files[]" data-url="<%= Url.Content("~/webeditor.ashx?type=upload") %>" />
</a>
</div>
</div>
<table class="user-block-table" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td valign="middle">
<span class="select-user">Username</span>
<img class="info" data-id="user" data-tooltip="You can open the same document using different users in different Web browser sessions, so you can check out multi-user editing functions.
</br>
<% foreach (User user in Users.getAllUsers())
{ %>
<b><%= user.name.IsEmpty() ? "Anonymous" : user.name %></b>
<ul>
<% foreach (string description in user.descriptions)
{ %>
<li><%= description %></li>
<% } %>
</ul>
<% } %>"
src="content/images/info.svg" />
<select class="select-user" id="user">
<% foreach (User user in Users.getAllUsers())
{ %>
<option value="<%= user.id %>"><%= user.name.IsEmpty() ? "Anonymous" : user.name %></option>
<% } %>
</select>
</td>
</tr>
<tr>
<td valign="middle">
<span class="select-user">Language</span>
<img class="info" data-id="language" data-tooltip="Choose the language for ONLYOFFICE editors interface" src="content/images/info.svg" />
<select class="select-user" id="language">
<option value="en">English</option>
<option value="be">Belarusian</option>
<option value="bg">Bulgarian</option>
<option value="ca">Catalan</option>
<option value="zh">Chinese</option>
<option value="cs">Czech</option>
<option value="da">Danish</option>
<option value="nl">Dutch</option>
<option value="fi">Finnish</option>
<option value="fr">French</option>
<option value="de">German</option>
<option value="el">Greek</option>
<option value="hu">Hungarian</option>
<option value="id">Indonesian</option>
<option value="it">Italian</option>
<option value="ja">Japanese</option>
<option value="ko">Korean</option>
<option value="lv">Latvian</option>
<option value="lo">Lao</option>
<option value="nb">Norwegian</option>
<option value="pl">Polish</option>
<option value="pt">Portuguese</option>
<option value="ro">Romanian</option>
<option value="ru">Russian</option>
<option value="sk">Slovak</option>
<option value="sl">Slovenian</option>
<option value="sv">Swedish</option>
<option value="es">Spanish</option>
<option value="tr">Turkish</option>
<option value="uk">Ukrainian</option>
<option value="vi">Vietnamese</option>
</select>
</td>
</tr>
</tbody>
</table>
</div>
</td>
<td width="70%" valign="middle">Select user name before opening the document; you can open the same document using different users in different Web browser sessions, so you can check out multi-user editing functions.</td>
</tr>
<tr>
<td width="30%" valign="middle">
<select class="select-user" id="language">
<option value="en">English</option>
<option value="be">Belarusian</option>
<option value="bg">Bulgarian</option>
<option value="ca">Catalan</option>
<option value="zh">Chinese</option>
<option value="cs">Czech</option>
<option value="da">Danish</option>
<option value="nl">Dutch</option>
<option value="fi">Finnish</option>
<option value="fr">French</option>
<option value="de">German</option>
<option value="el">Greek</option>
<option value="hu">Hungarian</option>
<option value="id">Indonesian</option>
<option value="it">Italian</option>
<option value="ja">Japanese</option>
<option value="ko">Korean</option>
<option value="lv">Latvian</option>
<option value="lo">Lao</option>
<option value="nb">Norwegian</option>
<option value="pl">Polish</option>
<option value="pt">Portuguese</option>
<option value="ro">Romanian</option>
<option value="ru">Russian</option>
<option value="sk">Slovak</option>
<option value="sl">Slovenian</option>
<option value="sv">Swedish</option>
<option value="es">Spanish</option>
<option value="tr">Turkish</option>
<option value="uk">Ukrainian</option>
<option value="vi">Vietnamese</option>
</select>
<td class="section">
<div class="main-panel">
<% var storedFiles = DocManagerHelper.GetStoredFiles();
if (!storedFiles.Any())
{ %>
<span class="portal-name">ONLYOFFICE Document Editors Welcome!</span>
<span class="portal-descr">
Get started with a demo-sample of ONLYOFFICE Document Editors, the first html5-based editors.
<br /> You may upload your own documents for testing using the "<b>Upload file</b>" button and <b>selecting</b> the necessary files on your PC.
</span>
<% }
else
{ %>
<div class="stored-list">
<span class="header-list">Your documents</span>
<table class="tableHeader" cellspacing="0" cellpadding="0" width="100%">
<thead>
<tr>
<td class="tableHeaderCell tableHeaderCellFileName">Filename</td>
<td class="tableHeaderCell tableHeaderCellEditors contentCells-shift">Editors</td>
<td class="tableHeaderCell tableHeaderCellViewers">Viewers</td>
<td class="tableHeaderCell tableHeaderCellDownload">Download</td>
<td class="tableHeaderCell tableHeaderCellRemove">Remove</td>
</tr>
</thead>
</table>
<div class="scroll-table-body">
<table cellspacing="0" cellpadding="0" width="100%">
<tbody>
<% foreach (var storedFile in storedFiles)
{
var editUrl = "doceditor.aspx?fileID=" + HttpUtility.UrlEncode(storedFile.Name);
var docType = FileUtility.GetFileType(storedFile.Name).ToString().ToLower();
var canEdir = DocManagerHelper.EditedExts.Contains(Path.GetExtension(storedFile.Name).ToLower());
%>
<tr class="tableRow" title="<%= storedFile.Name %>">
<td class="contentCells">
<a class="stored-edit <%= docType %>" href="<%= Url.Action("Editor", "Home", new { fileName = storedFile.Name }) %>" target="_blank">
<span title="<%= storedFile.Name %>"><%= storedFile.Name %></span>
</a>
</td>
<% if (canEdir) { %>
<td class="contentCells contentCells-icon">
<a href="<%= Url.Action("Editor", "Home", new { fileName = storedFile.Name, editorsType = "desktop", editorsMode = "edit" }) %>" target="_blank">
<img src="content/images/desktop-24.png" alt="Open in editor for full size screens" title="Open in editor for full size screens"/>
</a>
</td>
<td class="contentCells contentCells-icon">
<a href="<%= Url.Action("Editor", "Home", new { fileName = storedFile.Name, editorsType = "mobile", editorsMode = "edit" }) %>" target="_blank">
<img src="content/images/mobile-24.png" alt="Open in editor for mobile devices" title="Open in editor for mobile devices"/>
</a>
</td>
<td class="contentCells contentCells-icon">
<% if (docType == "word") { %>
<a href="<%= Url.Action("Editor", "Home", new { fileName = storedFile.Name, editorsType = "desktop", editorsMode = "review" }) %>" target="_blank">
<img src="content/images/review-24.png" alt="Open in editor for review" title="Open in editor for review"/>
</a>
<% } else if (docType == "cell") { %>
<a href="<%= Url.Action("Editor", "Home", new { fileName = storedFile.Name, editorsType = "desktop", editorsMode = "filter" }) %>" target="_blank">
<img src="content/images/filter-24.png" alt="Open in editor without access to change the filter" title="Open in editor without access to change the filter" />
</a>
<% } %>
</td>
<td class="contentCells contentCells-icon">
<a href="<%= Url.Action("Editor", "Home", new { fileName = storedFile.Name, editorsType = "desktop", editorsMode = "comment" }) %>" target="_blank">
<img src="content/images/comment-24.png" alt="Open in editor for comment" title="Open in editor for comment"/>
</a>
</td>
<td class="contentCells contentCells-icon">
<% if (docType == "word") { %>
<a href="<%= Url.Action("Editor", "Home", new { fileName = storedFile.Name, editorsType = "desktop", editorsMode = "fillForms" }) %>" target="_blank">
<img src="content/images/fill-forms-24.png" alt="Open in editor for filling in forms" title="Open in editor for filling in forms"/>
</a>
<% } %>
</td>
<td class="contentCells contentCells-shift contentCells-icon">
<% if (docType == "word") { %>
<a href="<%= Url.Action("Editor", "Home", new { fileName = storedFile.Name, editorsType = "desktop", editorsMode = "blockcontent" }) %>" target="_blank">
<img src="content/images/block-content-24.png" alt="Open in editor without content control modification" title="Open in editor without content control modification"/>
</a>
<% } %>
</td>
<% } else { %>
<td class="contentCells contentCells-shift contentCells-icon" colspan="6"></td>
<% } %>
<td class="contentCells contentCells-icon">
<a href="<%= Url.Action("Editor", "Home", new { fileName = storedFile.Name, editorsType = "desktop", editorsMode = "view" }) %>" target="_blank">
<img src="content/images/desktop-24.png" alt="Open in viewer for full size screens" title="Open in viewer for full size screens"/>
</a>
</td>
<td class="contentCells contentCells-icon">
<a href="<%= Url.Action("Editor", "Home", new { fileName = storedFile.Name, editorsType = "mobile", editorsMode = "view" }) %>" target="_blank">
<img src="content/images/mobile-24.png" alt="Open in viewer for mobile devices" title="Open in viewer for mobile devices"/>
</a>
</td>
<td class="contentCells contentCells-icon contentCells-shift">
<a href="<%= Url.Action("Editor", "Home", new { fileName = storedFile.Name, editorsType = "embedded", editorsMode = "embedded" }) %>" target="_blank">
<img src="content/images/embeded-24.png" alt="Open in embedded mode" title="Open in embedded mode"/>
</a>
</td>
<td class="contentCells contentCells-icon contentCells-shift">
<a href="webeditor.ashx?type=download&fileName=<%= HttpUtility.UrlEncode(storedFile.Name) %>">
<img class="icon-download" src="content/images/download-24.png" alt="Download" title="Download" />
</a>
</td>
<td class="contentCells contentCells-icon contentCells-shift">
<a class="delete-file" data-filename="<%= storedFile.Name %>">
<img class="icon-delete" src="content/images/delete-24.png" alt="Delete" title="Delete" />
</a>
</td>
</tr>
<% } %>
</tbody>
</table>
</div>
</div>
<% } %>
</div>
</td>
<td width="70%" valign="middle">Choose the language for ONLYOFFICE™ editors interface.</td>
</tr>
</tbody>
</table>
<br />
<br />
<div class="help-block">
<span class="try-descr">Upload your file or create new file</span>
<br />
<br />
<div class="clearFix">
<div class="upload-panel clearFix">
<a class="file-upload">
Upload
<br />
File
<input type="file" id="fileupload" name="files[]" data-url="<%= Url.Content("~/webeditor.ashx?type=upload") %>" />
</a>
</div>
<div class="create-panel">
<ul class="try-editor-list clearFix" data-link="<%= Url.Action("sample", "Home") %>">
<li><a class="try-editor word" data-type="docx">Create<br />Document</a></li>
<li><a class="try-editor cell" data-type="xlsx">Create<br />Spreadsheet</a></li>
<li><a class="try-editor slide" data-type="pptx">Create<br />Presentation</a></li>
</ul>
<label class="create-sample">
<input id="createSample" class="checkbox" type="checkbox" />
Create a file filled with sample content
</label>
</div>
</div>
</div>
<% var storedFiles = DocManagerHelper.GetStoredFiles();
if (storedFiles.Any())
{ %>
<div class="help-block">
<span>Your documents</span>
<br />
<br />
<div class="stored-list">
<table width="100%" cellspacing="0" cellpadding="0">
<thead>
<tr class="tableHeader">
<td class="tableHeaderCell tableHeaderCellFileName">Filename</td>
<td colspan="6" class="tableHeaderCell contentCells-shift">Editors</td>
<td colspan="3" class="tableHeaderCell">Viewers</td>
</tr>
</thead>
<tbody>
<% foreach (var storedFile in storedFiles)
{ %>
<%
var editUrl = "doceditor.aspx?fileID=" + HttpUtility.UrlEncode(storedFile.Name);
var docType = FileUtility.GetFileType(storedFile.Name).ToString().ToLower();
%>
<tr class="tableRow" title="<%= storedFile.Name %>">
<td class="contentCells">
<a class="stored-edit <%= docType %>" href="<%= Url.Action("Editor", "Home", new { fileName = storedFile.Name }) %>" target="_blank">
<span title="<%= storedFile.Name %>"><%= storedFile.Name %></span>
</a>
<a href="webeditor.ashx?type=download&filename=<%= HttpUtility.UrlEncode(storedFile.Name) %>">
<img class="icon-download" src="content/images/download-24.png" alt="Download" title="Download" />
</a>
<a class="delete-file" data-filename="<%= storedFile.Name %>">
<img class="icon-delete" src="content/images/delete-24.png" alt="Delete" title="Delete" />
</a>
</td>
<td class="contentCells contentCells-icon">
<a href="<%= Url.Action("Editor", "Home", new { fileName = storedFile.Name, editorsType = "desktop", editorsMode = "edit" }) %>" target="_blank">
<img src="content/images/desktop-24.png" alt="Open in editor for full size screens" title="Open in editor for full size screens"/>
</a>
</td>
<td class="contentCells contentCells-icon">
<a href="<%= Url.Action("Editor", "Home", new { fileName = storedFile.Name, editorsType = "mobile", editorsMode = "edit" }) %>" target="_blank">
<img src="content/images/mobile-24.png" alt="Open in editor for mobile devices" title="Open in editor for mobile devices"/>
</a>
</td>
<td class="contentCells contentCells-icon">
<% if (docType == "word") { %>
<a href="<%= Url.Action("Editor", "Home", new { fileName = storedFile.Name, editorsType = "desktop", editorsMode = "review" }) %>" target="_blank">
<img src="content/images/review-24.png" alt="Open in editor for review" title="Open in editor for review"/>
</a>
<% } else if (docType == "cell") { %>
<a href="<%= Url.Action("Editor", "Home", new { fileName = storedFile.Name, editorsType = "desktop", editorsMode = "filter" }) %>" target="_blank">
<img src="content/images/filter-24.png" alt="Open in editor without access to change the filter" title="Open in editor without access to change the filter" />
</a>
<% } %>
</td>
<td class="contentCells contentCells-icon">
<a href="<%= Url.Action("Editor", "Home", new { fileName = storedFile.Name, editorsType = "desktop", editorsMode = "comment" }) %>" target="_blank">
<img src="content/images/comment-24.png" alt="Open in editor for comment" title="Open in editor for comment"/>
</a>
</td>
<td class="contentCells contentCells-icon">
<% if (docType == "word") { %>
<a href="<%= Url.Action("Editor", "Home", new { fileName = storedFile.Name, editorsType = "desktop", editorsMode = "fillForms" }) %>" target="_blank">
<img src="content/images/fill-forms-24.png" alt="Open in editor for filling in forms" title="Open in editor for filling in forms"/>
</a>
<% } %>
</td>
<td class="contentCells contentCells-shift contentCells-icon">
<% if (docType == "word") { %>
<a href="<%= Url.Action("Editor", "Home", new { fileName = storedFile.Name, editorsType = "desktop", editorsMode = "blockcontent" }) %>" target="_blank">
<img src="content/images/block-content-24.png" alt="Open in editor without content control modification" title="Open in editor without content control modification"/>
</a>
<% } %>
</td>
<td class="contentCells contentCells-icon">
<a href="<%= Url.Action("Editor", "Home", new { fileName = storedFile.Name, editorsType = "desktop", editorsMode = "view" }) %>" target="_blank">
<img src="content/images/desktop-24.png" alt="Open in viewer for full size screens" title="Open in viewer for full size screens"/>
</a>
</td>
<td class="contentCells contentCells-icon">
<a href="<%= Url.Action("Editor", "Home", new { fileName = storedFile.Name, editorsType = "mobile", editorsMode = "view" }) %>" target="_blank">
<img src="content/images/mobile-24.png" alt="Open in viewer for mobile devices" title="Open in viewer for mobile devices"/>
</a>
</td>
<td class="contentCells contentCells-icon">
<a href="<%= Url.Action("Editor", "Home", new { fileName = storedFile.Name, editorsType = "embedded", editorsMode = "embedded" }) %>" target="_blank">
<img src="content/images/embeded-24.png" alt="Open in embedded mode" title="Open in embedded mode"/>
</a>
</td>
</tr>
<% } %>
</tbody>
</table>
</div>
</div>
<% } %>
<br />
<br />
<br />
<div class="help-block">
<span>Want to learn how it works?</span>
<br />
Read the editor <a href="http://api.onlyoffice.com/editors/howitworks">API Documentation</a>
</div>
<br />
<br />
<br />
<div class="help-block">
<span>Any questions?</span>
<br />
Please, <a href="mailto:sales@onlyoffice.com">submit your request</a> and we'll help you shortly.
</div>
</div>
<div id="hint">
<div class="corner"></div>
If you check this option the file will be saved both in the original and converted into Office Open XML format for faster viewing and editing. In other case the document will be overwritten by its copy in Office Open XML format.
</div>
<div id="mainProgress">
<div id="uploadSteps">
<span id="step1" class="step">1. Loading the file</span>
<span class="step-descr">The file loading process will take some time depending on the file size, presence or absence of additional elements in it (macros, etc.) and the connection speed.</span>
<span id="uploadFileName" class="uploadFileName"></span>
<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>
<br />
<span id="step2" class="step">2. File conversion</span>
<span class="step-descr">The file is being converted into Office Open XML format for the document faster viewing and editing.</span>
<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>
<br />
<span id="step3" class="step">3. Loading editor scripts</span>
<span class="step-descr">The scripts for the editor are loaded only once and are will be cached on your computer in future. It might take some time depending on the connection speed.</span>
<div id="blockPassword">
<span class="descrFilePass">The file is password protected.</span>
<br />
<div>
<input id="filePass" type="password"/>
<div id="enterPass" class="button orange">Enter</div>
<div id="skipPass" class="button gray">Skip</div>
</div>
<span class="errorPass"></span>
<br />
</div>
<span id="step3" class="step">3. Loading editor scripts.</span>
<span class="step-descr">They are loaded only once, they will be cached on your computer.</span>
<input type="hidden" name="hiddenFileName" id="hiddenFileName" />
<br />
<br />
<span class="progress-descr">Please note, that the speed of all operations greatly depends on the server and the client locations. In case they differ or are located in differernt countries/continents, there might be lack of speed and greater wait time. The best results are achieved when the server and client computers are located in one and the same place (city).</span>
<span class="progress-descr">Note the speed of all operations depends on your connection quality and server location.</span>
<br />
<br />
<div class="error-message">
<span></span>
<b>Upload error: </b><span></span>
<br />
Please select another file and try again. If you have questions please <a href="mailto:sales@onlyoffice.com">contact us.</a>
Please select another file and try again.
</div>
</div>
<iframe id="embeddedView" src="" height="345px" width="600px" frameborder="0" scrolling="no" allowtransparency></iframe>
<iframe id="embeddedView" src="" height="345px" width="432px" frameborder="0" scrolling="no" allowtransparency></iframe>
<br />
<div id="beginEmbedded" class="button disable">Embedded view</div>
<div id="beginView" class="button disable">View</div>
<div id="beginEdit" class="button disable">Edit</div>
<div id="beginEdit" class="button orange disable">Edit</div>
<div id="beginView" class="button gray disable">View</div>
<div id="beginEmbedded" class="button gray disable">Embedded view</div>
<div id="cancelEdit" class="button gray">Cancel</div>
</div>
<span id="loadScripts" data-docs="<%= WebConfigurationManager.AppSettings["files.docservice.url.site"] + WebConfigurationManager.AppSettings["files.docservice.url.preloader"] %>"></span>
<div class="bottom-panel">&copy; Ascensio System SIA <%= DateTime.Now.Year.ToString() %>. All rights reserved.</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/scripts") %>

View File

@ -5,7 +5,7 @@
<meta name="viewport" content="width=device-width" />
<!--
*
* (c) Copyright Ascensio System SIA 2020
* (c) Copyright Ascensio System SIA 2021
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

View File

@ -1,6 +1,6 @@
/**
*
* (c) Copyright Ascensio System SIA 2020
* (c) Copyright Ascensio System SIA 2021
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -37,6 +37,7 @@ namespace OnlineEditorsExampleMVC
{
public void ProcessRequest(HttpContext context)
{
// define functions for each type of operation
switch (context.Request["type"])
{
case "upload":
@ -66,6 +67,7 @@ namespace OnlineEditorsExampleMVC
}
}
// upload a file
private static void Upload(HttpContext context)
{
context.Response.ContentType = "text/plain";
@ -74,10 +76,11 @@ namespace OnlineEditorsExampleMVC
var httpPostedFile = context.Request.Files[0];
string fileName;
// check from which browser the request came for
if (HttpContext.Current.Request.Browser.Browser.ToUpper() == "IE")
{
var files = httpPostedFile.FileName.Split(new char[] { '\\' });
fileName = files[files.Length - 1];
fileName = files[files.Length - 1]; // get file name
}
else
{
@ -85,24 +88,28 @@ namespace OnlineEditorsExampleMVC
}
var curSize = httpPostedFile.ContentLength;
if (DocManagerHelper.MaxFileSize < curSize || curSize <= 0)
if (DocManagerHelper.MaxFileSize < curSize || curSize <= 0) // check if the file size exceeds the maximum file size
{
throw new Exception("File size is incorrect");
}
var curExt = (Path.GetExtension(fileName) ?? "").ToLower();
if (!DocManagerHelper.FileExts.Contains(curExt))
if (!DocManagerHelper.FileExts.Contains(curExt)) // check if the file extension is supported by the editor
{
throw new Exception("File type is not supported");
}
fileName = DocManagerHelper.GetCorrectName(fileName);
fileName = DocManagerHelper.GetCorrectName(fileName); // get the correct file name if such a name already exists
var documentType = FileUtility.GetFileType(fileName).ToString().ToLower();
var savedFileName = DocManagerHelper.StoragePath(fileName);
httpPostedFile.SaveAs(savedFileName);
DocManagerHelper.CreateMeta(fileName, context.Request.Cookies.GetOrDefault("uid", ""), context.Request.Cookies.GetOrDefault("uname", ""));
var savedFileName = DocManagerHelper.StoragePath(fileName); // get the storage path to the uploading file
httpPostedFile.SaveAs(savedFileName); // and save it
// get file meta information or create the default one
var id = context.Request.Cookies.GetOrDefault("uid", null);
var user = Users.getUser(id);
DocManagerHelper.CreateMeta(fileName, user.id, user.name);
context.Response.Write("{ \"filename\": \"" + fileName + "\"}");
context.Response.Write("{ \"filename\": \"" + fileName + "\", \"documentType\": \"" + documentType + "\"}");
}
catch (Exception e)
{
@ -110,35 +117,61 @@ namespace OnlineEditorsExampleMVC
}
}
// convert a file
private static void Convert(HttpContext context)
{
context.Response.ContentType = "text/plain";
try
{
var fileName = Path.GetFileName(context.Request["filename"]);
string fileData;
using (var receiveStream = context.Request.InputStream)
using (var readStream = new StreamReader(receiveStream))
{
fileData = readStream.ReadToEnd();
if (string.IsNullOrEmpty(fileData)) context.Response.Write("{\"error\":1,\"message\":\"Request stream is empty\"}");
}
var jss = new JavaScriptSerializer();
var body = jss.Deserialize<Dictionary<string, object>>(fileData);
var fileName = Path.GetFileName(body["filename"].ToString());
var filePass = body["filePass"] != null ? body["filePass"].ToString() : null;
var fileUri = DocManagerHelper.GetFileUri(fileName, true);
var extension = (Path.GetExtension(fileUri) ?? "").Trim('.');
var extension = (Path.GetExtension(fileUri).ToLower() ?? "").Trim('.');
var internalExtension = DocManagerHelper.GetInternalExtension(FileUtility.GetFileType(fileName)).Trim('.');
// check if the file with such an extension can be converted
if (DocManagerHelper.ConvertExts.Contains("." + extension)
&& !string.IsNullOrEmpty(internalExtension))
{
// generate document key
var key = ServiceConverter.GenerateRevisionId(fileUri);
var downloadUri = new UriBuilder(DocManagerHelper.GetServerUrl(true))
{
Path = HttpRuntime.AppDomainAppVirtualPath
+ (HttpRuntime.AppDomainAppVirtualPath.EndsWith("/") ? "" : "/")
+ "webeditor.ashx",
Query = "type=download&fileName=" + HttpUtility.UrlEncode(fileName)
};
// get the url to the converted file
string newFileUri;
var result = ServiceConverter.GetConvertedUri(fileUri, extension, internalExtension, key, true, out newFileUri);
var result = ServiceConverter.GetConvertedUri(downloadUri.ToString(), extension, internalExtension, key, true, out newFileUri, filePass);
if (result != 100)
{
context.Response.Write("{ \"step\" : \"" + result + "\", \"filename\" : \"" + fileName + "\"}");
return;
}
// get a file name of an internal file extension with an index if the file with such a name already exists
var correctName = DocManagerHelper.GetCorrectName(Path.GetFileNameWithoutExtension(fileName) + "." + internalExtension);
var req = (HttpWebRequest)WebRequest.Create(newFileUri);
using (var stream = req.GetResponse().GetResponseStream())
using (var stream = req.GetResponse().GetResponseStream()) // get response stream of the converting file
{
if (stream == null) throw new Exception("Stream is null");
const int bufferSize = 4096;
@ -149,17 +182,20 @@ namespace OnlineEditorsExampleMVC
int readed;
while ((readed = stream.Read(buffer, 0, bufferSize)) != 0)
{
fs.Write(buffer, 0, readed);
fs.Write(buffer, 0, readed); // write bytes to the output stream
}
}
}
Remove(fileName);
fileName = correctName;
DocManagerHelper.CreateMeta(fileName, context.Request.Cookies.GetOrDefault("uid", ""), context.Request.Cookies.GetOrDefault("uname", ""));
Remove(fileName); // remove the original file and its history if it exists
fileName = correctName; // create meta information about the converted file with user id and name specified
var id = context.Request.Cookies.GetOrDefault("uid", null);
var user = Users.getUser(id);
DocManagerHelper.CreateMeta(fileName, user.id, user.name);
}
context.Response.Write("{ \"filename\" : \"" + fileName + "\"}");
var documentType = FileUtility.GetFileType(fileName).ToString().ToLower();
context.Response.Write("{ \"filename\" : \"" + fileName + "\", \"documentType\": \"" + documentType + "\" }");
}
catch (Exception e)
{
@ -167,6 +203,7 @@ namespace OnlineEditorsExampleMVC
}
}
// define tracker status
private enum TrackerStatus
{
NotFound = 0,
@ -178,14 +215,16 @@ namespace OnlineEditorsExampleMVC
CorruptedForceSave = 7
}
// track file changes
private static void Track(HttpContext context)
{
// read request body
var fileData = TrackManager.readBody(context);
var userAddress = context.Request["userAddress"];
var fileName = Path.GetFileName(context.Request["fileName"]);
var status = (TrackerStatus) (int) fileData["status"];
var saved = 1;
var status = (TrackerStatus) (int) fileData["status"]; // get status from the request body
var saved = 1; // editing
switch (status)
{
case TrackerStatus.Editing:
@ -194,13 +233,13 @@ namespace OnlineEditorsExampleMVC
var jss = new JavaScriptSerializer();
var actions = jss.Deserialize <List<object>> (jss.Serialize(fileData["actions"]));
var action = jss.Deserialize <Dictionary<string, object>> (jss.Serialize(actions[0]));
if (action != null && action["type"].ToString().Equals("0"))
if (action != null && action["type"].ToString().Equals("0")) // finished edit
{
var user = action["userid"].ToString();
var user = action["userid"].ToString(); // the user who finished editing
var users = jss.Deserialize<List<object>>(jss.Serialize(fileData["users"]));
if (!users.Contains(user))
{
TrackManager.commandRequest("forcesave", fileData["key"].ToString());
TrackManager.commandRequest("forcesave", fileData["key"].ToString()); // create a command request with the forcesave method
}
}
@ -211,10 +250,12 @@ namespace OnlineEditorsExampleMVC
}
break;
// MustSave, Corrupted
case TrackerStatus.MustSave:
case TrackerStatus.Corrupted:
try
{
// saving a document
saved = TrackManager.processSave(fileData, fileName, userAddress);
}
catch (Exception)
@ -224,10 +265,12 @@ namespace OnlineEditorsExampleMVC
context.Response.Write("{\"error\":" + saved + "}");
return;
// MustForceSave, CorruptedForceSave
case TrackerStatus.MustForceSave:
case TrackerStatus.CorruptedForceSave:
try
{
// force saving a document
saved = TrackManager.processForceSave(fileData, fileName, userAddress);
}
catch (Exception)
@ -241,13 +284,14 @@ namespace OnlineEditorsExampleMVC
context.Response.Write("{\"error\":0}");
}
// remove a file
private static void Remove(HttpContext context)
{
context.Response.ContentType = "text/plain";
try
{
var fileName = Path.GetFileName(context.Request["fileName"]);
Remove(fileName);
Remove(fileName); // remove a file and its history if it exists
context.Response.Write("{ \"success\": true }");
}
@ -257,15 +301,17 @@ namespace OnlineEditorsExampleMVC
}
}
// remove a file by its name
private static void Remove(string fileName)
{
var path = DocManagerHelper.StoragePath(fileName, null);
var histDir = DocManagerHelper.HistoryDir(path);
var path = DocManagerHelper.StoragePath(fileName, null); // delete file
var histDir = DocManagerHelper.HistoryDir(path); // delete file history
if (File.Exists(path)) File.Delete(path);
if (Directory.Exists(histDir)) Directory.Delete(histDir, true);
}
// get files information
private static void Files(HttpContext context)
{
List<Dictionary<string, object>> files = null;
@ -277,12 +323,12 @@ namespace OnlineEditorsExampleMVC
if (context.Request["fileId"] == null)
{
files = DocManagerHelper.GetFilesInfo();
files = DocManagerHelper.GetFilesInfo(); // get the information about the files from the storage path
context.Response.Write(jss.Serialize(files));
}
else
{
var fileId = context.Request["fileId"];
var fileId = context.Request["fileId"]; // get file id from the request
files = DocManagerHelper.GetFilesInfo(fileId);
if (files.Count == 0)
{
@ -300,6 +346,7 @@ namespace OnlineEditorsExampleMVC
}
}
// get sample files from the assests
private static void Assets(HttpContext context)
{
var fileName = Path.GetFileName(context.Request["filename"]);
@ -307,6 +354,7 @@ namespace OnlineEditorsExampleMVC
download(filePath, context);
}
// download a csv file
private static void GetCsv(HttpContext context)
{
var fileName = "csv.csv";
@ -314,16 +362,35 @@ namespace OnlineEditorsExampleMVC
download(filePath, context);
}
// download a file
private static void Download(HttpContext context)
{
try
{
var fileName = Path.GetFileName(context.Request["filename"]);
var fileName = Path.GetFileName(context.Request["fileName"]);
var userAddress = context.Request["userAddress"];
var filePath = DocManagerHelper.ForcesavePath(fileName, null, false);
if (JwtManager.Enabled)
{
string JWTheader = WebConfigurationManager.AppSettings["files.docservice.header"].Equals("") ? "Authorization" : WebConfigurationManager.AppSettings["files.docservice.header"];
if (context.Request.Headers.AllKeys.Contains(JWTheader, StringComparer.InvariantCultureIgnoreCase))
{
var headerToken = context.Request.Headers.Get(JWTheader).Substring("Bearer ".Length);
string token = JwtManager.Decode(headerToken);
if (token == null || token.Equals(""))
{
context.Response.StatusCode = (int)HttpStatusCode.Forbidden;
context.Response.Write("JWT validation failed");
return;
}
}
}
var filePath = DocManagerHelper.ForcesavePath(fileName, userAddress, false); // get the path to the force saved document version
if (filePath.Equals(""))
{
filePath = DocManagerHelper.StoragePath(fileName, null);
filePath = DocManagerHelper.StoragePath(fileName, userAddress); // or to the original document
}
download(filePath, context);
}
@ -333,10 +400,11 @@ namespace OnlineEditorsExampleMVC
}
}
// download data from the url to the file
private static void download(string filePath, HttpContext context)
{
var fileinf = new FileInfo(filePath);
context.Response.AddHeader("Content-Length", fileinf.Length.ToString());
context.Response.AddHeader("Content-Length", fileinf.Length.ToString()); // set headers to the response
context.Response.AddHeader("Content-Type", MimeMapping.GetMimeMapping(filePath));
var tmp = HttpUtility.UrlEncode(Path.GetFileName(filePath));
tmp = tmp.Replace("+", "%20");

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 96 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 146 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 74 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 197 B

View File

@ -0,0 +1,3 @@
<svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M0.294404 0.294466C-0.0961199 0.68499 -0.0998005 1.32183 0.290724 1.71236L5.57837 7L5.57841 7.00005L0.29081 12.2877C-0.0997145 12.6782 -0.0960336 13.315 0.294491 13.7055C0.685015 14.0961 1.32186 14.0997 1.71238 13.7092L6.99999 8.42162L12.2876 13.7092C12.6781 14.0997 13.315 14.0961 13.7055 13.7055C14.096 13.315 14.0997 12.6782 13.7092 12.2877L8.42156 7.00005L8.42161 7L13.7093 1.71236C14.0998 1.32183 14.0961 0.68499 13.7056 0.294466C13.315 -0.0960591 12.6782 -0.0997395 12.2877 0.290785L7.00003 5.57843L6.99999 5.57847L6.99994 5.57843L1.7123 0.290785C1.32177 -0.0997395 0.684928 -0.0960591 0.294404 0.294466Z" fill="#AAAAAA"/>
</svg>

After

Width:  |  Height:  |  Size: 781 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 232 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 631 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 d="M10.3765 15.128C9.98789 15.5187 9.35642 15.5214 8.96449 15.134L6.14517 12.3473C5.75561 11.9622 5.12876 11.9622 4.7392 12.3473L4.72038 12.3659C4.32403 12.7576 4.32441 13.3978 4.72124 13.7891L8.96526 17.974C9.35702 18.3603 9.98726 18.3576 10.3757 17.9679L20.2877 8.02323C20.6801 7.6296 20.67 6.9855 20.2729 6.59668C19.8804 6.21243 19.2454 6.21063 18.8581 6.60005L10.3765 15.128Z" fill="#8BB825"/>
</svg>

After

Width:  |  Height:  |  Size: 507 B

View File

@ -0,0 +1,3 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M7.99857 1.6C4.46508 1.6 1.6 4.46548 1.6 8.00029C1.6 9.70508 2.26458 11.2515 3.35202 12.3999C4.52033 13.6337 6.16874 14.4 7.99857 14.4C11.5348 14.4 14.4 11.5335 14.4 8.00029C14.4 4.46592 11.5348 1.6 7.99857 1.6ZM0 8.00029C0 3.58219 3.58105 0 7.99857 0C12.4184 0 16 3.58219 16 8.00029C16 12.4172 12.4184 16 7.99857 16C5.71117 16 3.64805 15.0395 2.19023 13.5C0.83265 12.0663 0 10.1304 0 8.00029ZM7 4H9V9H7V4ZM9 10H7V12H9V10Z" fill="#CB0000"/>
</svg>

After

Width:  |  Height:  |  Size: 593 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 682 B

View File

@ -0,0 +1,8 @@
<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 0H21.674C22.4697 0 23.2327 0.316071 23.7953 0.87868L29.1213 6.20465C29.6839 6.76726 30 7.53032 30 8.32597V37C30 38.6569 28.6569 40 27 40H3C1.34315 40 0 38.6569 0 37V3Z" fill="#3779A6"/>
<path d="M22.9167 0L30.0001 7.08333H25.9167C24.2599 7.08333 22.9167 5.74019 22.9167 4.08333V0Z" fill="#1D5880"/>
<path d="M6.17627 14.7059H23.8233V15.8823H6.17627V14.7059Z" fill="white"/>
<path d="M6.17627 18.5294H23.8233V19.7059H6.17627V18.5294Z" fill="white"/>
<path d="M6.17627 22.3529H23.8233V23.5294H6.17627V22.3529Z" fill="white"/>
<path d="M6.17627 26.1765H23.8233V27.3529H6.17627V26.1765Z" fill="white"/>
</svg>

After

Width:  |  Height:  |  Size: 738 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 728 B

View File

@ -0,0 +1,8 @@
<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 0H22.9167L30 7.08333V37C30 38.6569 28.6569 40 27 40H3C1.34315 40 0 38.6569 0 37V3Z" fill="#F36700"/>
<path d="M22.9167 0L30.0001 7.08333H25.9168C24.2599 7.08333 22.9167 5.74019 22.9167 4.08333V0Z" fill="#AB531F"/>
<path d="M6.17627 16.1275H23.8233V17.3039H6.17627V16.1275Z" fill="white"/>
<path d="M6.17627 28.7745L6.17627 16.1275L7.35274 16.1275L7.35274 28.7745H6.17627Z" fill="white"/>
<path d="M23.8233 16.1275V28.7745H22.6469V16.1275L23.8233 16.1275Z" fill="white"/>
<path d="M6.17627 27.598H23.8233V28.7745H6.17627L6.17627 27.598Z" fill="white"/>
</svg>

After

Width:  |  Height:  |  Size: 691 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

View File

@ -0,0 +1,6 @@
<svg width="30" height="40" viewBox="0 0 30 40" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M30 7.44186L22 0H3C1.22739 0 0 0.822551 0 2.32558V37.2093C0 38.7123 1.22739 40 3 40H27C28.7726 40 30 38.7123 30 37.2093V7.44186Z" fill="#D0D5DA"/>
<path d="M24.1042 7.27273H29.9631L22 0V5.32334C22 6.4105 22.949 7.27273 24.1042 7.27273Z" fill="#646464"/>
<path d="M16.9562 22.3485H12.9746V17.803H10.9839L14.9654 14.1667L18.947 17.803H16.9562V22.3485Z" fill="#646464"/>
<path d="M20.9378 23.7121C20.9378 24.1666 20.4401 24.6212 19.9424 24.6212H9.98848C9.49078 24.6212 8.99309 24.1666 8.99309 23.7121V22.3485C8.99309 21.8939 9.49078 21.4394 9.98848 21.4394H10.9839V20.0757H9.49078C8.49539 20.0757 7.5 20.9848 7.5 21.8939V24.1666C7.5 25.0757 8.61982 25.9848 9.49078 25.9848H20.4401C21.3111 25.9848 22.4309 25.0757 22.4309 24.1666V21.8939C22.4309 20.9848 21.4355 20.0757 20.4401 20.0757H18.947V21.4394H19.9424C20.4401 21.4394 20.9378 21.8939 20.9378 22.3485V23.7121Z" fill="#646464"/>
</svg>

After

Width:  |  Height:  |  Size: 992 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 744 B

View File

@ -0,0 +1,12 @@
<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 0H22.9167L30 7.08333V37C30 38.6569 28.6569 40 27 40H3C1.34315 40 0 38.6569 0 37V3Z" fill="#78A73B"/>
<path d="M22.9167 0L30.0001 7.08333H25.9168C24.2599 7.08333 22.9167 5.74019 22.9167 4.08333V0Z" fill="#5A7D2B"/>
<path d="M6.17644 15.2941H23.8235V16.4706H6.17644V15.2941Z" fill="white"/>
<path d="M6.17644 19.1177H23.8235V20.2941H6.17644V19.1177Z" fill="white"/>
<path d="M6.17644 22.9412H23.8235V24.1177H6.17644V22.9412Z" fill="white"/>
<path d="M6.17644 26.7647H23.8235V27.9412H6.17644V26.7647Z" fill="white"/>
<path d="M5.88232 27.9412L5.88232 15.2941L7.0588 15.2941L7.0588 27.9412H5.88232Z" fill="white"/>
<path d="M11.4706 27.9412L11.4706 15.2941L12.647 15.2941V27.9412H11.4706Z" fill="white"/>
<path d="M17.0588 27.9412L17.0588 15.2941L18.2353 15.2941V27.9412H17.0588Z" fill="white"/>
<path d="M22.647 27.9412V15.2941H23.8235V27.9412H22.647Z" fill="white"/>
</svg>

After

Width:  |  Height:  |  Size: 1004 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

View File

@ -0,0 +1,12 @@
<svg width="17" height="16" viewBox="0 0 17 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M2.84616 1H10.8462L14.8462 5V15H2.84616V1Z" fill="white"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M14.8462 5L10.8462 1H2.84616V15H14.8462V5ZM10.8462 0L15.8462 5V16H1.84616V0H10.8462Z" fill="#BFBFBF"/>
<rect x="3.84616" y="10" width="10" height="4" fill="#3779A6"/>
<path d="M3.84616 4H4.84616V5H3.84616V4Z" fill="#BFBFBF"/>
<path d="M3.84616 6H4.84616V7H3.84616V6Z" fill="#BFBFBF"/>
<path d="M4.84616 8H3.84616V9H4.84616V8Z" fill="#BFBFBF"/>
<path d="M12.8462 8H5.84616V9H12.8462V8Z" fill="#BFBFBF"/>
<path d="M7.84616 6H5.84616V7H7.84616V6Z" fill="#BFBFBF"/>
<path d="M12.8462 4H5.84616V5H12.8462V4Z" fill="#BFBFBF"/>
<path opacity="0.3" d="M9.84616 1H10.8462V4H14.8462L15.8462 5H9.84616V1Z" fill="#333333"/>
</svg>

After

Width:  |  Height:  |  Size: 832 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

View File

@ -0,0 +1,12 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M2 1H10L14 5V15H2V1Z" fill="white"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M14 5L10 1H2V15H14V5ZM10 0L15 5V16H1V0H10Z" fill="#BFBFBF"/>
<rect x="3" y="10" width="10" height="4" fill="#F36700"/>
<path d="M3 4H4V5H3V4Z" fill="#BFBFBF"/>
<path d="M3 6H4V7H3V6Z" fill="#BFBFBF"/>
<path d="M4 8H3V9H4V8Z" fill="#BFBFBF"/>
<path d="M12 8H5V9H12V8Z" fill="#BFBFBF"/>
<path d="M7 6H5V7H7V6Z" fill="#BFBFBF"/>
<path d="M12 4H5V5H12V4Z" fill="#BFBFBF"/>
<path opacity="0.3" d="M9 1H10V4H14L15 5H9V1Z" fill="#333333"/>
</svg>

After

Width:  |  Height:  |  Size: 631 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

View File

@ -0,0 +1,12 @@
<svg width="17" height="16" viewBox="0 0 17 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M2.84592 1H10.8459L14.8459 5V15H2.84592V1Z" fill="white"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M14.8459 5L10.8459 1H2.84592V15H14.8459V5ZM10.8459 0L15.8459 5V16H1.84592V0H10.8459Z" fill="#BFBFBF"/>
<rect x="3.84592" y="10" width="10" height="4" fill="#78A73B"/>
<path d="M3.84592 4H4.84592V5H3.84592V4Z" fill="#BFBFBF"/>
<path d="M3.84592 6H4.84592V7H3.84592V6Z" fill="#BFBFBF"/>
<path d="M4.84592 8H3.84592V9H4.84592V8Z" fill="#BFBFBF"/>
<path d="M12.8459 8H5.84592V9H12.8459V8Z" fill="#BFBFBF"/>
<path d="M7.84592 6H5.84592V7H7.84592V6Z" fill="#BFBFBF"/>
<path d="M12.8459 4H5.84592V5H12.8459V4Z" fill="#BFBFBF"/>
<path opacity="0.3" d="M9.84592 1H10.8459V4H14.8459L15.8459 5H9.84592V1Z" fill="#333333"/>
</svg>

After

Width:  |  Height:  |  Size: 832 B

View File

@ -0,0 +1,3 @@
<svg width="12" height="12" viewBox="0 0 12 12" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M6 12C9.31371 12 12 9.31371 12 6C12 2.68629 9.31371 0 6 0C2.68629 0 0 2.68629 0 6C0 9.31371 2.68629 12 6 12ZM5 6C5 5.44772 5.44772 5 6 5C6.55228 5 7 5.44772 7 6V9C7 9.55229 6.55228 10 6 10C5.44772 10 5 9.55229 5 9V6ZM6 2C5.44772 2 5 2.44772 5 3C5 3.55228 5.44772 4 6 4C6.55228 4 7 3.55228 7 3C7 2.44772 6.55228 2 6 2Z" fill="#D0D5DA"/>
</svg>

After

Width:  |  Height:  |  Size: 488 B

View File

@ -1,15 +1,15 @@
<svg width="248" height="53" viewBox="0 0 248 53" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M24.9111 46.0096L7.13565 37.771C5.62145 37.0517 5.62145 35.9401 7.13565 35.2863L13.3241 32.4093L24.8453 37.771C26.3595 38.4902 28.7954 38.4902 30.2437 37.771L41.7648 32.4093L47.9533 35.2863C49.4675 36.0055 49.4675 37.1171 47.9533 37.771L30.1779 46.0096C28.7954 46.6635 26.3595 46.6635 24.9111 46.0096Z" fill="#FF6F3D"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M24.9111 35.8748L7.13565 27.6361C5.62145 26.9169 5.62145 25.8053 7.13565 25.1514L13.1925 22.3398L24.9111 27.7669C26.4253 28.4861 28.8612 28.4861 30.3096 27.7669L42.0282 22.3398L48.085 25.1514C49.5992 25.8707 49.5992 26.9823 48.085 27.6361L30.3096 35.8748C28.7953 36.594 26.3595 36.594 24.9111 35.8748Z" fill="#95C038"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M24.9111 26.0014L7.13565 17.7628C5.62145 17.0435 5.62145 15.9319 7.13565 15.2781L24.9111 7.03944C26.4253 6.32019 28.8612 6.32019 30.3096 7.03944L48.085 15.2781C49.5992 15.9973 49.5992 17.1089 48.085 17.7628L30.3096 26.0014C28.7953 26.6553 26.3595 26.6553 24.9111 26.0014Z" fill="#5DC0E8"/>
<path d="M60.085 26.4189C60.085 23.0116 61.0651 20.44 63.0906 18.7685C65.0509 17.0327 67.4031 16.197 70.0821 16.197C72.7611 16.197 75.048 17.0327 77.0083 18.7685C78.9685 20.5043 79.9486 23.0116 79.9486 26.4832C79.9486 29.8906 78.9685 32.4621 77.0083 34.1336C75.048 35.8695 72.6958 36.7052 70.0821 36.7052C67.4031 36.7052 65.1162 35.8695 63.0906 34.1336C61.0651 32.3978 60.085 29.8263 60.085 26.4189ZM64.3975 26.4189C64.3975 28.7976 64.8548 30.4692 65.7043 31.5621C66.619 32.655 67.5992 33.3622 68.6446 33.6193C68.906 33.6836 69.102 33.7479 69.3634 33.7479C69.5594 33.7479 69.8208 33.8122 70.0168 33.8122C70.2781 33.8122 70.4742 33.8122 70.7355 33.7479C70.9969 33.7479 71.1929 33.6836 71.4543 33.6193C72.4997 33.3622 73.4798 32.655 74.3293 31.5621C75.1787 30.4692 75.6361 28.7334 75.6361 26.4832C75.6361 24.1688 75.1787 22.4973 74.3293 21.4044C73.4798 20.3115 72.4997 19.6043 71.4543 19.3471C71.1929 19.2828 70.9315 19.2186 70.7355 19.2186C70.4742 19.2186 70.2781 19.1543 70.0168 19.1543C69.7554 19.1543 69.5594 19.1543 69.3634 19.2186C69.1673 19.2186 68.906 19.2828 68.6446 19.3471C67.5992 19.6043 66.619 20.3115 65.7043 21.4044C64.8548 22.3687 64.3975 24.1045 64.3975 26.4189Z" fill="white"/>
<path d="M82.105 16.3898H87.4629L94.5198 28.9905L95.5652 31.755H95.6306L95.5652 28.1548V16.3898H99.6817V36.4481H94.3237L87.2669 23.3331L86.2215 21.0829H86.1561L86.2215 24.6188V36.4481H82.105V16.3898Z" fill="white"/>
<path d="M103.929 16.3898H108.045V33.0407H116.147V36.4481H103.929V16.3898Z" fill="white"/>
<path d="M113.599 16.3898H118.369L122.551 23.3974L123.204 24.8117H123.335L123.988 23.3974L128.235 16.3898H132.613L125.23 28.2833V36.4481H121.113V28.219L113.599 16.3898Z" fill="white"/>
<path d="M132.091 26.4189C132.091 23.0116 133.071 20.44 135.096 18.7685C137.057 17.0327 139.409 16.197 142.088 16.197C144.767 16.197 147.054 17.0327 149.014 18.7685C150.974 20.5043 151.954 23.0116 151.954 26.4832C151.954 29.8906 150.974 32.4621 149.014 34.1336C147.054 35.8695 144.702 36.7052 142.088 36.7052C139.409 36.7052 137.122 35.8695 135.096 34.1336C133.136 32.3978 132.091 29.8263 132.091 26.4189ZM136.403 26.4189C136.403 28.7976 136.861 30.4692 137.71 31.5621C138.625 32.655 139.54 33.3622 140.65 33.6193C140.912 33.6836 141.108 33.7479 141.369 33.7479C141.565 33.7479 141.827 33.8122 142.023 33.8122C142.284 33.8122 142.48 33.8122 142.741 33.7479C143.003 33.7479 143.199 33.6836 143.46 33.6193C144.506 33.3622 145.486 32.655 146.335 31.5621C147.185 30.4692 147.642 28.7334 147.642 26.4832C147.642 24.1688 147.185 22.4973 146.335 21.4044C145.486 20.3115 144.506 19.6043 143.46 19.3471C143.199 19.2828 142.937 19.2186 142.741 19.2186C142.48 19.2186 142.284 19.1543 142.023 19.1543C141.761 19.1543 141.565 19.1543 141.369 19.2186C141.173 19.2186 140.912 19.2828 140.65 19.3471C139.605 19.6043 138.625 20.3115 137.71 21.4044C136.861 22.3687 136.403 24.1045 136.403 26.4189Z" fill="white"/>
<path d="M154.829 16.3898H166.198V19.7329H158.946V24.6188H165.872V28.0262H158.946V36.4481H154.829V16.3898Z" fill="white"/>
<path d="M169.27 16.3898H180.639V19.7329H173.386V24.6188H180.312V28.0262H173.386V36.4481H169.27V16.3898Z" fill="white"/>
<path d="M183.057 36.4481V16.3898H187.173V36.4481H183.057Z" fill="white"/>
<path d="M205.311 16.8397V20.3113C204.592 20.0542 203.873 19.8613 203.089 19.7327C202.305 19.6041 201.39 19.5398 200.476 19.5398C198.319 19.5398 196.686 20.1827 195.51 21.5328C194.334 22.8186 193.746 24.4901 193.746 26.4831C193.746 28.4117 194.268 30.019 195.379 31.3048C196.49 32.5905 198.058 33.2977 200.084 33.2977C200.802 33.2977 201.521 33.2334 202.371 33.1692C203.22 33.0406 204.069 32.8477 204.984 32.462L205.246 35.8693C205.115 35.9336 204.919 35.9979 204.723 36.0622C204.462 36.1265 204.2 36.1907 203.873 36.255C203.351 36.3836 202.697 36.4479 201.913 36.5765C201.129 36.6408 200.345 36.7051 199.496 36.7051C199.365 36.7051 199.234 36.7051 199.169 36.7051C199.038 36.7051 198.908 36.7051 198.842 36.7051C196.49 36.5765 194.334 35.6764 192.373 34.1335C190.413 32.5263 189.433 30.019 189.433 26.6759C189.433 23.3972 190.413 20.8256 192.308 19.0255C194.203 17.2254 196.817 16.3254 200.018 16.3254C200.868 16.3254 201.652 16.3254 202.305 16.3897C203.024 16.454 203.677 16.5825 204.396 16.7111C204.527 16.7754 204.723 16.7754 204.854 16.8397C204.984 16.7754 205.115 16.8397 205.311 16.8397Z" fill="white"/>
<path d="M208.578 16.3899H220.797V19.5401H212.76V24.5546H220.013V27.6405H212.76V33.298H220.797V36.4481H208.578V16.3899Z" fill="white"/>
<svg width="153" height="28" viewBox="0 0 153 28" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M13.3403 27.6567L0.801116 21.8897C-0.267039 21.3862 -0.267039 20.6081 0.801116 20.1504L5.16662 18.1365L13.2939 21.8897C14.362 22.3932 16.0804 22.3932 17.1021 21.8897L25.2294 18.1365L29.5949 20.1504C30.663 20.6539 30.663 21.432 29.5949 21.8897L17.0556 27.6567C16.0804 28.1144 14.362 28.1144 13.3403 27.6567Z" fill="#FF6F3D"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M13.3403 20.5623L0.801116 14.7953C-0.267039 14.2918 -0.267039 13.5137 0.801116 13.056L5.07373 11.0879L13.3403 14.8868C14.4085 15.3903 16.1268 15.3903 17.1485 14.8868L25.4151 11.0879L29.6877 13.056C30.7559 13.5595 30.7559 14.3376 29.6877 14.7953L17.1485 20.5623C16.0804 21.0658 14.362 21.0658 13.3403 20.5623Z" fill="#95C038"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M13.3403 13.651L0.801116 7.88393C-0.267039 7.38045 -0.267039 6.60236 0.801116 6.14466L13.3403 0.377605C14.4085 -0.125868 16.1268 -0.125868 17.1485 0.377605L29.6877 6.14466C30.7559 6.64813 30.7559 7.42622 29.6877 7.88393L17.1485 13.651C16.0804 14.1087 14.362 14.1087 13.3403 13.651Z" fill="#5DC0E8"/>
<path d="M38.1528 13.9433C38.1528 11.5581 38.8442 9.75803 40.2731 8.58797C41.6559 7.3729 43.3152 6.78787 45.2051 6.78787C47.0949 6.78787 48.7081 7.3729 50.0909 8.58797C51.4737 9.80304 52.1651 11.5581 52.1651 13.9883C52.1651 16.3734 51.4737 18.1735 50.0909 19.3436C48.7081 20.5586 47.0488 21.1437 45.2051 21.1437C43.3152 21.1437 41.702 20.5586 40.2731 19.3436C38.8442 18.1285 38.1528 16.3284 38.1528 13.9433ZM41.195 13.9433C41.195 15.6084 41.5176 16.7784 42.1168 17.5435C42.7621 18.3085 43.4535 18.8035 44.191 18.9835C44.3754 19.0285 44.5137 19.0735 44.698 19.0735C44.8363 19.0735 45.0207 19.1185 45.159 19.1185C45.3433 19.1185 45.4816 19.1185 45.666 19.0735C45.8504 19.0735 45.9886 19.0285 46.173 18.9835C46.9105 18.8035 47.6019 18.3085 48.2011 17.5435C48.8003 16.7784 49.123 15.5633 49.123 13.9883C49.123 12.3682 48.8003 11.1981 48.2011 10.4331C47.6019 9.66803 46.9105 9.173 46.173 8.99299C45.9886 8.94799 45.8043 8.90299 45.666 8.90299C45.4816 8.90299 45.3433 8.85798 45.159 8.85798C44.9746 8.85798 44.8363 8.85798 44.698 8.90299C44.5598 8.90299 44.3754 8.94799 44.191 8.99299C43.4535 9.173 42.7621 9.66803 42.1168 10.4331C41.5176 11.1081 41.195 12.3232 41.195 13.9433Z" fill="white"/>
<path d="M53.6863 6.92288H57.4659L62.444 15.7434L63.1814 17.6785H63.2275L63.1814 15.1583V6.92288H66.0853V20.9636H62.3057L57.3276 11.7831L56.5901 10.2081H56.544L56.5901 12.6832V20.9636H53.6863V6.92288Z" fill="white"/>
<path d="M69.0813 6.92288H71.9852V18.5785H77.7007V20.9636H69.0813V6.92288Z" fill="white"/>
<path d="M75.9031 6.92288H79.2679L82.2178 11.8281L82.6787 12.8182H82.7709L83.2319 11.8281L86.2279 6.92288H89.3161L84.1076 15.2483V20.9636H81.2038V15.2033L75.9031 6.92288Z" fill="white"/>
<path d="M88.9473 13.9433C88.9473 11.5581 89.6387 9.75803 91.0675 8.58797C92.4503 7.3729 94.1097 6.78787 95.9995 6.78787C97.8893 6.78787 99.5026 7.3729 100.885 8.58797C102.268 9.80304 102.96 11.5581 102.96 13.9883C102.96 16.3734 102.268 18.1735 100.885 19.3436C99.5026 20.5586 97.8432 21.1437 95.9995 21.1437C94.1097 21.1437 92.4964 20.5586 91.0675 19.3436C89.6848 18.1285 88.9473 16.3284 88.9473 13.9433ZM91.9894 13.9433C91.9894 15.6084 92.3121 16.7784 92.9113 17.5435C93.5566 18.3085 94.2019 18.8035 94.9855 18.9835C95.1698 19.0285 95.3081 19.0735 95.4925 19.0735C95.6308 19.0735 95.8151 19.1185 95.9534 19.1185C96.1378 19.1185 96.2761 19.1185 96.4604 19.0735C96.6448 19.0735 96.7831 19.0285 96.9675 18.9835C97.7049 18.8035 98.3963 18.3085 98.9955 17.5435C99.5948 16.7784 99.9174 15.5633 99.9174 13.9883C99.9174 12.3682 99.5948 11.1981 98.9955 10.4331C98.3963 9.66803 97.7049 9.173 96.9675 8.99299C96.7831 8.94799 96.5987 8.90299 96.4604 8.90299C96.2761 8.90299 96.1378 8.85798 95.9534 8.85798C95.769 8.85798 95.6308 8.85798 95.4925 8.90299C95.3542 8.90299 95.1698 8.94799 94.9855 8.99299C94.248 9.173 93.5566 9.66803 92.9113 10.4331C92.3121 11.1081 91.9894 12.3232 91.9894 13.9433Z" fill="white"/>
<path d="M104.988 6.92288H113.008V9.26301H107.891V12.6832H112.777V15.0683H107.891V20.9636H104.988V6.92288Z" fill="white"/>
<path d="M115.174 6.92288H123.195V9.26301H118.078V12.6832H122.964V15.0683H118.078V20.9636H115.174V6.92288Z" fill="white"/>
<path d="M124.9 20.9636V6.92288H127.804V20.9636H124.9Z" fill="white"/>
<path d="M140.599 7.2378V9.66793C140.092 9.48792 139.585 9.35291 139.032 9.26291C138.478 9.1729 137.833 9.1279 137.188 9.1279C135.667 9.1279 134.515 9.57792 133.685 10.523C132.855 11.423 132.44 12.5931 132.44 13.9882C132.44 15.3382 132.809 16.4633 133.593 17.3633C134.376 18.2634 135.482 18.7584 136.911 18.7584C137.418 18.7584 137.925 18.7134 138.525 18.6684C139.124 18.5784 139.723 18.4434 140.368 18.1734L140.553 20.5585C140.46 20.6035 140.322 20.6485 140.184 20.6935C140 20.7385 139.815 20.7835 139.585 20.8285C139.216 20.9185 138.755 20.9635 138.202 21.0535C137.649 21.0985 137.096 21.1436 136.497 21.1436C136.404 21.1436 136.312 21.1436 136.266 21.1436C136.174 21.1436 136.082 21.1436 136.036 21.1436C134.376 21.0535 132.855 20.4235 131.472 19.3435C130.09 18.2184 129.398 16.4633 129.398 14.1232C129.398 11.828 130.09 10.0279 131.426 8.76788C132.763 7.50781 134.607 6.87778 136.865 6.87778C137.464 6.87778 138.018 6.87778 138.478 6.92278C138.986 6.96778 139.446 7.05779 139.953 7.14779C140.046 7.19279 140.184 7.19279 140.276 7.2378C140.368 7.19279 140.46 7.2378 140.599 7.2378Z" fill="white"/>
<path d="M142.903 6.92294H151.523V9.12806H145.853V12.6383H150.97V14.7984H145.853V18.7586H151.523V20.9637H142.903V6.92294Z" fill="white"/>
</svg>

Before

Width:  |  Height:  |  Size: 5.5 KiB

After

Width:  |  Height:  |  Size: 5.5 KiB

View File

@ -0,0 +1,5 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<g opacity="0.3">
<path d="M10.3826 15.3872C9.9926 15.7862 9.35162 15.7889 8.95828 15.3933L6.15133 12.5701C5.76034 12.1768 5.12403 12.1768 4.73304 12.5701L4.70185 12.6015C4.31371 12.9918 4.31409 13.6225 4.7027 14.0124L8.95904 18.2831C9.35223 18.6776 9.99196 18.6749 10.3817 18.277L20.3062 8.14519C20.6903 7.75301 20.6865 7.12447 20.2976 6.73701L20.273 6.71257C19.8791 6.32014 19.2408 6.32437 18.8521 6.722L10.3826 15.3872Z" fill="#444444"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 549 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

View File

@ -1,6 +1,6 @@
/**
*
* (c) Copyright Ascensio System SIA 2020
* (c) Copyright Ascensio System SIA 2021
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -16,354 +16,455 @@
*
*/
html {
html {
height: 100%;
width: 100%;
}
body {
background: #fff;
color: #333;
font-family: 'Open Sans', sans-serif;
background: #FFFFFF;
color: #333333;
font-family: Open Sans;
font-size: 12px;
font-style: normal;
font-weight: normal;
height: 100%;
margin: 0;
overflow-y: overlay;
padding: 0;
text-decoration: none;
}
form {
height: 100%;
}
div {
margin: 0;
padding: 0;
}
a, a:hover, a:visited {
color: #333;
a,
a:hover,
a:visited {
color: #333333;
cursor: pointer;
}
header {
background: #333333;
height: 72px;
margin: 0 auto;
min-width: 1152px;
width: auto;
}
.top-panel {
background: #3D4A6B;
height: 80px;
width: 100%;
header img {
margin: 22px 0 22px 32px;
}
.top-panel img {
margin: 12px 0 0 16px;
.center {
margin: 0 auto 0;
width: 1152px;
}
.main {
height: calc(100% - 136px);
min-height: 536px;
}
.table-main {
border-spacing: 0;
height: 100%;
min-height: 536px;
}
.section {
height: 100%;
padding: 0;
vertical-align: top;
}
.main-panel {
margin: 80px auto;
width: 600px;
box-sizing: border-box;
-moz-box-sizing: border-box;
height: 100%;
list-style: none;
padding: 48px 32px 24px;
position: relative;
width: 896px;
}
.portal-name {
font-size: 20px;
color: #FF6F3D;
font-size: 24px;
font-weight: bold;
line-height: 133%;
letter-spacing: -0.02em;
}
.portal-descr {
display: inline-block;
line-height: 20px;
margin-bottom: 24px;
width: 600px;
}
.save-original {
color: #929597;
line-height: 20px;
margin-left: 16px;
white-space: nowrap;
width: 272px;
}
label .checkbox {
vertical-align: middle;
}
.question {
background: url("images/question_small.png") no-repeat center center transparent;
cursor: pointer;
display: inline-block;
height: 16px;
width: 16px;
}
#hint {
background-color: #FFFFFF;
border: 1px solid #8E908F;
display: none;
margin: 4px 0 0 -32px;
max-width: 415px;
padding: 10px 15px 15px;
word-wrap: break-word;
z-index: 255;
}
.corner {
background: url("images/corner.png") no-repeat scroll 0 0 transparent;
height: 6px;
left: 35px;
margin-top: -15px;
position: absolute;
width: 9px;
z-index: 261;
}
.try-descr {
font-size: 16px;
white-space : nowrap;
line-height: 160%;
margin-top: 16px;
}
.header-list {
font-weight: bold;
font-size: 16px;
line-height: 133%;
letter-spacing: -0.02em;
}
label .checkbox {
margin: 0 5px 3px 0;
vertical-align: middle;
}
.try-editor-list {
list-style: none;
margin: 0 0 16px;
margin: 0;
padding: 0;
}
.try-editor-list li {
float: left;
margin: 0 15px;
width: 100px;
cursor: pointer;
}
.try-editor-list li {
margin-bottom: 12px
}
.try-editor {
background-color: transparent;
background-position: center 0;
background-repeat: no-repeat;
display: block;
font-size: 14px;
font-weight: bold;
height: 45px;
padding-top: 100px;
text-align: center;
line-height: 40px;
padding-left: 42px;
text-decoration: none;
}
.try-editor.word {
background-image: url("images/file_docx.png");
background-image: url("images/file_docx.svg");
}
.try-editor.cell {
background-image: url("images/file_xlsx.png");
background-image: url("images/file_xlsx.svg");
}
.try-editor.slide {
background-image: url("images/file_pptx.png");
background-image: url("images/file_pptx.svg");
}
.create-sample {
display: inline-block;
margin-left: 75px;
color: #666666;
line-height: 24px;
}
.button, .button:visited, .button:hover, .button:active {
.button,
.button:visited,
.button:hover,
.button:active {
align-items: center;
border-radius: 3px;
box-sizing: border-box;
cursor: pointer;
display: inline-block;
font-weight: normal;
font-weight: 600;
letter-spacing: 0.08em;
line-height: 133%;
padding: 8px 20px;
text-align: center;
text-decoration: none;
vertical-align: middle;
cursor:pointer;
border-radius: 3px;
-moz-border-radius: 3px;
-webkit-border-radius: 3px;
touch-callout: none;
text-transform: uppercase;
vertical-align: middle;
user-select: none;
-o-touch-callout: none;
-moz-touch-callout: none;
-webkit-touch-callout: none;
user-select: none;
-o-user-select: none;
-moz-user-select: none;
-webkit-user-select: none;
font-size: 12px;
line-height: 16px;
margin-right: 3px;
padding: 4px 12px;
color: #fff;
background: #3D96C6;
border-width: 1px;
border-style: solid;
border-color: #3D96C6;
}
.button.disable {
.button.orange {
background: #FF6F3D;
border: 1px solid #FF6F3D;
color: #FFFFFF;
}
.button.orange.disable {
background: #EDC2B3;
border: 1px solid #EDC2B3;
cursor: default;
background: #BADDEF;
border: 1px solid #BADDEF;
}
.button.orange:not(.disable):hover {
background: #ff7a4b;
}
.button.gray {
background: #888;
border: 1px solid #E9EAEA;
border: 1px solid #AAAAAA;
margin-left: 8px;
}
.button.gray.disable {
border: 1px solid #E5E5E5;
color: #B5B5B5;
cursor: default;
}
.button.gray:not(.disable):hover {
border: 1px solid #FF6F3D;
color: #FF6F3D;
}
.upload-panel {
border-right: 1px solid #D1D1D1;
float: left;
margin-right: 25px;
padding: 24px 0;
}
.file-upload {
background: url("images/file_upload.png") no-repeat center 0 transparent;
background: url("images/file_upload.svg") no-repeat 0 transparent;
cursor: pointer;
display: inline-block;
display: block;
font-size: 14px;
font-weight: bold;
height: 45px;
margin: 0 40px 16px;
line-height: 40px;
overflow: hidden;
padding-top: 100px;
padding-left: 42px;
position: relative;
text-align: center;
width: 100px;
width: 150px;
}
.file-upload input {
cursor: pointer;
opacity: 0;
position: absolute;
right: 0;
top: 0;
transform: translate(555px, 60px) scale(8);
}
.file-upload input {
cursor: pointer;
height: 40px;
margin: 0;
opacity: 0;
opacity: 0;
position: absolute;
right: 0;
top: 0;
transform: translate(0px, -21px) scale(2);
width: 192px;
}
.create-panel {
float: left;
padding: 16px 0;
}
.upload-panel,
.create-panel {
padding: 10px 0;
width: 100%;
border-bottom: 1px solid #D0D5DA;
}
#mainProgress {
color: #979b9f;
color: #333333;
display: none;
margin: 15px;
font-size: 12px;
margin: 30px 40px;
}
#mainProgress .uploadFileName {
background-position: left center;
background-repeat: no-repeat;
display: block;
font-size: 14px;
line-height: 160%;
overflow: hidden;
padding-left: 28px;
text-overflow: ellipsis;
white-space: nowrap;
}
#mainProgress .describeUpload {
line-height: 150%;
letter-spacing: -0.02em;
padding: 16px 0;
}
#mainProgress #embeddedView {
display: none;
}
#mainProgress.embedded #embeddedView {
display: block;
}
#mainProgress.embedded #uploadSteps {
display: none;
}
.error-message {
background: url("images/alert.png") no-repeat scroll 4px 10px #FFECE3;
color: #666668 !important;
background: url("images/error.svg") no-repeat scroll 4px 10px;
color: #CB0000;
display: none;
font-size: 13px;
font-weight: normal;
line-height: 160%;
letter-spacing: -0.02em;
margin: 5px 0;
padding: 10px 10px 10px 30px;
vertical-align: middle;
word-wrap: break-word;
}
#mainProgress .error-message a {
color: #666668;
}
.step {
background-repeat: no-repeat;
background-position: left center;
background-color: transparent;
color: #979B9F;
font-size: 14px;
line-height: 30px;
padding-left: 25px;
font-weight: bold;
line-height: 167%;
padding-left: 35px;
}
.current {
background-image: url("images/loader16.gif");
color: #333;
}
.done {
background-image: url("images/done.png");
color: #333;
background-image: url("images/done.svg");
}
.error {
background-image: url("images/alert.png");
background-image: url("images/notdone.svg");
}
.step-descr {
display: block;
margin-left: 45px;
}
#mainProgress .step-descr a {
color: #979B9F;
margin-left: 35px;
font-size: 11px;
line-height: 188%;
}
.progress-descr {
color: #333;
letter-spacing: -0.02em;
line-height: 150%;
}
#loadScripts {
display: none;
}
#iframeScripts {
position: absolute;
visibility: hidden;
}
.bottom-panel {
bottom: 0;
position: fixed;
text-align: right;
width: 100%;
footer {
background: #333333;
color: #AAAAAA;
height: 64px;
min-width: 1152px;
width: auto;
}
footer table {
border-spacing: 0;
}
footer table tr {
height: 64px;
}
footer table td {
padding-left: 32px;
}
footer a,
footer a:hover,
footer a:visited {
color: #FF6F3D;
font-size: 14px;
line-height: 120%;
}
footer a:hover {
text-decoration: none;
}
.copy {
padding-left: 510px;
}
.help-block {
margin: 48px 32px 24px;
}
.help-block span {
font-size: 16px;
line-height: 26px;
font-size: 14px;
font-weight: 600;
line-height: 19px;
}
.stored-list {
border-top: 1px solid #D1D1D1;
list-style: none;
margin: 0;
padding: 0;
position: relative;
height: 100%;
}
.stored-list li {
border-bottom: 1px solid #D1D1D1;
line-height: 28px;
padding: 0 8px;
}
.stored-edit {
background-color: transparent;
background-position: left center;
background-repeat: no-repeat;
display: inline-block;
height: 16px;
max-width: 450px;
margin-bottom: -6px;
max-width: 250px;
overflow: hidden;
padding: 4px 0 1px 34px;
padding: 8px 0 1px 26px;
text-decoration: none;
text-overflow: ellipsis;
white-space: nowrap;
}
.stored-edit.word {
background-image: url("images/icon_docx.png");
.stored-edit.word,
.uploadFileName.word {
background-image: url("images/icon_docx.svg");
}
.stored-edit.cell {
background-image: url("images/icon_xlsx.png");
.stored-edit.cell,
.uploadFileName.cell {
background-image: url("images/icon_xlsx.svg");
}
.stored-edit.slide {
background-image: url("images/icon_pptx.png");
.stored-edit.slide,
.uploadFileName.slide {
background-image: url("images/icon_pptx.svg");
}
.stored-edit span {
font-size: 12px;
line-height: 12px;
}
.stored-edit:hover span {
text-decoration: underline;
}
.blockTitle {
background-color: #E2E2E2 !important;
background-color: #333333 !important;
border: none !important;
border-radius: 0 !important;
-moz-border-radius: 0 !important;
-webkit-border-radius: 0 !important;
color: #333 !important;
color: #F5F5F5 !important;
font-size: 16px !important;
font-weight: normal !important;
padding: 15px 25px !important;
font-weight: 600 !important;
line-height: 133%;
letter-spacing: -0.02em;
padding: 14px 16px 14px 46px !important;
}
.dialog-close {
background: url("images/close.png") no-repeat scroll left top #E2E2E2;
background: url("images/close.svg") no-repeat scroll left top;
cursor: pointer;
float: right;
font-size: 1px;
height: 12px;
height: 14px;
line-height: 1px;
margin-top: 4px;
width: 12px;
width: 14px;
}
.blockPage {
border: none !important;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.5);
@ -381,11 +482,6 @@ label .checkbox {
visibility: hidden;
}
/*Icon table*/
#tableRow {
vertical-align: top;
}
.tableRow {
background: transparent;
-moz-transition: all 0.2s ease-in-out;
@ -395,16 +491,17 @@ label .checkbox {
transition: all 0.2s ease-in-out;
}
.tableRow:hover {
background-color: #ebebeb;
}
.tableRow:hover {
background-color: #ECECEC;
}
.tableHeader {
padding-top: 10px;
}
.tableHeader tr {
background: transparent;
color: #333;
cursor: default;
font-family: 'Open Sans', sans-serif;
font-size: 13px;
height: 40px;
-khtml-user-select: none;
user-select: none;
@ -413,19 +510,39 @@ label .checkbox {
}
.tableHeaderCell {
padding: 2px 1px 2px 5px;
border-bottom: 1px solid #CCCCCC;
padding: 2px 4px;
text-align: center;
}
.tableHeaderCellFileName {
text-align: left;
width: 37%;
}
.tableHeaderCellEditors {
width: 29%;
}
.tableHeaderCellViewers {
width: 11%;
}
.tableHeaderCellDownload {
width: 13%;
text-align: right;
padding-right: 20px;
}
.tableHeaderCellRemove {
text-align: left;
}
.contentCells {
padding: 4px 1px 4px 5px;
border-bottom: 1px solid #EFEFEF;
font-family: 'Open Sans', sans-serif;
font-size: 16px;
border-bottom: 1px solid #e5e5e5;
padding: 4px;
white-space: nowrap;
-khtml-user-select: none;
user-select: none;
@ -433,59 +550,134 @@ label .checkbox {
-webkit-user-select: none;
}
.contentCells a {
text-decoration: none;
}
.contentCells-shift {
padding-right: 30px;
}
.contentCells-shift {
padding-right: 44px;
}
.contentCells-icon {
width: 6%;
}
.contentCellsSmall {
padding: 5px 1px 5px 6px;
font-family: 'Open Sans', sans-serif;
font-size: 13px;
border-bottom: 1px solid #e5e5e5;
white-space: nowrap;
text-align: center;
}
.primaryRow {
background-color: #e9e9e9;
}
.secondaryRow {
background-color: #F9F9F9;
width: 4%;
}
.select-user {
margin-left: 15px;
color: #444444;
font-family: Open Sans;
font-size: 12px !important;
font-weight: normal !important;
line-height: 16px !important;
}
.info {
cursor: pointer;
padding: 3px 5px;
position: absolute;
}
.tooltip {
background: #FFFFFF;
border-radius: 5px;
box-shadow: 0px 7px 25px rgba(85, 85, 85, 0.15);
color: #666666;
line-height: 160%;
max-width: 455px;
padding: 14px;
position: absolute;
}
.tooltip ul {
margin: 0;
}
.arrow {
border-top: 8px solid transparent;
border-bottom: 8px solid transparent;
border-right: 8px solid #FFFFFF;
position: absolute;
transform: translate(-50%, -50%);
}
.user-block-table {
height: 100%;
padding-top: 14px;
width: 100%;
}
.user-block-table td {
background-color: #F4F4F4;
border-bottom: 1px solid white;
padding: 12px 0;
}
#user, #language {
width: 130px;
.user-block-table td {
background-color: #F4F4F4;
padding-top: 10px;
}
.icon-download {
margin-bottom: -5px;
.user-block-table td select {
border: 1px solid #D0D5DA;
box-sizing: border-box;
border-radius: 3px;
cursor: pointer;
margin-top: 5px;
padding: 2px 5px;
width: 100%;
}
.icon-delete {
cursor: pointer;
margin-bottom: -6px;
}
.left-panel {
width: 256px;
background: #F5F5F5;
}
.scroll-table-body {
bottom: 0;
left: 0;
margin-top: 0px;
overflow-x: auto;
position: absolute;
right: 0;
top: 71px;
scrollbar-color: #D0D5DA transparent;
scrollbar-width: thin;
}
.scroll-table-body::-webkit-scrollbar {
width: 4px;
}
.scroll-table-body::-webkit-scrollbar-thumb {
background: #D0D5DA;
border-radius: 3px;
}
.descrFilePass {
display: block;
font-weight: bold;
line-height: 167%;
}
#filePass {
border: 1px solid #D0D5DA;
border-radius: 3px;
box-sizing: border-box;
display: inline-block;
height: 33px;
letter-spacing: -0.02em;
line-height: 150%;
margin-right: 8px;
outline: none;
padding: 7px 8px;
vertical-align: bottom;
user-select: none;
-moz-user-select: none;
-webkit-user-select: none;
width: 250px;
}
.errorInput {
border-color: #CB0000 !important;
}
.errorPass {
color: #CB0000;
display: block;
line-height: 160%;
letter-spacing: -0.02em;
word-wrap: break-word;
}

View File

@ -1,8 +1,10 @@
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="OnlineEditorsExample._Default" Title="ONLYOFFICE" %>
<%@ Import Namespace="System.IO" %>
<%@ Import Namespace="System.Web.WebPages" %>
<%@ Import Namespace="System.Linq" %>
<%@ Import Namespace="System.Web.Configuration" %>
<%@ Import Namespace="OnlineEditorsExample" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
@ -12,7 +14,7 @@
<title>ONLYOFFICE</title>
<!--
*
* (c) Copyright Ascensio System SIA 2020
* (c) Copyright Ascensio System SIA 2021
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -35,300 +37,317 @@
<link rel="stylesheet" type="text/css" href="app_themes/jquery-ui.css" />
<script language="javascript" type="text/javascript" src="script/jquery-1.9.0.min.js"></script>
<script language="javascript" type="text/javascript" src="script/jquery-ui.min.js"></script>
<script language="javascript" type="text/javascript" src="script/jquery.blockUI.js"></script>
<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/jscript.js"></script>
<script language="javascript" type="text/javascript">
var ConverExtList = '<%= string.Join(",", ConvertExts.ToArray()) %>';
var EditedExtList = '<%= string.Join(",", EditedExts.ToArray()) %>';
</script>
</head>
<body>
<form id="form1" runat="server">
<div class="top-panel">
<a href="">
<img src ="app_themes/images/logo.svg" alt="ONLYOFFICE" />
</a>
</div>
<div class="main-panel">
<span class="portal-name">ONLYOFFICE Document Editors</span>
<br />
<br />
<span class="portal-descr">Get started with a demo-sample of ONLYOFFICE Document Editors, the first html5-based editors. You may upload your own documents for testing using the "Upload file" button and selecting the necessary files on your PC.</span>
<table class="user-block-table" cellspacing="0" cellpadding="0">
<header>
<div class="center">
<a href="">
<img src ="app_themes/images/logo.svg" alt="ONLYOFFICE" />
</a>
</div>
</header>
<div class="center main">
<table class="table-main">
<tbody>
<tr>
<td width="30%" valign="middle">
<span class="select-user">Username:</span>
<select class="select-user" id="user">
<option value="uid-1">John Smith</option>
<option value="uid-2">Mark Pottato</option>
<option value="uid-3">Hamish Mitchell</option>
<option value="uid-0">anonymous</option>
</select>
<td class="left-panel section">
<div class="help-block">
<span>Create new</span>
<div class="clearFix">
<div class="create-panel clearFix">
<ul class="try-editor-list clearFix">
<li>
<a class="try-editor word" data-type="word">Document</a>
</li>
<li>
<a class="try-editor cell" data-type="cell">Spreadsheet</a>
</li>
<li>
<a class="try-editor slide" data-type="slide">Presentation</a>
</li>
</ul>
<label class="create-sample">
<input id="createSample" class="checkbox" type="checkbox" />With sample content
</label>
</div>
<div class="upload-panel clearFix">
<a class="file-upload">Upload file
<input type="file" id="fileupload" name="files[]" data-url="webeditor.ashx?type=upload" />
</a>
</div>
</div>
<table class="user-block-table" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td valign="middle">
<span class="select-user">Username</span>
<img class="info" data-id="user" data-tooltip="You can open the same document using different users in different Web browser sessions, so you can check out multi-user editing functions.
</br>
<% foreach (User user in Users.getAllUsers())
{ %>
<b><%= user.name.IsEmpty() ? "Anonymous" : user.name %></b>
<ul>
<% foreach (string description in user.descriptions)
{ %>
<li><%= description %></li>
<% } %>
</ul>
<% } %>"
src="app_themes/images/info.svg" />
<select class="select-user" id="user">
<% foreach (User user in Users.getAllUsers())
{ %>
<option value="<%= user.id %>"><%= user.name.IsEmpty() ? "Anonymous" : user.name %></option>
<% } %>
</select>
</td>
</tr>
<tr>
<td valign="middle">
<span class="select-user">Language</span>
<img class="info" data-id="language" data-tooltip="Choose the language for ONLYOFFICE editors interface" src="app_themes/images/info.svg" />
<select class="select-user" id="language">
<option value="en">English</option>
<option value="be">Belarusian</option>
<option value="bg">Bulgarian</option>
<option value="ca">Catalan</option>
<option value="zh">Chinese</option>
<option value="cs">Czech</option>
<option value="da">Danish</option>
<option value="nl">Dutch</option>
<option value="fi">Finnish</option>
<option value="fr">French</option>
<option value="de">German</option>
<option value="el">Greek</option>
<option value="hu">Hungarian</option>
<option value="id">Indonesian</option>
<option value="it">Italian</option>
<option value="ja">Japanese</option>
<option value="ko">Korean</option>
<option value="lv">Latvian</option>
<option value="lo">Lao</option>
<option value="nb">Norwegian</option>
<option value="pl">Polish</option>
<option value="pt">Portuguese</option>
<option value="ro">Romanian</option>
<option value="ru">Russian</option>
<option value="sk">Slovak</option>
<option value="sl">Slovenian</option>
<option value="sv">Swedish</option>
<option value="es">Spanish</option>
<option value="tr">Turkish</option>
<option value="uk">Ukrainian</option>
<option value="vi">Vietnamese</option>
</select>
</td>
</tr>
</tbody>
</table>
</div>
</td>
<td width="70%" valign="middle">Select user name before opening the document; you can open the same document using different users in different Web browser sessions, so you can check out multi-user editing functions.</td>
</tr>
<tr>
<td width="30%" valign="middle">
<select class="select-user" id="language">
<option value="en">English</option>
<option value="be">Belarusian</option>
<option value="bg">Bulgarian</option>
<option value="ca">Catalan</option>
<option value="zh">Chinese</option>
<option value="cs">Czech</option>
<option value="da">Danish</option>
<option value="nl">Dutch</option>
<option value="fi">Finnish</option>
<option value="fr">French</option>
<option value="de">German</option>
<option value="el">Greek</option>
<option value="hu">Hungarian</option>
<option value="id">Indonesian</option>
<option value="it">Italian</option>
<option value="ja">Japanese</option>
<option value="ko">Korean</option>
<option value="lv">Latvian</option>
<option value="lo">Lao</option>
<option value="nb">Norwegian</option>
<option value="pl">Polish</option>
<option value="pt">Portuguese</option>
<option value="ro">Romanian</option>
<option value="ru">Russian</option>
<option value="sk">Slovak</option>
<option value="sl">Slovenian</option>
<option value="sv">Swedish</option>
<option value="es">Spanish</option>
<option value="tr">Turkish</option>
<option value="uk">Ukrainian</option>
<option value="vi">Vietnamese</option>
</select>
<td class="section">
<div class="main-panel">
<% var storedFiles = GetStoredFiles();
if (!storedFiles.Any())
{ %>
<span class="portal-name">ONLYOFFICE Document Editors Welcome!</span>
<span class="portal-descr">
Get started with a demo-sample of ONLYOFFICE Document Editors, the first html5-based editors.
<br /> You may upload your own documents for testing using the "<b>Upload file</b>" button and <b>selecting</b> the necessary files on your PC.
</span>
<% }
else
{ %>
<div class="stored-list">
<span class="header-list">Your documents</span>
<table class="tableHeader" cellspacing="0" cellpadding="0" width="100%">
<thead>
<tr >
<td class="tableHeaderCell tableHeaderCellFileName">Filename</td>
<td class="tableHeaderCell tableHeaderCellEditors contentCells-shift">Editors</td>
<td class="tableHeaderCell tableHeaderCellViewers">Viewers</td>
<td class="tableHeaderCell tableHeaderCellDownload">Download</td>
<td class="tableHeaderCell tableHeaderCellRemove">Remove</td>
</tr>
</thead>
</table>
<div class="scroll-table-body">
<table cellspacing="0" cellpadding="0" width="100%">
<tbody>
<% foreach (var storedFile in storedFiles)
{
var editUrl = "doceditor.aspx?fileID=" + HttpUtility.UrlEncode(storedFile.Name);
var docType = DocumentType(storedFile.Name);
var canEdit = EditedExts.Contains(Path.GetExtension(storedFile.Name).ToLower());
%>
<tr class="tableRow" title="<%= storedFile.Name %>">
<td class="contentCells">
<a class="stored-edit <%= docType %>" href="<%= editUrl %>" target="_blank">
<span title="<%= storedFile.Name %>"><%= storedFile.Name %></span>
</a>
</td>
<% if (canEdit) { %>
<td class="contentCells contentCells-icon">
<a href="<%= editUrl + "&editorsType=desktop&editorsMode=edit" %>" target="_blank">
<img src="app_themes/images/desktop-24.png" alt="Open in editor for full size screens" title="Open in editor for full size screens"/>
</a>
</td>
<td class="contentCells contentCells-icon">
<a href="<%= editUrl + "&editorsType=mobile&editorsMode=edit" %>" target="_blank">
<img src="app_themes/images/mobile-24.png" alt="Open in editor for mobile devices" title="Open in editor for mobile devices"/>
</a>
</td>
<td class="contentCells contentCells-icon">
<% if (docType == "word") { %>
<a href="<%= editUrl + "&editorsType=desktop&editorsMode=review" %>" target="_blank">
<img src="app_themes/images/review-24.png" alt="Open in editor for review" title="Open in editor for review"/>
</a>
<% } else if (docType == "cell") { %>
<a href="<%= editUrl + "&editorsType=desktop&editorsMode=filter" %>" target="_blank">
<img src="app_themes/images/filter-24.png" alt="Open in editor without access to change the filter" title="Open in editor without access to change the filter" />
</a>
<% } %>
</td>
<td class="contentCells contentCells-icon">
<a href="<%= editUrl + "&editorsType=desktop&editorsMode=comment" %>" target="_blank">
<img src="app_themes/images/comment-24.png" alt="Open in editor for comment" title="Open in editor for comment"/>
</a>
</td>
<td class="contentCells contentCells-icon">
<% if (docType == "word") { %>
<a href="<%= editUrl + "&editorsType=desktop&editorsMode=fillForms" %>" target="_blank">
<img src="app_themes/images/fill-forms-24.png" alt="Open in editor for filling in forms" title="Open in editor for filling in forms"/>
</a>
<% } %>
</td>
<td class="contentCells contentCells-shift contentCells-icon">
<% if (docType == "word") { %>
<a href="<%= editUrl + "&editorsType=desktop&editorsMode=blockcontent" %>" target="_blank">
<img src="app_themes/images/block-content-24.png" alt="Open in editor without content control modification" title="Open in editor without content control modification"/>
</a>
<% } %>
</td>
<% } else { %>
<td class="contentCells contentCells-shift contentCells-icon" colspan="6"></td>
<% } %>
<td class="contentCells contentCells-icon">
<a href="<%= editUrl + "&editorsType=desktop&editorsMode=view" %>" target="_blank">
<img src="app_themes/images/desktop-24.png" alt="Open in viewer for full size screens" title="Open in viewer for full size screens"/>
</a>
</td>
<td class="contentCells contentCells-icon">
<a href="<%= editUrl + "&editorsType=mobile&editorsMode=view" %>" target="_blank">
<img src="app_themes/images/mobile-24.png" alt="Open in viewer for mobile devices" title="Open in viewer for mobile devices"/>
</a>
</td>
<td class="contentCells contentCells-icon contentCells-shift">
<a href="<%= editUrl + "&editorsType=embedded&editorsMode=embedded" %>" target="_blank">
<img src="app_themes/images/embeded-24.png" alt="Open in embedded mode" title="Open in embedded mode"/>
</a>
</td>
<td class="contentCells contentCells-icon contentCells-shift">
<a href="webeditor.ashx?type=download&fileName=<%= HttpUtility.UrlEncode(storedFile.Name) %>">
<img class="icon-download" src="app_themes/images/download-24.png" alt="Download" title="Download" />
</a>
</td>
<td class="contentCells contentCells-icon contentCells-shift">
<a class="delete-file" data-filename="<%= storedFile.Name %>">
<img class="icon-delete" src="app_themes/images/delete-24.png" alt="Delete" title="Delete" />
</a>
</td>
</tr>
<% } %>
</tbody>
</table>
</div>
</div>
<% } %>
</div>
</td>
<td width="70%" valign="middle">Choose the language for ONLYOFFICE™ editors interface.</td>
</tr>
</tbody>
</table>
<br />
<br />
<div class="help-block">
<span class="try-descr">Upload your file or create new file</span>
<br />
<br />
<div class="clearFix">
<div class="upload-panel clearFix">
<a class="file-upload">
Upload
<br />
File
<input type="file" id="fileupload" name="files[]" data-url="webeditor.ashx?type=upload" />
</a>
</div>
<div class="create-panel">
<ul class="try-editor-list clearFix">
<li><a class="try-editor word" data-type="word">Create<br />Document</a></li>
<li><a class="try-editor cell" data-type="cell">Create<br />Spreadsheet</a></li>
<li><a class="try-editor slide" data-type="slide">Create<br />Presentation</a></li>
</ul>
<label class="create-sample">
<input id="createSample" class="checkbox" type="checkbox" />
Create a file filled with sample content
</label>
</div>
</div>
</div>
<% var storedFiles = GetStoredFiles();
if (storedFiles.Any())
{ %>
<div class="help-block">
<span>Your documents</span>
<br />
<br />
<div class="stored-list">
<table width="100%" cellspacing="0" cellpadding="0">
<thead>
<tr class="tableHeader">
<td class="tableHeaderCell tableHeaderCellFileName">Filename</td>
<td colspan="6" class="tableHeaderCell contentCells-shift">Editors</td>
<td colspan="3" class="tableHeaderCell">Viewers</td>
</tr>
</thead>
<tbody>
<% foreach (var storedFile in storedFiles)
{ %>
<%
var editUrl = "doceditor.aspx?fileID=" + HttpUtility.UrlEncode(storedFile.Name);
var docType = DocumentType(storedFile.Name);
%>
<tr class="tableRow" title="<%= storedFile.Name %>">
<td class="contentCells">
<a class="stored-edit <%= docType %>" href="<%= editUrl %>" target="_blank">
<span title="<%= storedFile.Name %>"><%= storedFile.Name %></span>
</a>
<a href="webeditor.ashx?type=download&filename=<%= HttpUtility.UrlEncode(storedFile.Name) %>">
<img class="icon-download" src="app_themes/images/download-24.png" alt="Download" title="Download" />
</a>
<a class="delete-file" data-filename="<%= storedFile.Name %>">
<img class="icon-delete" src="app_themes/images/delete-24.png" alt="Delete" title="Delete" />
</a>
</td>
<td class="contentCells contentCells-icon">
<a href="<%= editUrl + "&editorsType=desktop&editorsMode=edit" %>" target="_blank">
<img src="app_themes/images/desktop-24.png" alt="Open in editor for full size screens" title="Open in editor for full size screens"/>
</a>
</td>
<td class="contentCells contentCells-icon">
<a href="<%= editUrl + "&editorsType=mobile&editorsMode=edit" %>" target="_blank">
<img src="app_themes/images/mobile-24.png" alt="Open in editor for mobile devices" title="Open in editor for mobile devices"/>
</a>
</td>
<td class="contentCells contentCells-icon">
<% if (docType == "word") { %>
<a href="<%= editUrl + "&editorsType=desktop&editorsMode=review" %>" target="_blank">
<img src="app_themes/images/review-24.png" alt="Open in editor for review" title="Open in editor for review"/>
</a>
<% } else if (docType == "cell") { %>
<a href="<%= editUrl + "&editorsType=desktop&editorsMode=filter" %>" target="_blank">
<img src="app_themes/images/filter-24.png" alt="Open in editor without access to change the filter" title="Open in editor without access to change the filter" />
</a>
<% } %>
</td>
<td class="contentCells contentCells-icon">
<a href="<%= editUrl + "&editorsType=desktop&editorsMode=comment" %>" target="_blank">
<img src="app_themes/images/comment-24.png" alt="Open in editor for comment" title="Open in editor for comment"/>
</a>
</td>
<td class="contentCells contentCells-icon">
<% if (docType == "word") { %>
<a href="<%= editUrl + "&editorsType=desktop&editorsMode=fillForms" %>" target="_blank">
<img src="app_themes/images/fill-forms-24.png" alt="Open in editor for filling in forms" title="Open in editor for filling in forms"/>
</a>
<% } %>
</td>
<td class="contentCells contentCells-icon contentCells-shift">
<% if (docType == "word") { %>
<a href="<%= editUrl + "&editorsType=desktop&editorsMode=blockcontent" %>" target="_blank">
<img src="app_themes/images/block-content-24.png" alt="Open in editor without content control modification" title="Open in editor without content control modification"/>
</a>
<% } %>
</td>
<td class="contentCells contentCells-icon">
<a href="<%= editUrl + "&editorsType=desktop&editorsMode=view" %>" target="_blank">
<img src="app_themes/images/desktop-24.png" alt="Open in viewer for full size screens" title="Open in viewer for full size screens"/>
</a>
</td>
<td class="contentCells contentCells-icon">
<a href="<%= editUrl + "&editorsType=mobile&editorsMode=view" %>" target="_blank">
<img src="app_themes/images/mobile-24.png" alt="Open in viewer for mobile devices" title="Open in viewer for mobile devices"/>
</a>
</td>
<td class="contentCells contentCells-icon">
<a href="<%= editUrl + "&editorsType=embedded&editorsMode=embedded" %>" target="_blank">
<img src="app_themes/images/embeded-24.png" alt="Open in embedded mode" title="Open in embedded mode"/>
</a>
</td>
</tr>
<% } %>
</tbody>
</table>
</div>
</div>
<% } %>
<br />
<br />
<br />
<div class="help-block">
<span>Want to learn how it works?</span>
<% var examples = new DirectoryInfo(HttpRuntime.AppDomainAppPath + "assets")
.GetFiles("*.zip", SearchOption.TopDirectoryOnly)
.Select(fileInfo => fileInfo.Name).ToList();
if (examples.Any())
{ %>
<br />
Download the code for the sample of ONLYOFFICE Document Editors to find out the details.
<br />
<br />
<% foreach (var example in examples)
{ %>
<a class="button gray" href="app_data/<%= HttpUtility.HtmlEncode(example).Replace("#", "%23") %>">
<%= example.Replace(" Example.zip", "") %>
</a>
<% } %>
<br />
<br />
<% } %>
<br />
Read the editor <a href="http://api.onlyoffice.com/editors/howitworks">API Documentation</a>
</div>
<br />
<br />
<br />
<div class="help-block">
<span>Any questions?</span>
<br />
Please, <a href="mailto:sales@onlyoffice.com">submit your request</a> and we'll help you shortly.
</div>
</div>
<div id="hint">
<div class="corner"></div>
If you check this option the file will be saved both in the original and converted into Office Open XML format for faster viewing and editing. In other case the document will be overwritten by its copy in Office Open XML format.
</div>
<div id="mainProgress">
<div id="uploadSteps">
<span id="step1" class="step">1. Loading the file</span>
<span class="step-descr">The file loading process will take some time depending on the file size, presence or absence of additional elements in it (macros, etc.) and the connection speed.</span>
<span id="uploadFileName" class="uploadFileName"></span>
<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>
<br />
<span id="step2" class="step">2. File conversion</span>
<span class="step-descr">The file is being converted into Office Open XML format for the document faster viewing and editing.</span>
<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>
<br />
<span id="step3" class="step">3. Loading editor scripts</span>
<span class="step-descr">The scripts for the editor are loaded only once and are will be cached on your computer in future. It might take some time depending on the connection speed.</span>
<div id="blockPassword">
<span class="descrFilePass">The file is password protected.</span>
<br />
<div>
<input id="filePass" type="password"/>
<div id="enterPass" class="button orange">Enter</div>
<div id="skipPass" class="button gray">Skip</div>
</div>
<span class="errorPass"></span>
<br />
</div>
<span id="step3" class="step">3. Loading editor scripts.</span>
<span class="step-descr">They are loaded only once, they will be cached on your computer.</span>
<input type="hidden" name="hiddenFileName" id="hiddenFileName" />
<br />
<br />
<span class="progress-descr">Please note, that the speed of all operations greatly depends on the server and the client locations. In case they differ or are located in differernt countries/continents, there might be lack of speed and greater wait time. The best results are achieved when the server and client computers are located in one and the same place (city).</span>
<span class="progress-descr">Note the speed of all operations depends on your connection quality and server location.</span>
<br />
<br />
<div class="error-message">
<span></span>
<b>Upload error: </b><span></span>
<br />
Please select another file and try again. If you have questions please <a href="mailto:sales@onlyoffice.com">contact us.</a>
Please select another file and try again.
</div>
</div>
<iframe id="embeddedView" src="" height="345px" width="600px" frameborder="0" scrolling="no" allowtransparency></iframe>
<iframe id="embeddedView" src="" height="345px" width="432px" frameborder="0" scrolling="no" allowtransparency></iframe>
<br />
<div id="beginEmbedded" class="button disable">Embedded view</div>
<div id="beginView" class="button disable">View</div>
<div id="beginEdit" class="button disable">Edit</div>
<div id="beginEdit" class="button orange disable">Edit</div>
<div id="beginView" class="button gray disable">View</div>
<div id="beginEmbedded" class="button gray disable">Embedded view</div>
<div id="cancelEdit" class="button gray">Cancel</div>
</div>
<span id="loadScripts" data-docs="<%= UrlPreloadScripts %>"></span>
<div class="bottom-panel">&copy; Ascensio System SIA <%= DateTime.Now.Year.ToString() %>. All rights reserved.</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/jquery-1.9.0.min.js"></script>
<script language="javascript" type="text/javascript" src="script/jquery-ui.min.js"></script>
<script language="javascript" type="text/javascript" src="script/jquery.blockUI.js"></script>
<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/jscript.js"></script>
<script language="javascript" type="text/javascript">
var ConverExtList = '<%= string.Join(",", ConvertExts.ToArray()) %>';
var EditedExtList = '<%= string.Join(",", EditedExts.ToArray()) %>';
</script>
</body>
</html>

View File

@ -1,6 +1,6 @@
/**
*
* (c) Copyright Ascensio System SIA 2020
* (c) Copyright Ascensio System SIA 2021
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -32,6 +32,7 @@ namespace OnlineEditorsExample
{
internal static class FileType
{
// the spreadsheet extension list
public static readonly List<string> ExtsSpreadsheet = new List<string>
{
".xls", ".xlsx", ".xlsm",
@ -39,6 +40,7 @@ namespace OnlineEditorsExample
".ods", ".fods", ".ots", ".csv"
};
// the presentation extension list
public static readonly List<string> ExtsPresentation = new List<string>
{
".pps", ".ppsx", ".ppsm",
@ -47,6 +49,7 @@ namespace OnlineEditorsExample
".odp", ".fodp", ".otp"
};
// the document extension list
public static readonly List<string> ExtsDocument = new List<string>
{
".doc", ".docx", ".docm",
@ -56,12 +59,13 @@ namespace OnlineEditorsExample
".pdf", ".djvu", ".fb2", ".epub", ".xps"
};
// get an internal file extension
public static string GetInternalExtension(string extension)
{
extension = Path.GetExtension(extension).ToLower();
if (ExtsDocument.Contains(extension)) return ".docx";
if (ExtsSpreadsheet.Contains(extension)) return ".xlsx";
if (ExtsPresentation.Contains(extension)) return ".pptx";
extension = Path.GetExtension(extension).ToLower(); // get file extension
if (ExtsDocument.Contains(extension)) return ".docx"; // .docx for text document extensions
if (ExtsSpreadsheet.Contains(extension)) return ".xlsx"; // .xlsx for spreadsheet extensions
if (ExtsPresentation.Contains(extension)) return ".pptx"; // .pptx for presentation extensions
return string.Empty;
}
}
@ -69,6 +73,7 @@ namespace OnlineEditorsExample
public partial class _Default : Page
{
// get the virtual path
public static string VirtualPath
{
get
@ -88,6 +93,7 @@ namespace OnlineEditorsExample
get { return _ismono.HasValue ? _ismono.Value : (_ismono = (bool?)(Type.GetType("Mono.Runtime") != null)).Value; }
}
// get maximum file size
private static long MaxFileSize
{
get
@ -98,21 +104,25 @@ namespace OnlineEditorsExample
}
}
// get all the supported file extensions
private static List<string> FileExts
{
get { return ViewedExts.Concat(EditedExts).Concat(ConvertExts).ToList(); }
}
// file extensions that can be viewed
private static List<string> ViewedExts
{
get { return (WebConfigurationManager.AppSettings["files.docservice.viewed-docs"] ?? "").Split(new char[] { '|', ',' }, StringSplitOptions.RemoveEmptyEntries).ToList(); }
}
// file extensions that can be edited
public static List<string> EditedExts
{
get { return (WebConfigurationManager.AppSettings["files.docservice.edited-docs"] ?? "").Split(new char[] { '|', ',' }, StringSplitOptions.RemoveEmptyEntries).ToList(); }
}
// file extensions that can be converted
public static List<string> ConvertExts
{
get { return (WebConfigurationManager.AppSettings["files.docservice.convert-docs"] ?? "").Split(new char[] { '|', ',' }, StringSplitOptions.RemoveEmptyEntries).ToList(); }
@ -120,43 +130,46 @@ namespace OnlineEditorsExample
private static string _fileName;
// get current user host address
public static string CurUserHostAddress(string userAddress)
{
return Regex.Replace(userAddress ?? HttpContext.Current.Request.UserHostAddress, "[^0-9a-zA-Z.=]", "_");
}
// get the storage path of the given file
public static string StoragePath(string fileName, string userAddress)
{
var directory = HttpRuntime.AppDomainAppPath + WebConfigurationManager.AppSettings["storage-path"] + CurUserHostAddress(userAddress) + "\\";
if (!Directory.Exists(directory))
{
Directory.CreateDirectory(directory);
Directory.CreateDirectory(directory); // if the file directory doesn't exist, make it
}
return directory + Path.GetFileName(fileName);
}
// get the path to the forcesaved file version
public static string ForcesavePath(string fileName, string userAddress, Boolean create)
{
var directory = HttpRuntime.AppDomainAppPath + WebConfigurationManager.AppSettings["storage-path"] + CurUserHostAddress(userAddress) + "\\";
if (!Directory.Exists(directory))
if (!Directory.Exists(directory)) // the directory with host address doesn't exist
{
return "";
}
directory = directory + Path.GetFileName(fileName) + "-hist" + "\\";
directory = directory + Path.GetFileName(fileName) + "-hist" + "\\"; // get the path to the history of the given file
if (!Directory.Exists(directory))
{
if (create)
if (create) // create history directory if it doesn't exist
{
Directory.CreateDirectory(directory);
}
else
else // the history directory doesn't exist and we are not supposed to create it
{
return "";
}
}
directory = directory + Path.GetFileName(fileName);
directory = directory + Path.GetFileName(fileName); // get the path to the given file
if (!File.Exists(directory))
{
if (!create)
@ -168,39 +181,46 @@ namespace OnlineEditorsExample
return directory;
}
// create the path to the file history
public static string HistoryDir(string storagePath)
{
return storagePath += "-hist";
}
// get the path to the specified file version by its history directory
public static string VersionDir(string histPath, int version)
{
return Path.Combine(histPath, version.ToString());
}
// get the path to the specified file version by the file name and the user address
public static string VersionDir(string fileName, string userAddress, int version)
{
return VersionDir(HistoryDir(StoragePath(fileName, userAddress)), version);
}
// get the last file version by its history directory
public static int GetFileVersion(string historyPath)
{
if (!Directory.Exists(historyPath)) return 0;
return Directory.EnumerateDirectories(historyPath).Count() + 1;
return Directory.EnumerateDirectories(historyPath).Count() + 1; // run through all the file versions and count them
}
// get the last file version by the file name and the user address
public static int GetFileVersion(string fileName, string userAddress)
{
return GetFileVersion(HistoryDir(StoragePath(fileName, userAddress)));
}
// get url to the original file
public static string FileUri(string fileName, Boolean forDocumentServer)
{
var uri = new UriBuilder(GetServerUrl(forDocumentServer));
uri.Path = VirtualPath + fileName;
uri.Path = VirtualPath + fileName; // get full url address to the file
return uri.ToString();
}
// get server url
public static string GetServerUrl(Boolean forDocumentServer)
{
if (forDocumentServer && !WebConfigurationManager.AppSettings["files.docservice.url.example"].Equals(""))
@ -218,15 +238,16 @@ namespace OnlineEditorsExample
}
}
// get the document type
public static string DocumentType(string fileName)
{
var ext = Path.GetExtension(fileName).ToLower();
if (FileType.ExtsDocument.Contains(ext)) return "word";
if (FileType.ExtsSpreadsheet.Contains(ext)) return "cell";
if (FileType.ExtsPresentation.Contains(ext)) return "slide";
if (FileType.ExtsDocument.Contains(ext)) return "word"; // word for text document extensions
if (FileType.ExtsSpreadsheet.Contains(ext)) return "cell"; // cell for spreadsheet extensions
if (FileType.ExtsPresentation.Contains(ext)) return "slide"; // slide for presentation extensions
return "word";
return "word"; // the default document type is word
}
protected string UrlPreloadScripts = WebConfigurationManager.AppSettings["files.docservice.url.site"] + WebConfigurationManager.AppSettings["files.docservice.url.preloader"];
@ -236,14 +257,15 @@ namespace OnlineEditorsExample
{
}
// uploading a file by the HtthContext object
public static string DoUpload(HttpContext context)
{
var httpPostedFile = context.Request.Files[0];
if (HttpContext.Current.Request.Browser.Browser.ToUpper() == "IE")
if (HttpContext.Current.Request.Browser.Browser.ToUpper() == "IE") // check from which browser the request came for
{
var files = httpPostedFile.FileName.Split(new char[] { '\\' });
_fileName = files[files.Length - 1];
_fileName = files[files.Length - 1]; // get file name
}
else
{
@ -251,33 +273,37 @@ namespace OnlineEditorsExample
}
var curSize = httpPostedFile.ContentLength;
if (MaxFileSize < curSize || curSize <= 0)
if (MaxFileSize < curSize || curSize <= 0) // check if the file size exceeds the maximum file size
{
throw new Exception("File size is incorrect");
}
var curExt = (Path.GetExtension(_fileName) ?? "").ToLower();
if (!FileExts.Contains(curExt))
if (!FileExts.Contains(curExt)) // check if the file extension is supported by the editor
{
throw new Exception("File type is not supported");
}
_fileName = GetCorrectName(_fileName);
_fileName = GetCorrectName(_fileName); // get the correct file name if such a name already exists
var savedFileName = StoragePath(_fileName, null);
httpPostedFile.SaveAs(savedFileName);
var savedFileName = StoragePath(_fileName, null); // get the storage path to the uploading file
httpPostedFile.SaveAs(savedFileName); // and save it
DocEditor.CreateMeta(_fileName, context.Request.Cookies.GetOrDefault("uid", "uid-1"), context.Request.Cookies.GetOrDefault("uname", "John Smith"), null);
// get file meta information or create the default one
var id = context.Request.Cookies.GetOrDefault("uid", null);
var user = Users.getUser(id); // get the user
DocEditor.CreateMeta(_fileName, user.id, user.name, null);
return _fileName;
}
// uploading a file by the file url and the request
public static string DoUpload(string fileUri, HttpRequest request)
{
_fileName = GetCorrectName(Path.GetFileName(fileUri));
_fileName = GetCorrectName(Path.GetFileName(fileUri)); // get the correct file name if such a name already exists
var curExt = (Path.GetExtension(_fileName) ?? "").ToLower();
if (!FileExts.Contains(curExt))
if (!FileExts.Contains(curExt)) // check if the file extension is supported by the editor
{
throw new Exception("File type is not supported");
}
@ -292,7 +318,7 @@ namespace OnlineEditorsExample
ServicePointManager.ServerCertificateValidationCallback += (s, ce, ca, p) => true;
}
using (var stream = req.GetResponse().GetResponseStream())
using (var stream = req.GetResponse().GetResponseStream()) // get response stream of the uploading file
{
if (stream == null) throw new Exception("stream is null");
const int bufferSize = 4096;
@ -303,12 +329,15 @@ namespace OnlineEditorsExample
int readed;
while ((readed = stream.Read(buffer, 0, bufferSize)) != 0)
{
fs.Write(buffer, 0, readed);
fs.Write(buffer, 0, readed); // write bytes to the output stream
}
}
}
DocEditor.CreateMeta(_fileName, request.Cookies.GetOrDefault("uid", "uid-1"), request.Cookies.GetOrDefault("uname", "John Smith"), null);
// get file meta information or create the default one
var id = request.Cookies.GetOrDefault("uid", null);
var user = Users.getUser(id); // get the user
DocEditor.CreateMeta(_fileName, user.id, user.name, null);
}
catch (Exception)
{
@ -317,25 +346,55 @@ namespace OnlineEditorsExample
return _fileName;
}
// converting a file
public static string DoConvert(HttpContext context)
{
_fileName = Path.GetFileName(context.Request["filename"]);
string fileData;
try
{
using (var receiveStream = context.Request.InputStream)
using (var readStream = new StreamReader(receiveStream))
{
fileData = readStream.ReadToEnd();
if (string.IsNullOrEmpty(fileData)) context.Response.Write("{\"error\":1,\"message\":\"Request stream is empty\"}");
}
}
catch (Exception e)
{
throw new HttpException((int)HttpStatusCode.BadRequest, e.Message);
}
var extension = (Path.GetExtension(_fileName) ?? "").Trim('.');
var jss = new JavaScriptSerializer();
var body = jss.Deserialize<Dictionary<string, object>>(fileData);
_fileName = Path.GetFileName(body["filename"].ToString());
var filePass = body["filePass"] != null ? body["filePass"].ToString() : null;
var extension = (Path.GetExtension(_fileName).ToLower() ?? "").Trim('.');
var internalExtension = FileType.GetInternalExtension(_fileName).Trim('.');
// check if the file with such an extension can be converted
if (ConvertExts.Contains("." + extension)
&& !string.IsNullOrEmpty(internalExtension))
{
// generate document key
var key = ServiceConverter.GenerateRevisionId(FileUri(_fileName, true));
var fileUrl = new UriBuilder(_Default.GetServerUrl(true));
fileUrl.Path = HttpRuntime.AppDomainAppVirtualPath
+ (HttpRuntime.AppDomainAppVirtualPath.EndsWith("/") ? "" : "/")
+ "webeditor.ashx";
fileUrl.Query = "type=download&fileName=" + HttpUtility.UrlEncode(_fileName);
// get the url to the converted file
string newFileUri;
var result = ServiceConverter.GetConvertedUri(FileUri(_fileName, true), extension, internalExtension, key, true, out newFileUri);
var result = ServiceConverter.GetConvertedUri(fileUrl.ToString() , extension, internalExtension, key, true, out newFileUri, filePass); ;
if (result != 100)
{
return "{ \"step\" : \"" + result + "\", \"filename\" : \"" + _fileName + "\"}";
}
// get a file name of an internal file extension with an index if the file with such a name already exists
var fileName = GetCorrectName(Path.GetFileNameWithoutExtension(_fileName) + "." + internalExtension);
var req = (HttpWebRequest)WebRequest.Create(newFileUri);
@ -346,7 +405,7 @@ namespace OnlineEditorsExample
ServicePointManager.ServerCertificateValidationCallback += (s, ce, ca, p) => true;
}
using (var stream = req.GetResponse().GetResponseStream())
using (var stream = req.GetResponse().GetResponseStream()) // get response stream of the converting file
{
if (stream == null) throw new Exception("Stream is null");
const int bufferSize = 4096;
@ -357,53 +416,64 @@ namespace OnlineEditorsExample
int readed;
while ((readed = stream.Read(buffer, 0, bufferSize)) != 0)
{
fs.Write(buffer, 0, readed);
fs.Write(buffer, 0, readed); // write bytes to the output stream
}
}
}
// remove the original file and its history if it exists
var storagePath = StoragePath(_fileName, null);
var histDir = HistoryDir(storagePath);
File.Delete(storagePath);
if (Directory.Exists(histDir)) Directory.Delete(histDir, true);
// create meta information about the converted file with user id and name specified
_fileName = fileName;
DocEditor.CreateMeta(_fileName, context.Request.Cookies.GetOrDefault("uid", "uid-1"), context.Request.Cookies.GetOrDefault("uname", "John Smith"), null);
var id = context.Request.Cookies.GetOrDefault("uid", null);
var user = Users.getUser(id); // get the user
DocEditor.CreateMeta(_fileName, user.id, user.name, null);
}
return "{ \"filename\" : \"" + _fileName + "\"}";
}
// get the correct file name if such a name already exists
public static string GetCorrectName(string fileName, string userAddress = null)
{
var baseName = Path.GetFileNameWithoutExtension(fileName);
var ext = Path.GetExtension(fileName);
var name = baseName + ext;
var baseName = Path.GetFileNameWithoutExtension(fileName); // get file name without extension
var ext = Path.GetExtension(fileName).ToLower(); // get file extension
var name = baseName + ext; // get full file name
// if the file with such a name already exists in this directory
for (var i = 1; File.Exists(StoragePath(name, userAddress)); i++)
{
name = baseName + " (" + i + ")" + ext;
name = baseName + " (" + i + ")" + ext; // add an index after its base name
}
return name;
}
// get all the stored files from the folder
protected static List<FileInfo> GetStoredFiles()
{
var directory = HttpRuntime.AppDomainAppPath + WebConfigurationManager.AppSettings["storage-path"] + CurUserHostAddress(null) + "\\";
if (!Directory.Exists(directory)) return new List<FileInfo>();
var directoryInfo = new DirectoryInfo(directory);
var directoryInfo = new DirectoryInfo(directory); // read the user host directory contents
// get the list of stored files from the host directory
List<FileInfo> storedFiles = directoryInfo.GetFiles("*.*", SearchOption.TopDirectoryOnly).ToList();
return storedFiles;
}
// get files information
public static List<Dictionary<string, object>> GetFilesInfo(string fileId = null)
{
var files = new List<Dictionary<string, object>>();
// run through all the files from the directory
foreach (var file in GetStoredFiles())
{
// write file parameters to the file object
var dictionary = new Dictionary<string, object>();
dictionary.Add("version", GetFileVersion(file.Name, null));
dictionary.Add("id", ServiceConverter.GenerateRevisionId(_Default.CurUserHostAddress(null) + "/" + file.Name + "/" + File.GetLastWriteTime(_Default.StoragePath(file.Name, null)).GetHashCode()));
@ -413,9 +483,10 @@ namespace OnlineEditorsExample
dictionary.Add("updated", file.LastWriteTime.ToString());
if (fileId != null)
{
// if file id is defined and it is equal to the document key value
if (fileId.Equals(dictionary["id"]))
{
files.Add(dictionary);
files.Add(dictionary); // add file object to the files
break;
}
}

View File

@ -15,7 +15,7 @@
<title>ONLYOFFICE</title>
<!--
*
* (c) Copyright Ascensio System SIA 2020
* (c) Copyright Ascensio System SIA 2021
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -70,28 +70,34 @@
console.log(message);
};
// the application is loaded into the browser
var onAppReady = function () {
innerAlert("Document editor ready");
};
// the document is modified
var onDocumentStateChange = function (event) {
var title = document.title.replace(/\*$/g, "");
document.title = title + (event.data ? "*" : "");
};
// the user is trying to switch the document from the viewing into the editing mode
var onRequestEditRights = function () {
location.href = location.href.replace(RegExp("editorsMode=view\&?", "i"), "");
};
// an error or some other specific event occurs
var onError = function (event) {
if (event)
innerAlert(event.data);
};
// the document is opened for editing with the old document.key value
var onOutdatedVersion = function (event) {
location.reload(true);
};
// replace the link to the document which contains a bookmark
var replaceActionLink = function(href, linkParam) {
var link;
var actionIndex = href.indexOf("&actionLink=");
@ -108,32 +114,37 @@
return link;
}
// the user is trying to get link for opening the document which contains a bookmark, scrolling to the bookmark position
var onMakeActionLink = function (event) {
var actionData = event.data;
var linkParam = JSON.stringify(actionData);
docEditor.setActionLink(replaceActionLink(location.href, linkParam));
docEditor.setActionLink(replaceActionLink(location.href, linkParam)); // set the link to the document which contains a bookmark
};
// the meta information of the document is changed via the meta command
var onMetaChange = function (event) {
var favorite = !!event.data.favorite;
var title = document.title.replace(/^\☆/g, "");
document.title = (favorite ? "☆" : "") + title;
docEditor.setFavorite(favorite);
docEditor.setFavorite(favorite); // change the Favorite icon state
};
// the user is trying to insert an image by clicking the Image from Storage button
var onRequestInsertImage = function (event) {
docEditor.insertImage({
docEditor.insertImage({ // insert an image into the file
"c": event.data.c,
<%= InsertImageConfig%>
})
};
// the user is trying to select document for comparing by clicking the Document from Storage button
var onRequestCompareFile = function () {
docEditor.setRevisedFile(<%= compareFileData%>);
docEditor.setRevisedFile(<%= compareFileData%>); // select a document for comparing
};
// the user is trying to select recipients data by clicking the Mail merge button
var onRequestMailMergeRecipients = function (event) {
docEditor.setMailMergeRecipients(<%= dataMailMergeRecipients%>);
docEditor.setMailMergeRecipients(<%= dataMailMergeRecipients%>); // insert recipient data for mail merge into the file
};
var config = <%= DocConfig %>;
@ -156,15 +167,15 @@
<% if (!string.IsNullOrEmpty(History) && !string.IsNullOrEmpty(HistoryData))
{ %>
config.events['onRequestHistory'] = function () {
docEditor.refreshHistory(<%= History %>);
config.events['onRequestHistory'] = function () { // the user is trying to show the document version history
docEditor.refreshHistory(<%= History %>); // show the document version history
};
config.events['onRequestHistoryData'] = function (event) {
config.events['onRequestHistoryData'] = function (event) { // the user is trying to click the specific document version in the document version history
var ver = event.data;
var histData = <%= HistoryData %>;
docEditor.setHistoryData(histData[ver - 1]);
docEditor.setHistoryData(histData[ver - 1]); // send the link to the document for viewing the version history
};
config.events['onRequestHistoryClose '] = function () {
config.events['onRequestHistoryClose '] = function () { // the user is trying to go back to the document from viewing the document version history
document.location.reload();
};
<% } %>

View File

@ -1,6 +1,6 @@
/**
*
* (c) Copyright Ascensio System SIA 2020
* (c) Copyright Ascensio System SIA 2021
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -32,11 +32,13 @@ namespace OnlineEditorsExample
{
public static string FileName;
// get url to the original file
public static string FileUri
{
get { return _Default.FileUri(FileName, true); }
}
// get url to the original file for Document Server
public static string FileUriUser
{
get { return _Default.FileUri(FileName, false); }
@ -46,6 +48,7 @@ namespace OnlineEditorsExample
{
get
{
// generate document key
return ServiceConverter.GenerateRevisionId(_Default.CurUserHostAddress(null)
+ "/" + Path.GetFileName(FileUri)
+ "/" + File.GetLastWriteTime(_Default.StoragePath(FileName, null)).GetHashCode());
@ -65,6 +68,7 @@ namespace OnlineEditorsExample
protected string dataMailMergeRecipients { get; private set; }
protected string documentType { get { return _Default.DocumentType(FileName); } }
// get callback url
public static string CallbackUrl
{
get
@ -81,68 +85,91 @@ namespace OnlineEditorsExample
}
}
public static string getCreateUrl(String documentType, String editorsType)
{
var createUrl = new UriBuilder(_Default.GetServerUrl(false));
createUrl.Path =
HttpRuntime.AppDomainAppVirtualPath
+ (HttpRuntime.AppDomainAppVirtualPath.EndsWith("/") ? "" : "/")
+ "doceditor.aspx";
createUrl.Query = "type=" + documentType
+ "&editorsType=" + editorsType;
return createUrl.ToString();
}
public static string getDownloadUrl
{
get
{
var downloadUrl = new UriBuilder(_Default.GetServerUrl(true));
downloadUrl.Path =
HttpRuntime.AppDomainAppVirtualPath
+ (HttpRuntime.AppDomainAppVirtualPath.EndsWith("/") ? "" : "/")
+ "webeditor.ashx";
downloadUrl.Query = "type=download"
+ "&fileName=" + HttpUtility.UrlEncode(FileName)
+ "&userAddress=" + HttpUtility.UrlEncode(HttpContext.Current.Request.UserHostAddress);
return downloadUrl.ToString();
}
}
// loading a page
protected void Page_Load(object sender, EventArgs e)
{
// get file url
var externalUrl = Request["fileUrl"];
if (!string.IsNullOrEmpty(externalUrl))
{
// and upload the file by the file url and the request
FileName = _Default.DoUpload(externalUrl, Request);
}
else
else // if it doesn't exist
{
// get file name
FileName = Path.GetFileName(Request["fileID"]);
}
// get file type
var type = Request["type"];
if (!string.IsNullOrEmpty(type))
{
// create demo document of a specified file type
Try(type, Request["sample"], Request);
Response.Redirect("doceditor.aspx?fileID=" + HttpUtility.UrlEncode(FileName));
}
var ext = Path.GetExtension(FileName);
// get file extension
var ext = Path.GetExtension(FileName).ToLower();
// get editor mode or set the default one (edit)
var editorsMode = Request.GetOrDefault("editorsMode", "edit");
var canEdit = _Default.EditedExts.Contains(ext);
var mode = canEdit && editorsMode != "view" ? "edit" : "view";
var submitForm = canEdit && (editorsMode.Equals("edit") || editorsMode.Equals("fillForms"));
var canEdit = _Default.EditedExts.Contains(ext); // check if this file can be edited
var mode = canEdit && editorsMode != "view" ? "edit" : "view"; // get the editor opening mode (edit or view)
var submitForm = canEdit && (editorsMode.Equals("edit") || editorsMode.Equals("fillForms")); // check if the Submit form button is displayed or hidden
var editorsType = Request.GetOrDefault("editorsType", "desktop");
var userId = Request.Cookies.GetOrDefault("uid", "uid-1");
var uname = userId.Equals("uid-0") ? null : Request.Cookies.GetOrDefault("uname", "John Smith");
string userGroup = null;
List<string> reviewGroups = null;
if (userId.Equals("uid-2"))
{
userGroup = "group-2";
reviewGroups = new List<string>() { "group-2", "" };
}
if (userId.Equals("uid-3"))
{
userGroup = "group-3";
reviewGroups = new List<string>() { "group-2" };
}
var id = Request.Cookies.GetOrDefault("uid", null);
var user = Users.getUser(id); // get the user
var jss = new JavaScriptSerializer();
object favorite = null;
if (!string.IsNullOrEmpty(Request.Cookies.GetOrDefault("uid", null)))
{
favorite = Request.Cookies.GetOrDefault("uid", null).Equals("uid-2");
}
// favorite icon state
bool? favorite = user.favorite;
var actionLink = Request.GetOrDefault("actionLink", null);
var actionData = string.IsNullOrEmpty(actionLink) ? null : jss.DeserializeObject(actionLink);
var actionLink = Request.GetOrDefault("actionLink", null); // get the action link (comment or bookmark) if it exists
var actionData = string.IsNullOrEmpty(actionLink) ? null : jss.DeserializeObject(actionLink); // get action data for the action link
// specify the document config
var config = new Dictionary<string, object>
{
{ "type", Request.GetOrDefault("editorsType", "desktop") },
{ "type", editorsType },
{ "documentType", documentType },
{
"document", new Dictionary<string, object>
{
{ "title", FileName },
{ "url", FileUri },
{ "url", getDownloadUrl },
{ "fileType", ext.Trim('.') },
{ "key", Key },
{
@ -154,16 +181,19 @@ namespace OnlineEditorsExample
}
},
{
// the permission for the document to be edited and downloaded or not
"permissions", new Dictionary<string, object>
{
{ "comment", editorsMode != "view" && editorsMode != "fillForms" && editorsMode != "embedded" && editorsMode != "blockcontent"},
{ "download", true },
{ "edit", canEdit && (editorsMode == "edit" || editorsMode == "filter") || editorsMode == "blockcontent" },
{ "copy", !user.deniedPermissions.Contains("copy") },
{ "download", !user.deniedPermissions.Contains("download") },
{ "edit", canEdit && (editorsMode == "edit" || editorsMode =="view" || editorsMode == "filter" || editorsMode == "blockcontent") },
{ "print", !user.deniedPermissions.Contains("print") },
{ "fillForms", editorsMode != "view" && editorsMode != "comment" && editorsMode != "embedded" && editorsMode != "blockcontent" },
{ "modifyFilter", editorsMode != "filter" },
{ "modifyContentControl", editorsMode != "blockcontent" },
{ "review", editorsMode == "edit" || editorsMode == "review" },
{ "reviewGroups", reviewGroups }
{ "review", canEdit && (editorsMode == "edit" || editorsMode == "review") },
{ "reviewGroups", user.reviewGroups }
}
}
}
@ -174,35 +204,39 @@ namespace OnlineEditorsExample
{ "actionLink", actionData },
{ "mode", mode },
{ "lang", Request.Cookies.GetOrDefault("ulang", "en") },
{ "callbackUrl", CallbackUrl },
{ "callbackUrl", CallbackUrl }, // absolute URL to the document storage service
{ "createUrl", getCreateUrl(documentType, editorsType)},
{
// the user currently viewing or editing the document
"user", new Dictionary<string, object>
{
{ "id", userId },
{ "name", uname },
{ "group", userGroup }
{ "id", user.id },
{ "name", user.name },
{ "group", user.group }
}
},
{
// the parameters for the embedded document type
"embedded", new Dictionary<string, object>
{
{ "saveUrl", FileUriUser },
{ "embedUrl", FileUriUser },
{ "shareUrl", FileUriUser },
{ "toolbarDocked", "top" }
{ "saveUrl", FileUriUser }, // the absolute URL that will allow the document to be saved onto the user personal computer
{ "embedUrl", FileUriUser }, // the absolute URL to the document serving as a source file for the document embedded into the web page
{ "shareUrl", FileUriUser }, // the absolute URL that will allow other users to share this document
{ "toolbarDocked", "top" } // the place for the embedded viewer toolbar (top or bottom)
}
},
{
// the parameters for the editor interface
"customization", new Dictionary<string, object>
{
{ "about", true },
{ "feedback", true },
{ "forcesave", false },
{ "submitForm", submitForm },
{ "about", true }, // the About section display
{ "feedback", true }, // the Feedback & Support menu button display
{ "forcesave", false }, // adds the request for the forced file saving to the callback handler
{ "submitForm", submitForm }, // if the Submit form button is displayed or not
{
"goback", new Dictionary<string, object>
"goback", new Dictionary<string, object> // settings for the Open file location menu button and upper right corner button
{
{ "url", _Default.GetServerUrl(false) + "default.aspx" }
{ "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
}
}
}
@ -211,8 +245,10 @@ namespace OnlineEditorsExample
}
};
// if the secret key to generate token exists
if (JwtManager.Enabled)
{
// encode the document config into a token
var token = JwtManager.Encode(config);
config.Add("token", token);
}
@ -221,12 +257,15 @@ namespace OnlineEditorsExample
try
{
// a logo which will be inserted into the document
Dictionary<string, object> logoConfig = GetLogoConfig();
InsertImageConfig = jss.Serialize(logoConfig).Replace("{", "").Replace("}", "");
// a document which will be compared with the current document
Dictionary<string, object> compareFile = GetCompareFile();
compareFileData = jss.Serialize(compareFile);
// recipient data for mail merging
Dictionary<string, object> mailMergeConfig = GetMailMergeConfig();
dataMailMergeRecipients = jss.Serialize(mailMergeConfig);
@ -234,6 +273,7 @@ namespace OnlineEditorsExample
Dictionary<string, object> hist;
Dictionary<string, object> histData;
// get the document history
GetHistory(out hist, out histData);
if (hist != null && histData != null)
{
@ -244,6 +284,7 @@ namespace OnlineEditorsExample
catch { }
}
// get the document history
private void GetHistory(out Dictionary<string, object> history, out Dictionary<string, object> historyData)
{
var jss = new JavaScriptSerializer();
@ -252,30 +293,30 @@ namespace OnlineEditorsExample
history = null;
historyData = null;
if (_Default.GetFileVersion(histDir) > 0)
if (_Default.GetFileVersion(histDir) > 0) // if the file was modified (the file version is greater than 0)
{
var currentVersion = _Default.GetFileVersion(histDir);
var hist = new List<Dictionary<string, object>>();
var histData = new Dictionary<string, object>();
for (var i = 1; i <= currentVersion; i++)
for (var i = 1; i <= currentVersion; i++) // run through all the file versions
{
var obj = new Dictionary<string, object>();
var dataObj = new Dictionary<string, object>();
var verDir = _Default.VersionDir(histDir, i);
var verDir = _Default.VersionDir(histDir, i); // get the path to the given file version
var key = i == currentVersion ? Key : File.ReadAllText(Path.Combine(verDir, "key.txt"));
var key = i == currentVersion ? Key : File.ReadAllText(Path.Combine(verDir, "key.txt")); // get document key
obj.Add("key", key);
obj.Add("version", i);
if (i == 1)
if (i == 1) // check if the version number is equal to 1
{
var infoPath = Path.Combine(histDir, "createdInfo.json");
var infoPath = Path.Combine(histDir, "createdInfo.json"); // get meta data of this file
if (File.Exists(infoPath)) {
var info = jss.Deserialize<Dictionary<string, object>>(File.ReadAllText(infoPath));
obj.Add("created", info["created"]);
obj.Add("created", info["created"]); // write meta information to the object (user information and creation date)
obj.Add("user", new Dictionary<string, object>() {
{ "id", info["id"] },
{ "name", info["name"] },
@ -284,23 +325,26 @@ namespace OnlineEditorsExample
}
dataObj.Add("key", key);
dataObj.Add("url", i == currentVersion ? FileUri : MakePublicUrl(Directory.GetFiles(verDir, "prev.*")[0]));
dataObj.Add("url", i == currentVersion ? FileUri : MakePublicUrl(Directory.GetFiles(verDir, "prev.*")[0])); // write file url to the data object
dataObj.Add("version", i);
if (i > 1)
if (i > 1) // check if the version number is greater than 1 (the file was modified)
{
// get the path to the changes.json file
var changes = jss.Deserialize<Dictionary<string, object>>(File.ReadAllText(Path.Combine(_Default.VersionDir(histDir, i - 1), "changes.json")));
var change = ((Dictionary<string, object>)((ArrayList)changes["changes"])[0]);
// write information about changes to the object
obj.Add("changes", changes["changes"]);
obj.Add("serverVersion", changes["serverVersion"]);
obj.Add("created", change["created"]);
obj.Add("user", change["user"]);
var prev = (Dictionary<string, object>)histData[(i - 2).ToString()];
dataObj.Add("previous", new Dictionary<string, object>() {
{ "key", prev["key"] },
var prev = (Dictionary<string, object>)histData[(i - 2).ToString()]; // get the history data from the previous file version
dataObj.Add("previous", new Dictionary<string, object>() { // write information about previous file version to the data object
{ "key", prev["key"] }, // write key and url information about previous file version
{ "url", prev["url"] },
});
// write the path to the diff.zip archive with differences in this file version
dataObj.Add("changesUrl", MakePublicUrl(Path.Combine(_Default.VersionDir(histDir, i - 1), "diff.zip")));
}
if (JwtManager.Enabled)
@ -308,10 +352,11 @@ namespace OnlineEditorsExample
var token = JwtManager.Encode(dataObj);
dataObj.Add("token", token);
}
hist.Add(obj);
histData.Add((i - 1).ToString(), dataObj);
hist.Add(obj); // add object dictionary to the hist list
histData.Add((i - 1).ToString(), dataObj); // write data object information to the history data
}
// write history information about the current file version to the history object
history = new Dictionary<string, object>()
{
{ "currentVersion", currentVersion },
@ -321,53 +366,61 @@ namespace OnlineEditorsExample
}
}
// get a logo config
private Dictionary<string, object> GetLogoConfig()
{
// get the path to the logo image
var InsertImageUrl = new UriBuilder(_Default.GetServerUrl(true));
InsertImageUrl.Path = HttpRuntime.AppDomainAppVirtualPath
+ (HttpRuntime.AppDomainAppVirtualPath.EndsWith("/") ? "" : "/")
+ "App_Themes\\images\\logo.png";
// create a logo config
Dictionary<string, object> logoConfig = new Dictionary<string, object>
{
{ "fileType", "png"},
{ "url", InsertImageUrl.ToString()}
};
if (JwtManager.Enabled)
if (JwtManager.Enabled) // if the secret key to generate token exists
{
var insImageToken = JwtManager.Encode(logoConfig);
logoConfig.Add("token", insImageToken);
var insImageToken = JwtManager.Encode(logoConfig); // encode logoConfig into the token
logoConfig.Add("token", insImageToken); // and add it to the logo config
}
return logoConfig;
}
// get a document which will be compared with the current document
private Dictionary<string, object> GetCompareFile()
{
// get the path to the compared file
var compareFileUrl = new UriBuilder(_Default.GetServerUrl(true));
compareFileUrl.Path = HttpRuntime.AppDomainAppVirtualPath
+ (HttpRuntime.AppDomainAppVirtualPath.EndsWith("/") ? "" : "/")
+ "webeditor.ashx";
compareFileUrl.Query = "type=assets&fileName=" + HttpUtility.UrlEncode("sample.docx");
// create an object with the information about the compared file
Dictionary<string, object> dataCompareFile = new Dictionary<string, object>
{
{ "fileType", "docx" },
{ "url", compareFileUrl.ToString() }
};
if (JwtManager.Enabled)
if (JwtManager.Enabled) // if the secret key to generate token exists
{
var compareFileToken = JwtManager.Encode(dataCompareFile);
dataCompareFile.Add("token", compareFileToken);
var compareFileToken = JwtManager.Encode(dataCompareFile); // encode the dataCompareFile object into the token
dataCompareFile.Add("token", compareFileToken); // and add it to the dataCompareFile object
}
return dataCompareFile;
}
// get a mail merge config
private Dictionary<string, object> GetMailMergeConfig()
{
// get the path to the recipients data for mail merging
var mailmergeUrl = new UriBuilder(_Default.GetServerUrl(true));
mailmergeUrl.Path =
HttpRuntime.AppDomainAppVirtualPath
@ -375,59 +428,67 @@ namespace OnlineEditorsExample
+ "webeditor.ashx";
mailmergeUrl.Query = "type=csv";
// create a mail merge config
Dictionary<string, object> mailMergeConfig = new Dictionary<string, object>
{
{ "fileType", "csv" },
{ "url", mailmergeUrl.ToString() }
};
if (JwtManager.Enabled)
if (JwtManager.Enabled) // if the secret key to generate token exists
{
var mailmergeToken = JwtManager.Encode(mailMergeConfig);
mailMergeConfig.Add("token", mailmergeToken);
var mailmergeToken = JwtManager.Encode(mailMergeConfig); // encode mailMergeConfig into the token
mailMergeConfig.Add("token", mailmergeToken); // and add it to the mail merge config
}
return mailMergeConfig;
}
// create the public url
private string MakePublicUrl(string fullPath)
{
var root = HttpRuntime.AppDomainAppPath + WebConfigurationManager.AppSettings["storage-path"];
return _Default.GetServerUrl(true) + fullPath.Substring(root.Length).Replace(Path.DirectorySeparatorChar, '/');
}
// create demo document
private static void Try(string type, string sample, HttpRequest request)
{
string ext;
switch (type)
{
case "word":
ext = ".docx";
ext = ".docx"; // .docx for word document type
break;
case "cell":
ext = ".xlsx";
ext = ".xlsx"; // .xlsx for cell document type
break;
case "slide":
ext = ".pptx";
ext = ".pptx"; // .pptx for slide document type
break;
default:
return;
}
var demoName = (string.IsNullOrEmpty(sample) ? "new" : "sample") + ext;
var demoPath = "assets\\" + (string.IsNullOrEmpty(sample) ? "new\\" : "sample\\");
var demoName = (string.IsNullOrEmpty(sample) ? "new" : "sample") + ext; // create demo document name with the necessary extension
var demoPath = "assets\\" + (string.IsNullOrEmpty(sample) ? "new\\" : "sample\\"); // and put this file into the assets directory
FileName = _Default.GetCorrectName(demoName);
FileName = _Default.GetCorrectName(demoName); // get file name with an index if such a file name already exists
var filePath = _Default.StoragePath(FileName, null);
File.Copy(HttpRuntime.AppDomainAppPath + demoPath + demoName, filePath);
File.Copy(HttpRuntime.AppDomainAppPath + demoPath + demoName, filePath); // copy this file to the storage directory
CreateMeta(FileName, request.Cookies.GetOrDefault("uid", "uid-1"), request.Cookies.GetOrDefault("uname", "John Smith"), null);
// create a json file with file meta data
var id = request.Cookies.GetOrDefault("uid", null);
var user = Users.getUser(id); // get the user
CreateMeta(FileName, user.id, user.name, null);
}
// create a json file with file meta data
public static void CreateMeta(string fileName, string uid, string uname, string userAddress)
{
var histDir = _Default.HistoryDir(_Default.StoragePath(fileName, userAddress));
Directory.CreateDirectory(histDir);
// create the meta data object and write the information into the createdInfo.json file
File.WriteAllText(Path.Combine(histDir, "createdInfo.json"), new JavaScriptSerializer().Serialize(new Dictionary<string, object> {
{ "created", DateTime.Now.ToString("yyyy'-'MM'-'dd HH':'mm':'ss") },
{ "id", uid },

View File

@ -1,6 +1,6 @@
/**
*
* (c) Copyright Ascensio System SIA 2020
* (c) Copyright Ascensio System SIA 2021
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -71,7 +71,7 @@ namespace ASC.Api.DocumentConverter
/// <param name="documentRevisionId">Key for caching on service</param>
/// <param name="isAsync">Perform conversions asynchronously</param>
/// <param name="convertedDocumentUri">Uri to the converted document</param>
/// <returns>The percentage of completion of conversion</returns>
/// <returns>The percentage of conversion completion</returns>
/// <example>
/// string convertedDocumentUri;
/// GetConvertedUri("http://helpcenter.onlyoffice.com/content/GettingStarted.pdf", ".pdf", ".docx", "http://helpcenter.onlyoffice.com/content/GettingStarted.pdf", false, out convertedDocumentUri);
@ -83,55 +83,64 @@ namespace ASC.Api.DocumentConverter
string toExtension,
string documentRevisionId,
bool isAsync,
out string convertedDocumentUri)
out string convertedDocumentUri,
string filePass = null)
{
convertedDocumentUri = string.Empty;
fromExtension = string.IsNullOrEmpty(fromExtension) ? Path.GetExtension(documentUri) : fromExtension;
// check if the fromExtension parameter is defined; if not, get it from the document url
fromExtension = string.IsNullOrEmpty(fromExtension) ? Path.GetExtension(documentUri).ToLower() : fromExtension;
// check if the file name parameter is defined; if not, get random uuid for this file
var title = Path.GetFileName(documentUri);
title = string.IsNullOrEmpty(title) ? Guid.NewGuid().ToString() : title;
// get document key
documentRevisionId = string.IsNullOrEmpty(documentRevisionId)
? documentUri
: documentRevisionId;
documentRevisionId = GenerateRevisionId(documentRevisionId);
// specify request parameters
var request = (HttpWebRequest)WebRequest.Create(DocumentConverterUrl);
request.Method = "POST";
request.ContentType = "application/json";
request.Accept = "application/json";
request.Timeout = ConvertTimeout;
// write all the necessary parameters to the body object
var body = new Dictionary<string, object>() {
{ "async", isAsync },
{ "filetype", fromExtension.Trim('.') },
{ "key", documentRevisionId },
{ "outputtype", toExtension.Trim('.') },
{ "title", title },
{ "url", documentUri }
{ "url", documentUri },
{ "password", filePass }
};
if (JwtManager.Enabled)
{
// create payload object
var payload = new Dictionary<string, object>
{
{ "payload", body }
};
var payloadToken = JwtManager.Encode(payload);
var bodyToken = JwtManager.Encode(body);
var payloadToken = JwtManager.Encode(payload); // encode the payload object to the payload token
var bodyToken = JwtManager.Encode(body); // encode the body object to the body token
// create header token
string JWTheader = WebConfigurationManager.AppSettings["files.docservice.header"].Equals("") ? "Authorization" : WebConfigurationManager.AppSettings["files.docservice.header"];
request.Headers.Add(JWTheader, "Bearer " + payloadToken);
request.Headers.Add(JWTheader, "Bearer " + payloadToken); // and add it to the request headers with the Bearer prefix
body.Add("token", bodyToken);
}
var bytes = Encoding.UTF8.GetBytes(new JavaScriptSerializer().Serialize(body));
request.ContentLength = bytes.Length;
using (var requestStream = request.GetRequestStream())
using (var requestStream = request.GetRequestStream()) // get the request stream
{
requestStream.Write(bytes, 0, bytes.Length);
requestStream.Write(bytes, 0, bytes.Length); // and write the serialized body object to it
}
// hack. http://ubuntuforums.org/showthread.php?t=1841740
@ -142,13 +151,13 @@ namespace ASC.Api.DocumentConverter
string dataResponse;
using (var response = request.GetResponse())
using (var stream = response.GetResponseStream())
using (var stream = response.GetResponseStream()) // get the response stream
{
if (stream == null) throw new Exception("Response is null");
using (var reader = new StreamReader(stream))
{
dataResponse = reader.ReadToEnd();
dataResponse = reader.ReadToEnd(); // and read it
}
}
@ -162,9 +171,10 @@ namespace ASC.Api.DocumentConverter
/// <returns>Supported key</returns>
public static string GenerateRevisionId(string expectedKey)
{
// if the expected key length is greater than 20, it is hashed and a fixed length value is stored in the string format
if (expectedKey.Length > 20) expectedKey = expectedKey.GetHashCode().ToString();
var key = Regex.Replace(expectedKey, "[^0-9-.a-zA-Z_=]", "_");
return key.Substring(key.Length - Math.Min(key.Length, 20));
return key.Substring(key.Length - Math.Min(key.Length, 20)); // the resulting key length is 20 or less
}
#endregion
@ -176,7 +186,7 @@ namespace ASC.Api.DocumentConverter
/// </summary>
/// <param name="jsonDocumentResponse">The resulting json from editing service</param>
/// <param name="responseUri">Uri to the converted document</param>
/// <returns>The percentage of completion of conversion</returns>
/// <returns>The percentage of conversion completion</returns>
private static int GetResponseUri(string jsonDocumentResponse, out string responseUri)
{
if (string.IsNullOrEmpty(jsonDocumentResponse)) throw new ArgumentException("Invalid param", "jsonDocumentResponse");
@ -184,21 +194,22 @@ namespace ASC.Api.DocumentConverter
var responseFromService = Json.Decode(jsonDocumentResponse);
if (jsonDocumentResponse == null) throw new WebException("Invalid answer format");
var errorElement = responseFromService.error;
if (errorElement != null) ProcessResponseError(Convert.ToInt32(errorElement));
var errorElement = responseFromService.error; // if an error occurs
if (errorElement != null) ProcessResponseError(Convert.ToInt32(errorElement)); // then get an error message
// check if the conversion is completed and save the result to a variable
var isEndConvert = responseFromService.endConvert;
int resultPercent;
responseUri = string.Empty;
if (isEndConvert)
if (isEndConvert) // if the conversion is completed
{
responseUri = responseFromService.fileUrl;
responseUri = responseFromService.fileUrl; // get the file url
resultPercent = 100;
}
else
else // if the conversion isn't completed
{
resultPercent = responseFromService.percent;
resultPercent = responseFromService.percent; // get the percentage value
if (resultPercent >= 100) resultPercent = 99;
}
@ -230,7 +241,7 @@ namespace ASC.Api.DocumentConverter
break;
case -5:
// public const int c_nErrorUnexpectedGuid = -5;
errorMessage = String.Format(errorMessageTemplate, "Error unexpected guid");
errorMessage = String.Format(errorMessageTemplate, "Incorrect password");
break;
case -4:
// public const int c_nErrorDownloadError = -4;

View File

@ -1,6 +1,6 @@
/**
*
* (c) Copyright Ascensio System SIA 2020
* (c) Copyright Ascensio System SIA 2021
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -34,26 +34,30 @@ namespace OnlineEditorsExample
static JwtManager()
{
Secret = WebConfigurationManager.AppSettings["files.docservice.secret"] ?? "";
Enabled = !string.IsNullOrEmpty(Secret);
Serializer = new JavaScriptSerializer();
Secret = WebConfigurationManager.AppSettings["files.docservice.secret"] ?? ""; // get token secret from the config parameters
Enabled = !string.IsNullOrEmpty(Secret); // check if the token is enabled
Serializer = new JavaScriptSerializer(); // define java script serializer
}
// encode a payload object into a token using a secret key
public static string Encode(IDictionary<string, object> payload)
{
// define the hashing algorithm and the token type
var header = new Dictionary<string, object>
{
{ "alg", "HS256" },
{ "typ", "JWT" }
};
var encHeader = Base64UrlEncode(Serializer.Serialize(header));
var encPayload = Base64UrlEncode(Serializer.Serialize(payload));
var hashSum = Base64UrlEncode(CalculateHash(encHeader, encPayload));
// three parts of token
var encHeader = Base64UrlEncode(Serializer.Serialize(header)); // header
var encPayload = Base64UrlEncode(Serializer.Serialize(payload)); // payload
var hashSum = Base64UrlEncode(CalculateHash(encHeader, encPayload)); // signature
return string.Format("{0}.{1}.{2}", encHeader, encPayload, hashSum);
}
// decode a token into a payload object using a secret key
public static string Decode(string token)
{
if (!Enabled || string.IsNullOrEmpty(token)) return "";
@ -61,11 +65,12 @@ namespace OnlineEditorsExample
var split = token.Split('.');
if (split.Length != 3) return "";
var hashSum = Base64UrlEncode(CalculateHash(split[0], split[1]));
if (hashSum != split[2]) return "";
return Base64UrlDecode(split[1]);
var hashSum = Base64UrlEncode(CalculateHash(split[0], split[1])); // get signature
if (hashSum != split[2]) return ""; // and check if it is equal to the signature from the token
return Base64UrlDecode(split[1]); // decode payload
}
// generate a hash code based on a key using the HMAC method
private static byte[] CalculateHash(string encHeader, string encPayload)
{
using (var hasher = new HMACSHA256(Encoding.UTF8.GetBytes(Secret)))
@ -75,17 +80,20 @@ namespace OnlineEditorsExample
}
}
// encode a string into the base64 value
private static string Base64UrlEncode(string str)
{
return Base64UrlEncode(Encoding.UTF8.GetBytes(str));
}
// encode bytes into the base64 value
private static string Base64UrlEncode(byte[] bytes)
{
return Convert.ToBase64String(bytes)
.TrimEnd('=').Replace('+', '-').Replace('/', '_');
}
// decode a base64 value into the string
private static string Base64UrlDecode(string payload)
{
var b64 = payload.Replace('_', '/').Replace('-', '+');

View File

@ -113,6 +113,7 @@
<DependentUpon>Default.aspx</DependentUpon>
</Compile>
<Compile Include="TrackManager.cs" />
<Compile Include="Users.cs" />
<Compile Include="Utils.cs" />
<Compile Include="WebEditor.ashx.cs">
<DependentUpon>WebEditor.ashx</DependentUpon>

View File

@ -7,7 +7,7 @@ using System.Runtime.InteropServices;
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Ascensio System SIA")]
[assembly: AssemblyProduct("OnlineEditorsExample")]
[assembly: AssemblyCopyright("Ascensio System SIA 2020")]
[assembly: AssemblyCopyright("Ascensio System SIA 2021")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]

View File

@ -0,0 +1,49 @@
## How to integrate online editors into your own web site on .Net (C#)
### Introduction
To integrate **ONLYOFFICE online editors** into your own website on **.Net (C#)** you need to download and install ONLYOFFICE editors on your local server and use the [.Net (C#) example](https://api.onlyoffice.com/editors/demopreview) for their integration.
Please note that the integration examples are used to demonstrate document editors functions and the ways to connect **Document Server** to your own application. **DO NOT USE** these examples on your own server without **PROPER CODE MODIFICATIONS**!
This guide will show you the sequence of actions to integrate the editors successfully.
### Step 1. Download and Install Document Server
First, download the [**ONLYOFFICE Editors**](https://api.onlyoffice.com/editors/demopreview) (the ONLYOFFICE Document Server).
See the detailed guide to learn how to install Document Server [for Windows](https://helpcenter.onlyoffice.com/installation/docs-developer-install-windows.aspx?from=api_csharp_example), [for Linux](https://helpcenter.onlyoffice.com/installation/docs-developer-install-ubuntu.aspx?from=api_csharp_example), or [for Docker](https://helpcenter.onlyoffice.com/server/developer-edition/docker/docker-installation.aspx?from=api_csharp_example).
### Step 2. Download the .Net (C#) code for the editors integration
Download the [.Net (C#) example](https://api.onlyoffice.com/editors/demopreview) from our site.
You need to connnect the editors to your web site. For that specify the path to the editors installation in the *settings.config* file:
```
<add key="files.docservice.url.site" value="https://documentserver/" />
```
where the **documentserver** is the name of the server with the ONLYOFFICE Document Server installed.
If you want to experiment with the editor configuration, modify the [parameters](https://api.onlyoffice.com/editors/advanced) it the *DocEditor.aspx* file.
### Step 3. Install the prerequisites
To run your website with the editors successfully, check if your system meets the necessary system requirements:
* Microsoft .NET Framework: version 4.5 (download it from the [official Microsoft website](https://www.microsoft.com/en-US/download/details.aspx?id=30653));
* Internet Information Services: version 7 or later.
### Step 4. Running your web site with the editors
1. Run the Internet Information Service (IIS) manager
Start -> ControlPanel -> System and Security -> Administrative Tools -> Internet Information Services (IIS) Manager
2. Add your web site in the IIS Manager
On the **Connections** panel right-click the **Sites** node in the tree, then click **Add Website**.
![add](screenshots/add.png)
3. In the **Add Website** dialog box specify the name of the folder with the .Net (C#) project in the **Site name** box.
Specify the path to the folder with your project in the **Physical Path** box.
Specify the unique value used only for this website in the **Port** box.
![sitename](screenshots/sitename.png)
4. Check for the .NET platform version specified in IIS manager for you web site. Choose **v4.0.** version.
Click the **Application Pool** -> right-click the platform name -> **Set application Pool defaults** -> **.NET CLR version**
![platform](screenshots/platform.png)
5. Browse your web site with the IIS manager:
Right-click the site -> **Manage Website** -> **Browse**
![browse](screenshots/browse.png)
### Step 5. Checking accessibility
In case the example and Document Server are installed on different computers, make sure that your server with the example installed has access to the Document Server with the address which you specify instead of **documentserver** in the configuration files. And you must also make sure that the Document Server in its turn has access to the server with the example installed with the address which you specify instead of **example.com** in the configuration files.
If you integrated the editors successfully the result should look like the [demo preview](https://api.onlyoffice.com/editors/demopreview#DemoPreview) on our site.

View File

@ -1,16 +0,0 @@
For the ONLYOFFICE Applications example to work properly you need to do the following:
1. Download and extract the Example.zip into a directory selected for it, for instance, C:\OnlyofficeExample
2. Run the IIS Manager (C:\Windows\system32\inetsrv\InetMgr.exe or Start -> All Programs -> Administrative Tools -> Internet Information Services (IIS) Manager for Windows Server 2003)
3. Add the unpacked Example to the list of sites with the physical path to the C:\OnlyofficeExample (or the one you selected) folder.
4. Make sure that the user account under which the IIS NetworkService process is executed has the write access rights for the C:\OnlyofficeExample\App_Data folder (this is significant for the IIS later than 6.0).
5. Make the created ONLYOFFICE Applications example available through IP or domain name so that it could be connected from the web by the document service for proper document rendering.

View File

@ -1,6 +1,6 @@
/**
*
* (c) Copyright Ascensio System SIA 2020
* (c) Copyright Ascensio System SIA 2021
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -32,11 +32,13 @@ namespace OnlineEditorsExample
{
public class TrackManager
{
// read request body
public static Dictionary<string, object> readBody(HttpContext context)
{
string body;
try
{
// read request body by streams and check if it is correct
using (var receiveStream = context.Request.InputStream)
using (var readStream = new StreamReader(receiveStream))
{
@ -52,27 +54,29 @@ namespace OnlineEditorsExample
var jss = new JavaScriptSerializer();
var fileData = jss.Deserialize<Dictionary<string, object>>(body);
// check if the document token is enabled
if (JwtManager.Enabled)
{
string JWTheader = WebConfigurationManager.AppSettings["files.docservice.header"].Equals("") ? "Authorization" : WebConfigurationManager.AppSettings["files.docservice.header"];
string token = null;
// if the document token is in the data
if (fileData.ContainsKey("token"))
{
token = JwtManager.Decode(fileData["token"].ToString());
token = JwtManager.Decode(fileData["token"].ToString()); // decode it
}
else if (context.Request.Headers.AllKeys.Contains(JWTheader, StringComparer.InvariantCultureIgnoreCase))
else if (context.Request.Headers.AllKeys.Contains(JWTheader, StringComparer.InvariantCultureIgnoreCase)) // if the Authorization header exists
{
var headerToken = context.Request.Headers.Get(JWTheader).Substring("Bearer ".Length);
token = JwtManager.Decode(headerToken);
token = JwtManager.Decode(headerToken); // decode its part after Authorization prefix
}
else
else // otherwise, an error occurs
{
context.Response.Write("{\"error\":1,\"message\":\"JWT expected\"}");
}
if (token != null && !token.Equals(""))
if (token != null && !token.Equals("")) // invalid signature error
{
fileData = (Dictionary<string, object>)jss.Deserialize<Dictionary<string, object>>(token)["payload"];
}
@ -85,21 +89,25 @@ namespace OnlineEditorsExample
return fileData;
}
// file saving process
public static int processSave(Dictionary<string, object> fileData, string fileName, string userAddress)
{
var downloadUri = (string)fileData["url"];
var curExt = Path.GetExtension(fileName);
var downloadExt = Path.GetExtension(downloadUri) ?? "";
var curExt = Path.GetExtension(fileName).ToLower(); // get current file extension
var downloadExt = Path.GetExtension(downloadUri).ToLower() ?? ""; // get the extension of the downloaded file
var newFileName = fileName;
// convert downloaded file to the file with the current extension if these extensions aren't equal
if (!downloadExt.Equals(curExt, StringComparison.InvariantCultureIgnoreCase))
{
try
{
// convert file and give url to a new file
string newFileUri;
ServiceConverter.GetConvertedUri(downloadUri, downloadExt, curExt, ServiceConverter.GenerateRevisionId(downloadUri), false, out newFileUri);
if (string.IsNullOrEmpty(newFileUri))
{
// get the correct file name if it already exists
newFileName = _Default.GetCorrectName(Path.GetFileNameWithoutExtension(fileName) + downloadExt, userAddress);
}
else
@ -119,17 +127,18 @@ namespace OnlineEditorsExample
ServicePointManager.ServerCertificateValidationCallback += (s, ce, ca, p) => true;
}
var storagePath = _Default.StoragePath(newFileName, userAddress);
var histDir = _Default.HistoryDir(storagePath);
var storagePath = _Default.StoragePath(newFileName, userAddress); // get the file path
var histDir = _Default.HistoryDir(storagePath); // get the path to the history directory
if (!Directory.Exists(histDir)) Directory.CreateDirectory(histDir);
var versionDir = _Default.VersionDir(histDir, _Default.GetFileVersion(histDir));
if (!Directory.Exists(versionDir)) Directory.CreateDirectory(versionDir);
var versionDir = _Default.VersionDir(histDir, _Default.GetFileVersion(histDir)); // get the path to the file version
if (!Directory.Exists(versionDir)) Directory.CreateDirectory(versionDir); // if the path doesn't exist, create it
// get the path to the previous file version and rename the storage path with it
File.Copy(_Default.StoragePath(fileName, userAddress), Path.Combine(versionDir, "prev" + curExt));
DownloadToFile(downloadUri, storagePath);
DownloadToFile((string)fileData["changesurl"], Path.Combine(versionDir, "diff.zip"));
DownloadToFile(downloadUri, storagePath); // save file to the storage directory
DownloadToFile((string)fileData["changesurl"], Path.Combine(versionDir, "diff.zip")); // save file changes to the diff.zip archive
var hist = fileData.ContainsKey("changeshistory") ? (string)fileData["changeshistory"] : null;
if (string.IsNullOrEmpty(hist) && fileData.ContainsKey("history"))
@ -140,37 +149,40 @@ namespace OnlineEditorsExample
if (!string.IsNullOrEmpty(hist))
{
File.WriteAllText(Path.Combine(versionDir, "changes.json"), hist);
File.WriteAllText(Path.Combine(versionDir, "changes.json"), hist); // write the history changes to the changes.json file
}
File.WriteAllText(Path.Combine(versionDir, "key.txt"), (string)fileData["key"]);
File.WriteAllText(Path.Combine(versionDir, "key.txt"), (string)fileData["key"]); // write the key value to the key.txt file
string forcesavePath = _Default.ForcesavePath(newFileName, userAddress, false);
if (!forcesavePath.Equals(""))
string forcesavePath = _Default.ForcesavePath(newFileName, userAddress, false); // get the path to the forcesaved file version
if (!forcesavePath.Equals("")) // if the forcesaved file version exists
{
File.Delete(forcesavePath);
File.Delete(forcesavePath); // remove it
}
return 0;
}
// file force saving process
public static int processForceSave(Dictionary<string, object> fileData, string fileName, string userAddress)
{
var downloadUri = (string)fileData["url"];
string curExt = Path.GetExtension(fileName);
string downloadExt = Path.GetExtension(downloadUri);
var newFileName = fileName;
string curExt = Path.GetExtension(fileName).ToLower(); // get current file extension
string downloadExt = Path.GetExtension(downloadUri).ToLower(); // get the extension of the downloaded file
Boolean newFileName = false;
// convert downloaded file to the file with the current extension if these extensions aren't equal
if (!curExt.Equals(downloadExt))
{
try
{
// convert file and give url to a new file
string newFileUri;
var result = ServiceConverter.GetConvertedUri(downloadUri, downloadExt, curExt, ServiceConverter.GenerateRevisionId(downloadUri), false, out newFileUri);
if (string.IsNullOrEmpty(newFileUri))
{
newFileName = _Default.GetCorrectName(Path.GetFileNameWithoutExtension(fileName) + downloadExt, userAddress);
newFileName = true;
}
else
{
@ -179,7 +191,7 @@ namespace OnlineEditorsExample
}
catch (Exception)
{
newFileName = _Default.GetCorrectName(Path.GetFileNameWithoutExtension(fileName) + downloadExt, userAddress);
newFileName = true;
}
}
@ -190,22 +202,30 @@ namespace OnlineEditorsExample
}
string forcesavePath = "";
Boolean isSubmitForm = fileData["forcesavetype"].ToString().Equals("3");
Boolean isSubmitForm = fileData["forcesavetype"].ToString().Equals("3"); // SubmitForm
if (isSubmitForm)
if (isSubmitForm) // if the form is submitted
{
if (newFileName.Equals(fileName))
if (newFileName)
{
newFileName = _Default.GetCorrectName(fileName, userAddress);
fileName = _Default.GetCorrectName(Path.GetFileNameWithoutExtension(fileName) + "-form" + downloadExt, userAddress); // get the correct file name if it already exists
} else
{
fileName = _Default.GetCorrectName(Path.GetFileNameWithoutExtension(fileName) + "-form" + curExt, userAddress);
}
forcesavePath = _Default.StoragePath(newFileName, userAddress);
forcesavePath = _Default.StoragePath(fileName, userAddress);
}
else
{
forcesavePath = _Default.ForcesavePath(newFileName, userAddress, false);
if (forcesavePath.Equals(""))
if (newFileName)
{
forcesavePath = _Default.ForcesavePath(newFileName, userAddress, true);
fileName = _Default.GetCorrectName(Path.GetFileNameWithoutExtension(fileName) + downloadExt, userAddress);
}
forcesavePath = _Default.ForcesavePath(fileName, userAddress, false);
if (forcesavePath.Equals("")) // create forcesave path if it doesn't exist
{
forcesavePath = _Default.ForcesavePath(fileName, userAddress, true);
}
}
@ -216,13 +236,14 @@ namespace OnlineEditorsExample
var jss = new JavaScriptSerializer();
var actions = jss.Deserialize<List<object>>(jss.Serialize(fileData["actions"]));
var action = jss.Deserialize<Dictionary<string, object>>(jss.Serialize(actions[0]));
var user = action["userid"].ToString();
DocEditor.CreateMeta(newFileName, user, "Filling Form", userAddress);
var user = action["userid"].ToString(); // get the user id
DocEditor.CreateMeta(fileName, user, "Filling Form", userAddress); // create meta data for the forcesaved file
}
return 0;
}
// create a command request
public static void commandRequest(string method, string key)
{
string documentCommandUrl = WebConfigurationManager.AppSettings["files.docservice.url.site"] + WebConfigurationManager.AppSettings["files.docservice.url.command"];
@ -236,6 +257,7 @@ namespace OnlineEditorsExample
{ "key", key }
};
// check if a secret key to generate token exists or not
if (JwtManager.Enabled)
{
var payload = new Dictionary<string, object>
@ -243,10 +265,10 @@ namespace OnlineEditorsExample
{ "payload", body }
};
var payloadToken = JwtManager.Encode(payload);
var bodyToken = JwtManager.Encode(body);
var payloadToken = JwtManager.Encode(payload); // encode a payload object into a header token
var bodyToken = JwtManager.Encode(body); // encode body into a body token
string JWTheader = WebConfigurationManager.AppSettings["files.docservice.header"].Equals("") ? "Authorization" : WebConfigurationManager.AppSettings["files.docservice.header"];
request.Headers.Add(JWTheader, "Bearer " + payloadToken);
request.Headers.Add(JWTheader, "Bearer " + payloadToken); // add a header Authorization with a header token and Authorization prefix in it
body.Add("token", bodyToken);
}
@ -255,21 +277,23 @@ namespace OnlineEditorsExample
request.ContentLength = bytes.Length;
using (var requestStream = request.GetRequestStream())
{
// write bytes to the output stream
requestStream.Write(bytes, 0, bytes.Length);
}
string dataResponse;
using (var response = request.GetResponse())
using (var response = request.GetResponse()) // get the response
using (var stream = response.GetResponseStream())
{
if (stream == null) throw new Exception("Response is null");
using (var reader = new StreamReader(stream))
{
dataResponse = reader.ReadToEnd();
dataResponse = reader.ReadToEnd(); // and read it
}
}
// convert stream to json string
var jss = new JavaScriptSerializer();
var responseObj = jss.Deserialize<Dictionary<string, object>>(dataResponse);
if (!responseObj["error"].ToString().Equals("0"))
@ -278,13 +302,14 @@ namespace OnlineEditorsExample
}
}
// save file information from the url to the file specified
private static void DownloadToFile(string url, string path)
{
if (string.IsNullOrEmpty(url)) throw new ArgumentException("url");
if (string.IsNullOrEmpty(path)) throw new ArgumentException("path");
if (string.IsNullOrEmpty(url)) throw new ArgumentException("url"); // url isn't specified
if (string.IsNullOrEmpty(path)) throw new ArgumentException("path"); // file isn't specified
var req = (HttpWebRequest)WebRequest.Create(url);
using (var stream = req.GetResponse().GetResponseStream())
using (var stream = req.GetResponse().GetResponseStream()) // get input stream of the file information from the url
{
if (stream == null) throw new Exception("stream is null");
const int bufferSize = 4096;
@ -295,7 +320,7 @@ namespace OnlineEditorsExample
int readed;
while ((readed = stream.Read(buffer, 0, bufferSize)) != 0)
{
fs.Write(buffer, 0, readed);
fs.Write(buffer, 0, readed); // write bytes to the output stream
}
}
}

View File

@ -0,0 +1,104 @@
/**
*
* (c) Copyright Ascensio System SIA 2021
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
using System.Collections.Generic;
namespace OnlineEditorsExample
{
public class Users
{
static List<string> descr_user_1 = new List<string>()
{
"File author by default",
"He doesnt belong to any of the groups",
"He can review all the changes",
"The file favorite state is undefined"
};
static List<string> descr_user_2 = new List<string>()
{
"He belongs to Group2",
"He can review only his own changes or the changes made by the users who dont belong to any of the groups",
"This file is favorite"
};
static List<string> descr_user_3 = new List<string>()
{
"He belongs to Group3",
"He can review only the changes made by the users from Group2",
"This file isnt favorite",
"He cant copy data from the file into the clipboard",
"He cant download the file",
"He cant print the file"
};
static List<string> descr_user_0 = new List<string>()
{
"The user without a name. The name is requested upon the editor opening",
"He doesnt belong to any of the groups",
"He can review all the changes",
"The file favorite state is undefined"
};
private static List<User> users = new List<User>() {
new User("uid-1", "John Smith", "smith@mail.ru", null, null, null, new List<string>(), descr_user_1),
new User("uid-2", "Mark Pottato", "pottato@mail.ru", "group-2", new List<string>() { "group-2", "" }, true, new List<string>(), descr_user_2),
new User("uid-3", "Hamish Mitchell", "mitchell@mail.ru", "group-3", new List<string>() { "group-2" }, false, new List<string>() { "copy", "download", "print" }, descr_user_3),
new User("uid-0", null, null, null, null, null, new List<string>(), descr_user_0)
};
public static User getUser(string id)
{
foreach (User user in users)
{
if (user.id.Equals(id)) return user;
}
return users[0];
}
public static List<User> getAllUsers()
{
return users;
}
}
public class User
{
public string id;
public string name;
public string email;
public string group;
public List<string> reviewGroups;
public bool? favorite;
public List<string> deniedPermissions;
public List<string> descriptions;
public User(string id, string name, string email, string group, List<string> reviewGroups, bool? favorite, List<string> deniedPermissions, List<string> descriptions)
{
this.id = id;
this.name = name;
this.email = email;
this.group = group;
this.reviewGroups = reviewGroups;
this.favorite = favorite;
this.deniedPermissions = deniedPermissions;
this.descriptions = descriptions;
}
}
}

View File

@ -4,6 +4,7 @@ namespace OnlineEditorsExample
{
public static class Utils
{
// get the request header or return the default one
public static string GetOrDefault(this HttpRequest request, string header, string def)
{
var value = request[header];
@ -11,6 +12,7 @@ namespace OnlineEditorsExample
return def;
}
// get a cookie from the cookie collection or return the default one
public static string GetOrDefault(this HttpCookieCollection cookies, string cookie, string def)
{
var cook = cookies[cookie];

View File

@ -1,6 +1,6 @@
/**
*
* (c) Copyright Ascensio System SIA 2020
* (c) Copyright Ascensio System SIA 2021
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -23,6 +23,9 @@ using System.Web;
using System.Web.Script.Serialization;
using System.Web.Services;
using System.Diagnostics;
using System.Web.Configuration;
using System.Linq;
using System.Net;
namespace OnlineEditorsExample
{
@ -32,6 +35,7 @@ namespace OnlineEditorsExample
{
public void ProcessRequest(HttpContext context)
{
// define functions for each type of operation
switch (context.Request["type"])
{
case "upload":
@ -61,12 +65,16 @@ namespace OnlineEditorsExample
}
}
// upload a file
private static void Upload(HttpContext context)
{
context.Response.ContentType = "text/plain";
try
{
context.Response.Write("{ \"filename\": \"" + _Default.DoUpload(context) + "\"}");
var filename = _Default.DoUpload(context);
var documentType = _Default.DocumentType(filename);
// get file name of the uploading file and write it to the response
context.Response.Write("{ \"filename\": \"" + filename + "\", \"documentType\": \"" + documentType + "\"}");
}
catch (Exception e)
{
@ -74,11 +82,13 @@ namespace OnlineEditorsExample
}
}
// convert a file
private static void Convert(HttpContext context)
{
context.Response.ContentType = "text/plain";
try
{
// get file name of the converting file and write it to the response
context.Response.Write(_Default.DoConvert(context));
}
catch (Exception e)
@ -87,6 +97,7 @@ namespace OnlineEditorsExample
}
}
// define tracker status
private enum TrackerStatus
{
NotFound = 0,
@ -98,14 +109,16 @@ namespace OnlineEditorsExample
CorruptedForceSave = 7
}
// track file changes
private static void Track(HttpContext context)
{
// read request body
var fileData = TrackManager.readBody(context);
var userAddress = context.Request["userAddress"];
var fileName = Path.GetFileName(context.Request["fileName"]);
var status = (TrackerStatus) (int) fileData["status"];
var saved = 1;
var status = (TrackerStatus) (int) fileData["status"]; // get status from the request body
var saved = 1; // editing
switch (status)
{
case TrackerStatus.Editing:
@ -114,13 +127,13 @@ namespace OnlineEditorsExample
var jss = new JavaScriptSerializer();
var actions = jss.Deserialize<List<object>>(jss.Serialize(fileData["actions"]));
var action = jss.Deserialize<Dictionary<string, object>>(jss.Serialize(actions[0]));
if (action != null && action["type"].ToString().Equals("0"))
if (action != null && action["type"].ToString().Equals("0")) // finished edit
{
var user = action["userid"].ToString();
var user = action["userid"].ToString(); // the user who finished editing
var users = jss.Deserialize<List<object>>(jss.Serialize(fileData["users"]));
if (!users.Contains(user))
{
TrackManager.commandRequest("forcesave", fileData["key"].ToString());
TrackManager.commandRequest("forcesave", fileData["key"].ToString()); // create a command request with the forcesave method
}
}
@ -131,10 +144,12 @@ namespace OnlineEditorsExample
}
break;
// MustSave, Corrupted
case TrackerStatus.MustSave:
case TrackerStatus.Corrupted:
try
{
// saving a document
saved = TrackManager.processSave(fileData, fileName, userAddress);
}
catch (Exception e)
@ -144,10 +159,12 @@ namespace OnlineEditorsExample
context.Response.Write("{\"error\":" + saved + "}");
return;
// MustForceSave, CorruptedForceSave
case TrackerStatus.MustForceSave:
case TrackerStatus.CorruptedForceSave:
try
{
// force saving a document
saved = TrackManager.processForceSave(fileData, fileName, userAddress);
}
catch (Exception)
@ -160,6 +177,7 @@ namespace OnlineEditorsExample
context.Response.Write("{\"error\":0}");
}
// remove a file
private static void Remove(HttpContext context)
{
context.Response.ContentType = "text/plain";
@ -169,8 +187,8 @@ namespace OnlineEditorsExample
var path = _Default.StoragePath(fileName, HttpUtility.UrlEncode(HttpContext.Current.Request.UserHostAddress));
var histDir = _Default.HistoryDir(path);
if (File.Exists(path)) File.Delete(path);
if (Directory.Exists(histDir)) Directory.Delete(histDir, true);
if (File.Exists(path)) File.Delete(path); // delete file
if (Directory.Exists(histDir)) Directory.Delete(histDir, true); // delete file history
context.Response.Write("{ \"success\": true }");
}
@ -180,6 +198,7 @@ namespace OnlineEditorsExample
}
}
// get files information
private static void Files(HttpContext context)
{
List<Dictionary<string, object>> files = null;
@ -191,12 +210,12 @@ namespace OnlineEditorsExample
if (context.Request["fileId"] == null)
{
files = _Default.GetFilesInfo();
files = _Default.GetFilesInfo(); // get the information about the files from the storage path
context.Response.Write(jss.Serialize(files));
}
else
{
var fileId = context.Request["fileId"];
var fileId = context.Request["fileId"]; // get file id from the request
files = _Default.GetFilesInfo(fileId);
if (files.Count == 0)
{
@ -214,6 +233,7 @@ namespace OnlineEditorsExample
}
}
// get sample files from the assests
private static void Assets(HttpContext context)
{
var fileName = Path.GetFileName(context.Request["filename"]);
@ -221,6 +241,7 @@ namespace OnlineEditorsExample
download(filePath, context);
}
// download a csv file
private static void GetCsv(HttpContext context)
{
var fileName = "csv.csv";
@ -228,16 +249,36 @@ namespace OnlineEditorsExample
download(filePath, context);
}
// download a file
private static void Download(HttpContext context)
{
try
{
var fileName = Path.GetFileName(context.Request["filename"]);
var fileName = Path.GetFileName(context.Request["fileName"]);
var userAddress = Path.GetFileName(context.Request["userAddress"]);
var filePath = _Default.ForcesavePath(fileName, null, false);
if (JwtManager.Enabled)
{
string JWTheader = WebConfigurationManager.AppSettings["files.docservice.header"].Equals("") ? "Authorization" : WebConfigurationManager.AppSettings["files.docservice.header"];
if (context.Request.Headers.AllKeys.Contains(JWTheader, StringComparer.InvariantCultureIgnoreCase))
{
var headerToken = context.Request.Headers.Get(JWTheader).Substring("Bearer ".Length);
string token = JwtManager.Decode(headerToken);
if (token == null || token.Equals(""))
{
context.Response.StatusCode = (int)HttpStatusCode.Forbidden;
context.Response.Write("JWT validation failed");
return;
}
}
}
var filePath = _Default.ForcesavePath(fileName, userAddress, false); // get the path to the force saved document version
if (filePath.Equals(""))
{
filePath = _Default.StoragePath(fileName, null);
filePath = _Default.StoragePath(fileName, userAddress); // or to the original document
}
download(filePath, context);
}
@ -247,10 +288,11 @@ namespace OnlineEditorsExample
}
}
// download data from the url to the file
private static void download(string filePath, HttpContext context)
{
FileInfo fileinf = new FileInfo(filePath);
context.Response.AddHeader("Content-Length", "" + fileinf.Length);
context.Response.AddHeader("Content-Length", "" + fileinf.Length); // set headers to the response
context.Response.AddHeader("Content-Type", MimeMapping.GetMimeMapping(filePath));
var tmp = HttpUtility.UrlEncode(Path.GetFileName(filePath));
tmp = tmp.Replace("+", "%20");

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 96 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 146 KiB

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