Compare commits

..

168 Commits

Author SHA1 Message Date
3ec226109e Merge remote-tracking branch 'remotes/origin/feature/referenceData' into release/v7.3.0 2022-12-01 12:14:12 +03:00
b1f0fa6ecc nodejs: referenceData 2022-12-01 11:55:32 +03:00
b02ffff33e nodejs: do not send link in referenceData 2022-12-01 11:17:49 +03:00
f74f0ba376 Merge branch 'develop' into release/v7.3.0
# Conflicts:
#	.github/workflows/lint-python.yml
#	.github/workflows/lint-ruby.yml
#	CHANGELOG.md
#	web/documentserver-example/nodejs/app.js
2022-12-01 10:54:40 +03:00
96d3bf2e63 Merge remote-tracking branch 'remotes/origin/master' into develop
# Conflicts:
#	.github/workflows/lint-python.yml
#	.github/workflows/lint-ruby.yml
2022-12-01 10:49:29 +03:00
daf4f62acd nodejs: normal wopi url after release v7.1 (fd456f59e8) 2022-12-01 10:46:35 +03:00
ade8a07e95 nodejs: fix wopi after restart 2022-12-01 10:46:34 +03:00
8b613627d1 ci: github actions 2022-12-01 10:46:34 +03:00
3d3a10005c lang to changelog 2022-12-01 10:46:34 +03:00
801c451899 tooltip to changelog 2022-12-01 10:46:34 +03:00
df034c2af2 csharp-mvc: fixed tooltip 2022-12-01 10:46:33 +03:00
9726c06c84 csharp: fixed tooltip 2022-12-01 10:46:33 +03:00
3a45e1b0f3 python: fixed tooltip 2022-12-01 10:46:33 +03:00
ed8d0194b7 ruby: fixed tooltip 2022-12-01 10:46:32 +03:00
a59da2d5df php: fixed tooltip 2022-12-01 10:46:32 +03:00
f5c9a9e924 java: fixed tooltip 2022-12-01 10:46:32 +03:00
7b12b970c0 java-spring: fixed tooltip 2022-12-01 10:46:32 +03:00
87a11c8633 ruby: deleting uid cookie 2022-12-01 10:46:31 +03:00
01e0cefae5 ruby: deleting uid cookie 2022-12-01 10:46:31 +03:00
98d42249fa node: added fake language 2022-12-01 10:46:31 +03:00
fd9454dd5f csharp: added fake language 2022-12-01 10:46:30 +03:00
fbf4153dea csharp-mvc: added fake language 2022-12-01 10:46:30 +03:00
83b0411a4d php: added fake language 2022-12-01 10:46:30 +03:00
c60e4e25e2 python: added fake language 2022-12-01 10:46:30 +03:00
4ebbecf580 ruby: added fake language 2022-12-01 10:46:29 +03:00
6dbf383e2d java-spring: added fake language 2022-12-01 10:46:29 +03:00
1012bf13a6 java: added fake language 2022-12-01 10:46:29 +03:00
a24e081564 php: added request timeout for download 2022-12-01 10:46:28 +03:00
187ee212a9 csharp-mvc: added request timeout for download 2022-12-01 10:46:28 +03:00
106d9bfed3 csharp: added request timeout for download 2022-12-01 10:46:28 +03:00
13e243f900 python: added request status check for file 2022-12-01 10:46:28 +03:00
4ccc3fa35e ruby: added request status check for file 2022-12-01 10:46:27 +03:00
be1fa2da14 java: added request status check for file 2022-12-01 10:46:27 +03:00
b6645427a8 java-spring: added request status check for file 2022-12-01 10:46:27 +03:00
39d7c366e3 nodejs: init type argument (fix ab03bb5490) 2022-12-01 10:46:26 +03:00
075f464701 fix changelog about directUrl task 2022-12-01 10:46:26 +03:00
9414dff70c Change CHANGELOG.md 2022-12-01 10:46:26 +03:00
05b8989a87 csharp: option to send directUrl 2022-12-01 10:46:26 +03:00
43b6f53652 csharp-mvc: fix label for aspx 2022-12-01 10:46:25 +03:00
c22c0d72aa Change CHANGELOG.md 2022-12-01 10:46:25 +03:00
d61c112aa2 Change CHANGELOG.md 2022-12-01 10:46:25 +03:00
ae3def67f5 python: option to send directUrl 2022-12-01 10:46:24 +03:00
7c22ba4e9e csharp-mvc: option to send directUrl 2022-12-01 10:46:24 +03:00
320881f1cf Change CHANGELOG.md 2022-12-01 10:46:24 +03:00
90c31eb887 php: option to send directUrl 2022-12-01 10:46:24 +03:00
702d0f1aa8 Change CHANGELOG.md 2022-12-01 10:46:23 +03:00
dbf1047f29 ruby: option to send directUrl 2022-12-01 10:46:23 +03:00
0d27d142d4 Change CHANGELOG.md 2022-12-01 10:46:23 +03:00
807cbbf236 java: option to send directUrl 2022-12-01 10:46:23 +03:00
e6b0bfd0be Change CHANGELOG.md 2022-12-01 10:46:22 +03:00
943d059c7c java-spring: fix option to send directUrl 2022-12-01 10:46:22 +03:00
399ab0714d java-spring: option to send directUrl 2022-12-01 10:46:22 +03:00
8cabbe9c71 java-spring: tooltip fix 2022-12-01 10:46:21 +03:00
e40b6b2e28 java-spring: option to send directUrl 2022-12-01 10:46:21 +03:00
0a390094e5 java-spring: option to send directUrl 2022-12-01 10:46:21 +03:00
f7bb668f8b Merge pull request #317 from ONLYOFFICE/feature/fix-linter
Feature/fix linter
2022-12-01 09:52:11 +03:00
808712ad34 fix: rubocop 2022-12-01 09:48:00 +03:00
2b0ba914dc fix: pylint 2022-12-01 09:48:00 +03:00
249adaab48 fix: java linter 2022-12-01 09:48:00 +03:00
ee99a80ead fix: nodejs eslint 2022-12-01 09:48:00 +03:00
d61fdaaa53 nodejs: normal wopi url after release v7.1 (fd456f59e8) 2022-11-30 11:04:27 +03:00
270cbee160 nodejs: fix wopi after restart 2022-11-30 10:37:34 +03:00
e9721dd655 ci: github actions 2022-11-29 13:14:57 +03:00
a31a24a871 Merge pull request #313 from ONLYOFFICE/feature/actions
feature/actions
2022-11-29 13:13:50 +03:00
df0e197cb5 Merge pull request #315 from ONLYOFFICE/feature/fake-language
Feature/fake language
2022-11-28 16:53:24 +03:00
09802afc6f lang to changelog 2022-11-28 16:52:06 +03:00
1c43679d87 Merge remote-tracking branch 'remotes/origin/develop' into feature/fake-language 2022-11-28 16:50:53 +03:00
573eeb6e18 node: added fake language 2022-11-28 16:49:47 +03:00
78cf6c35f8 csharp: added fake language 2022-11-28 16:49:47 +03:00
c7f5003d69 csharp-mvc: added fake language 2022-11-28 16:49:46 +03:00
19baff4340 php: added fake language 2022-11-28 16:49:46 +03:00
cc5c912658 Merge pull request #312 from ONLYOFFICE/bugfix/tooltip-fix
Bugfix/tooltip fix
2022-11-28 16:34:22 +03:00
64f2d605c2 tooltip to changelog 2022-11-28 16:33:43 +03:00
c9fca685bf Merge pull request #311 from ONLYOFFICE/bugfix/delete-uid-cookie
ruby: deleting uid cookie
2022-11-28 16:22:37 +03:00
820883a584 python: added fake language 2022-11-24 13:15:33 +03:00
05a00a33a3 ruby: added fake language 2022-11-24 13:14:19 +03:00
613cb713cc java-spring: added fake language 2022-11-24 13:13:45 +03:00
9216ff3a97 java: added fake language 2022-11-24 13:12:51 +03:00
dbaa7c5113 Merge pull request #310 from ONLYOFFICE/bugfix/file-request-status
Bugfix/file request status
2022-11-21 13:25:47 +03:00
d6ad145111 nodejs: init type argument (fix ab03bb5490) 2022-11-18 13:51:11 +03:00
456df162e6 ci: github actions 2022-11-16 17:53:02 +05:00
50fd47cf7c csharp-mvc: fixed tooltip 2022-11-15 14:33:15 +03:00
f9c0da1696 csharp: fixed tooltip 2022-11-15 14:31:57 +03:00
a7807513c6 python: fixed tooltip 2022-11-15 13:55:25 +03:00
128430d698 ruby: fixed tooltip 2022-11-15 13:52:52 +03:00
8077a66f16 php: fixed tooltip 2022-11-15 13:51:15 +03:00
b3d8695a26 java: fixed tooltip 2022-11-15 13:23:24 +03:00
00872758ee java-spring: fixed tooltip 2022-11-15 13:00:15 +03:00
3301c24de5 ruby: deleting uid cookie 2022-11-15 12:09:03 +03:00
dd0c049a70 ruby: deleting uid cookie 2022-11-15 10:55:02 +03:00
44fb3a089c php: added request timeout for download 2022-11-11 14:58:36 +03:00
513bf99adb csharp-mvc: added request timeout for download 2022-11-11 12:23:39 +03:00
6f92633ef8 csharp: added request timeout for download 2022-11-11 12:23:28 +03:00
b67e768dce python: added request status check for file 2022-11-10 19:07:17 +03:00
751a886bfa ruby: added request status check for file 2022-11-10 19:06:29 +03:00
66ea4b144b java: added request status check for file 2022-11-10 19:05:32 +03:00
7a73422231 java-spring: added request status check for file 2022-11-10 19:04:49 +03:00
5319e18fb5 Merge pull request #309 from ONLYOFFICE/release/1.4.0
Release/1.4.0
2022-11-08 16:37:37 +03:00
93accdac7c nodejs: do not send key in referenceData 2022-11-08 16:33:19 +03:00
def268f5f2 Merge remote-tracking branch 'remotes/origin/release/1.4.0' into develop 2022-11-08 10:42:00 +03:00
6054bffb3f Merge pull request #305 from ONLYOFFICE/dependabot/maven/web/documentserver-example/java-spring/com.fasterxml.jackson.core-jackson-databind-2.13.4.1
build(deps): bump jackson-databind from 2.12.6.1 to 2.13.4.1 in /web/documentserver-example/java-spring
2022-11-08 10:31:57 +03:00
a7c917db3f Merge remote-tracking branch 'remotes/origin/release/1.4.0' into develop 2022-11-08 09:18:02 +03:00
30481005a1 removed enum Language (Fix Bug 59624) 2022-11-08 09:17:30 +03:00
5544768500 set language from cookies (Fix Bug 59352) 2022-11-08 09:17:22 +03:00
14e53970c8 update pyjwt=2.6.0 (Fix Bug 59369) 2022-11-08 09:16:37 +03:00
82efd0f18a fix 848cfb20bc 2022-11-07 14:23:01 +03:00
8ce90d89ed removed enum Language (Fix Bug 59624) 2022-11-07 13:07:34 +03:00
2b184972dc Merge pull request #306 from ONLYOFFICE/dependabot/bundler/web/documentserver-example/ruby/nokogiri-1.13.9
build(deps): bump nokogiri from 1.13.8 to 1.13.9 in /web/documentserver-example/ruby
2022-11-03 14:46:55 +03:00
0fb9da4d89 update pom.xml 2022-11-03 14:11:05 +03:00
9277d3de58 Merge branch 'feature/optionDirectUrl' into develop 2022-11-03 13:34:47 +03:00
baf7a1e5dd fix changelog about directUrl task 2022-11-03 13:34:15 +03:00
e2a14a74db Merge pull request #308 from ONLYOFFICE/feature/optionDirectUrl
Feature/option direct url
2022-11-03 13:33:20 +03:00
848cfb20bc set language from cookies (Fix Bug 59352) 2022-11-03 12:05:53 +03:00
ddd3ec82a8 update pyjwt=2.6.0 (Fix Bug 59369) 2022-11-03 10:47:39 +03:00
0ed08fd7b2 Change CHANGELOG.md 2022-11-02 14:58:12 +03:00
e1c5907003 csharp: option to send directUrl 2022-11-02 14:54:33 +03:00
9dd2d7c0db csharp-mvc: fix label for aspx 2022-11-02 14:49:40 +03:00
8f0cbb78af Change CHANGELOG.md 2022-11-02 13:10:39 +03:00
72e48914aa Merge branch 'feature/optionDirectUrl' of https://github.com/ONLYOFFICE/document-server-integration into feature/optionDirectUrl 2022-11-02 13:05:45 +03:00
82a282029a csharp-mvc: option to send directUrl 2022-11-02 13:05:08 +03:00
9b7c12b5c0 Change CHANGELOG.md 2022-11-01 23:10:46 +03:00
6ea5546099 python: option to send directUrl 2022-11-01 23:09:36 +03:00
92fbd1e293 Change CHANGELOG.md 2022-10-28 16:48:05 +03:00
855c1ed9f9 php: option to send directUrl 2022-10-28 16:47:08 +03:00
7e60ec15fd Change CHANGELOG.md 2022-10-28 13:56:28 +03:00
3697a4a888 ruby: option to send directUrl 2022-10-28 13:55:48 +03:00
0b8107d167 Change CHANGELOG.md 2022-10-28 13:52:11 +03:00
885850ee33 java: option to send directUrl 2022-10-27 14:32:21 +03:00
98c61250a6 Change CHANGELOG.md 2022-10-26 16:54:16 +03:00
457487844c java-spring: fix option to send directUrl 2022-10-26 16:47:43 +03:00
ff72956b68 java-spring: option to send directUrl 2022-10-26 16:41:59 +03:00
1593df6aec build(deps): bump nokogiri in /web/documentserver-example/ruby
Bumps [nokogiri](https://github.com/sparklemotion/nokogiri) from 1.13.8 to 1.13.9.
- [Release notes](https://github.com/sparklemotion/nokogiri/releases)
- [Changelog](https://github.com/sparklemotion/nokogiri/blob/main/CHANGELOG.md)
- [Commits](https://github.com/sparklemotion/nokogiri/compare/v1.13.8...v1.13.9)

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

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

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-10-19 07:08:15 +00:00
1bdb3c03bc Merge remote-tracking branch 'remotes/origin/feature/referenceData' into develop 2022-10-14 10:22:24 +03:00
111dc14f2b nodejs: referenceData 2022-10-14 10:20:45 +03:00
4a656c025f 1.4.0 2022-10-14 10:12:48 +03:00
ce9930e5bc java-spring: fixed footer positioning 2022-10-12 11:12:59 +03:00
9da22d7803 java-spring: fixed sorting of the list of languages 2022-10-12 11:00:01 +03:00
d78c677c99 java: fixed sorting of the list of languages 2022-10-12 10:59:41 +03:00
b204142c13 csharp: include assets 2022-10-11 18:04:21 +03:00
fd1c26ab9f csharp-mvc: reload refs 2022-10-11 17:53:14 +03:00
5993d10bee csharp-mvc: fix ref 2022-10-11 17:23:16 +03:00
c5771c9008 sharp-mvc: Fix merge 24aee6d194 2022-10-11 17:22:49 +03:00
2fad227272 Merge remote-tracking branch 'remotes/origin/release/v7.2.0' into develop 2022-10-05 13:33:43 +03:00
ada438ff0b Merge remote-tracking branch 'remotes/origin/develop' into release/v7.2.0 2022-09-28 09:13:23 +03:00
0dbd65a577 ruby: rails 7.0.3.1 2022-09-27 19:03:26 +03:00
48e5b8d4e0 Merge pull request #304 from ONLYOFFICE/dependabot/nuget/web/documentserver-example/csharp/Newtonsoft.Json-13.0.1
build(deps): bump Newtonsoft.Json from 10.0.3 to 13.0.1 in /web/documentserver-example/csharp
2022-09-27 18:26:31 +03:00
7f08a96681 Merge remote-tracking branch 'remotes/origin/develop' into dependabot/nuget/web/documentserver-example/csharp/Newtonsoft.Json-13.0.1
# Conflicts:
#	web/documentserver-example/csharp/packages.config
2022-09-27 18:26:07 +03:00
3549b4bc2a csharp: Newtonsoft.Json update 2022-09-27 18:24:53 +03:00
c9265d9ddc csharp-mvc: fix dep path 2022-09-27 18:08:47 +03:00
44d9ca88c6 build(deps): bump Newtonsoft.Json in /web/documentserver-example/csharp
Bumps [Newtonsoft.Json](https://github.com/JamesNK/Newtonsoft.Json) from 10.0.3 to 13.0.1.
- [Release notes](https://github.com/JamesNK/Newtonsoft.Json/releases)
- [Commits](https://github.com/JamesNK/Newtonsoft.Json/compare/10.0.3...13.0.1)

---
updated-dependencies:
- dependency-name: Newtonsoft.Json
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-09-27 14:59:15 +00:00
d964b43087 Merge pull request #303 from ONLYOFFICE/develop
Release/v1.3.0
2022-09-27 17:58:46 +03:00
5a0debd9e8 Merge remote-tracking branch 'remotes/origin/develop' into release/v7.2.0 2022-09-27 17:55:26 +03:00
3b0f942eee Merge pull request #302 from ONLYOFFICE/feature/ruby-3.0.0
support ruby v.3
2022-09-27 17:54:59 +03:00
4ee110c2d5 Merge remote-tracking branch 'remotes/origin/develop' into release/v7.2.0
# Conflicts:
#	web/documentserver-example/nodejs/views/config.ejs
#	web/documentserver-example/ruby/app/models/document_helper.rb
2022-09-15 17:17:24 +03:00
ad1d93dd20 Merge pull request #301 from ONLYOFFICE/bugfix/file-request
added request status check for file
2022-09-15 14:43:19 +03:00
d2d98df5ab support ruby v.3 2022-09-01 16:56:38 +03:00
7805f7dc91 added request status check for file 2022-09-01 09:34:30 +03:00
51ec27d67c nodejs: removed trailing comma 2022-08-25 15:47:10 +03:00
9e94716df0 nodejs: reorder config items 2022-08-16 10:15:39 +03:00
988a8339b1 ruby: ERB::Util.url instead URI::encode 2022-08-15 11:10:02 +03:00
91 changed files with 4984 additions and 601 deletions

31
.github/workflows/lint-java.yml vendored Normal file
View File

@ -0,0 +1,31 @@
name: Lint Java
on:
workflow_dispatch:
push:
branches: [master, main]
paths: ['web/documentserver-example/java/**']
pull_request:
branches: [master, main, develop]
paths: ['web/documentserver-example/java/**']
jobs:
lint:
runs-on: ubuntu-latest
defaults:
run:
working-directory: ./web/documentserver-example/java
steps:
- name: Checkout Repository
uses: actions/checkout@v3
- name: Install Java 11
uses: actions/setup-java@v3
with:
distribution: 'temurin'
java-version: '11'
- name: Run linter
run: |
mvn -version
mvn package

35
.github/workflows/lint-nodejs.yml vendored Normal file
View File

@ -0,0 +1,35 @@
name: ESLint
on:
workflow_dispatch:
push:
branches: [master, main]
paths: ['web/documentserver-example/nodejs/**']
pull_request:
branches: [master, main, develop]
paths: ['web/documentserver-example/nodejs/**']
env:
NODE_VERSION: 16
jobs:
lint:
name: Lint
runs-on: ubuntu-latest
defaults:
run:
working-directory: ./web/documentserver-example/nodejs
steps:
- name: Install NodeJS
uses: actions/setup-node@v3
with:
node-version: ${{ env.NODE_VERSION }}
- name: Code Checkout
uses: actions/checkout@v3
- name: Install Dependencies
run: npm ci
- name: Code Linting
run: npm run lint

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

@ -0,0 +1,29 @@
name: PHPCs
on:
workflow_dispatch:
push:
branches: [master, main]
paths: ['web/documentserver-example/php/**']
pull_request:
branches: [master, main, develop]
paths: ['web/documentserver-example/php/**']
jobs:
lint:
runs-on: ubuntu-latest
defaults:
run:
working-directory: ./web/documentserver-example/php
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: '8.1'
tools: cs2pr, phpcs
- name: Run phpcs
run: phpcs -q --extensions=php,module,inc,install,test,profile,theme,css,info,txt,md,yml --ignore=node_modules,bower_components,vendor ./

40
.github/workflows/lint-python.yml vendored Normal file
View File

@ -0,0 +1,40 @@
name: PyLint
on:
workflow_dispatch:
push:
branches: [master, main]
paths: ['web/documentserver-example/python/**']
pull_request:
branches: [master, main, develop]
paths: ['web/documentserver-example/python/**']
jobs:
lint:
runs-on: ubuntu-latest
defaults:
run:
working-directory: ./web/documentserver-example/python
steps:
- uses: actions/checkout@v3
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.10'
- name: Install Dependencies
run: |
python -m pip install --upgrade pip
pip install flake8
pip install pylint
if [ -f requirements.txt ]; then pip install -r requirements.txt; fi
- name: Lint Flake8
run: |
flake8 ./**/*.py --count --select=E9,F63,F7,F82 --show-source --statistics
flake8 ./**/*.py --count --max-complexity=10 --max-line-length=79 --statistics
- name: Lint Pylint
run: |
pylint ./**/*.py

31
.github/workflows/lint-ruby.yml vendored Normal file
View File

@ -0,0 +1,31 @@
name: Rubocop
on:
workflow_dispatch:
push:
branches: [master, main]
paths: ['web/documentserver-example/ruby/**']
pull_request:
branches: [master, main, develop]
paths: ['web/documentserver-example/ruby/**']
jobs:
lint:
runs-on: ubuntu-latest
defaults:
run:
working-directory: ./web/documentserver-example/ruby
steps:
- name: Checkout Repository
uses: actions/checkout@v3
- uses: ruby/setup-ruby@v1
with:
ruby-version: '3.0'
bundler-cache: true
- name: Install dependencies
run: |
bundle install
- name: Rubocop
run: |
gem install rubocop
rubocop

31
.github/workflows/lint-spring.yml vendored Normal file
View File

@ -0,0 +1,31 @@
name: Lint Spring
on:
workflow_dispatch:
push:
branches: [master, main]
paths: ['web/documentserver-example/java-spring/**']
pull_request:
branches: [master, main, develop]
paths: ['web/documentserver-example/java-spring/**']
jobs:
lint:
runs-on: ubuntu-latest
defaults:
run:
working-directory: ./web/documentserver-example/java-spring
steps:
- name: Checkout Repository
uses: actions/checkout@v3
- name: Install Java 11
uses: actions/setup-java@v3
with:
distribution: 'temurin'
java-version: '11'
- name: Run linter
run: |
mvn -version
mvn package

View File

@ -1,10 +1,21 @@
# Change Log
- nodejs: fix wopi actions after restart
- setting an unavailable language
- description in the tooltip on the main page
- nodejs: referenceData
- option to send directUrl
## 1.4.0
- nodejs: option to send directUrl
- opening file on client by directUrl
- offline viewer for anonymous
- added hy, eu, zh-TW, ms, pt-PT
## 1.3.1
- charp: fix references
- ruby: update rails
## 1.3.0
- update empty files
- anonymous without chat
@ -29,6 +40,5 @@
- creating docxf
- opening docxf, oform
## 1.0.0
- added java spring

View File

@ -167,7 +167,7 @@ label .checkbox {
background-image: url("images/file_docxf.svg");
}
.create-sample {
.side-option {
color: #666666;
line-height: 24px;
}
@ -740,3 +740,28 @@ html {
.user-descr > b {
margin-left: 25px;
}
.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;
left: -4px;
position: absolute;
top: 50%;
transform: translate(-50%, -50%);
}

View File

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

View File

@ -334,7 +334,7 @@ namespace OnlineEditorsExampleMVC.Helpers
// get url to download a file
public static string GetDownloadUrl(string fileName, Boolean isServer = true)
{
var userAddress = isServer ? "&userAddress=" + HttpUtility.UrlEncode(HttpContext.Current.Request.UserHostAddress) : "";
var userAddress = isServer ? "&userAddress=" + HttpUtility.UrlEncode(CurUserHostAddress(HttpContext.Current.Request.UserHostAddress)) : "";
var downloadUrl = new UriBuilder(GetServerUrl(isServer))
{
Path =
@ -343,7 +343,6 @@ namespace OnlineEditorsExampleMVC.Helpers
+ "webeditor.ashx",
Query = "type=download"
+ "&fileName=" + HttpUtility.UrlEncode(fileName)
+ "&userAddress=" + HttpUtility.UrlEncode(CurUserHostAddress(HttpContext.Current.Request.UserHostAddress))
+ userAddress
};
return downloadUrl.ToString();
@ -443,5 +442,11 @@ namespace OnlineEditorsExampleMVC.Helpers
}
return languages;
}
public static string GetDirectUrl()
{
string isEnabledDirectUrl = HttpUtility.ParseQueryString(HttpContext.Current.Request.Url.Query).Get("directUrl");
return isEnabledDirectUrl != null ? isEnabledDirectUrl : "false";
}
}
}

View File

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

View File

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

View File

@ -53,49 +53,49 @@
<Reference Include="System.Web" />
<Reference Include="System.Web.Extensions" />
<Reference Include="System.Web.Services" />
<Reference Include="Antlr3.Runtime">
<Reference Include="Antlr3.Runtime, Version=3.5.0.2, Culture=neutral, PublicKeyToken=eb42632606e9261f, processorArchitecture=MSIL">
<HintPath>packages\Antlr.3.5.0.2\lib\Antlr3.Runtime.dll</HintPath>
</Reference>
<Reference Include="EntityFramework">
<Reference Include="EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL">
<HintPath>packages\EntityFramework.6.4.4\lib\net45\EntityFramework.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Web.Infrastructure">
<Reference Include="Microsoft.Web.Infrastructure, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>packages\Microsoft.Web.Infrastructure.1.0.0.0\lib\net40\Microsoft.Web.Infrastructure.dll</HintPath>
</Reference>
<Reference Include="Newtonsoft.Json">
<HintPath>packages\Newtonsoft.Json.12.0.3\lib\net45\Newtonsoft.Json.dll</HintPath>
<Reference Include="Newtonsoft.Json, Version=13.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<HintPath>packages\Newtonsoft.Json.13.0.1\lib\net45\Newtonsoft.Json.dll</HintPath>
</Reference>
<Reference Include="System.Net.Http.Formatting">
<Reference Include="System.Net.Http.Formatting, Version=5.2.7.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>packages\Microsoft.AspNet.WebApi.Client.5.2.7\lib\net45\System.Net.Http.Formatting.dll</HintPath>
</Reference>
<Reference Include="System.Web.Helpers">
<Reference Include="System.Web.Helpers, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>packages\Microsoft.AspNet.WebPages.3.2.7\lib\net45\System.Web.Helpers.dll</HintPath>
</Reference>
<Reference Include="System.Web.Http">
<Reference Include="System.Web.Http, Version=5.2.7.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>packages\Microsoft.AspNet.WebApi.Core.5.2.7\lib\net45\System.Web.Http.dll</HintPath>
</Reference>
<Reference Include="System.Web.Http.WebHost">
<Reference Include="System.Web.Http.WebHost, Version=5.2.7.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>packages\Microsoft.AspNet.WebApi.WebHost.5.2.7\lib\net45\System.Web.Http.WebHost.dll</HintPath>
</Reference>
<Reference Include="System.Web.Mvc">
<Reference Include="System.Web.Mvc, Version=5.2.7.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>packages\Microsoft.AspNet.Mvc.5.2.7\lib\net45\System.Web.Mvc.dll</HintPath>
</Reference>
<Reference Include="System.Web.Optimization">
<Reference Include="System.Web.Optimization, Version=1.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>packages\Microsoft.AspNet.Web.Optimization.1.1.3\lib\net40\System.Web.Optimization.dll</HintPath>
</Reference>
<Reference Include="System.Web.Razor">
<Reference Include="System.Web.Razor, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>packages\Microsoft.AspNet.Razor.3.2.7\lib\net45\System.Web.Razor.dll</HintPath>
</Reference>
<Reference Include="System.Web.WebPages">
<Reference Include="System.Web.WebPages, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>packages\Microsoft.AspNet.WebPages.3.2.7\lib\net45\System.Web.WebPages.dll</HintPath>
</Reference>
<Reference Include="System.Web.WebPages.Deployment">
<Reference Include="System.Web.WebPages.Deployment, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>packages\Microsoft.AspNet.WebPages.3.2.7\lib\net45\System.Web.WebPages.Deployment.dll</HintPath>
</Reference>
<Reference Include="System.Web.WebPages.Razor">
<Reference Include="System.Web.WebPages.Razor, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>packages\Microsoft.AspNet.WebPages.3.2.7\lib\net45\System.Web.WebPages.Razor.dll</HintPath>
</Reference>
<Reference Include="WebGrease">
<Reference Include="WebGrease, Version=1.6.5135.21930, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>packages\WebGrease.1.6.0\lib\WebGrease.dll</HintPath>
</Reference>
</ItemGroup>
@ -185,10 +185,12 @@
<Content Include="assets\AUTHORS.md" />
<Content Include="assets\LICENSE" />
<Content Include="assets\new\new.docx" />
<Content Include="assets\new\new.docxf" />
<Content Include="assets\new\new.pptx" />
<Content Include="assets\new\new.xlsx" />
<Content Include="assets\sample\csv.csv" />
<Content Include="assets\sample\sample.docx" />
<Content Include="assets\sample\sample.docxf" />
<Content Include="assets\sample\sample.pptx" />
<Content Include="assets\sample\sample.xlsx" />
<None Include="packages.config" />

View File

@ -16,11 +16,24 @@
*
*/
var directUrl;
if (typeof jQuery != "undefined") {
jq = jQuery.noConflict();
directUrl = getUrlVars()["directUrl"] == "true";
mustReload = false;
if (directUrl)
jq("#directUrl").prop("checked", directUrl);
else
directUrl = jq("#directUrl").prop("checked");
jq("#directUrl").change(function () {
window.location = "?directUrl=" + jq(this).prop("checked");
});
jq(function () {
jq('#fileupload').fileupload({
dataType: 'json',
@ -219,7 +232,7 @@ if (typeof jQuery != "undefined") {
jq(document).on("click", "#beginEdit:not(.disable)", function () {
var fileId = encodeURIComponent(jq('#hiddenFileName').val());
var url = UrlEditor + "?fileName=" + fileId;
var url = UrlEditor + "?fileName=" + fileId + "&directUrl=" + directUrl;
window.open(url, "_blank");
jq('#hiddenFileName').val("");
jq.unblockUI();
@ -227,7 +240,7 @@ if (typeof jQuery != "undefined") {
jq(document).on("click", "#beginView:not(.disable)", function () {
var fileId = encodeURIComponent(jq('#hiddenFileName').val());
var url = UrlEditor + "?editorsMode=view&fileName=" + fileId;
var url = UrlEditor + "?editorsMode=view&fileName=" + fileId + "&directUrl=" + directUrl;
window.open(url, "_blank");
jq('#hiddenFileName').val("");
jq.unblockUI();
@ -235,7 +248,7 @@ if (typeof jQuery != "undefined") {
jq(document).on("click", "#beginEmbedded:not(.disable)", function () {
var fileId = encodeURIComponent(jq('#hiddenFileName').val());
var url = UrlEditor + "?editorsType=embedded&editorsMode=embedded&fileName=" + fileId;
var url = UrlEditor + "?editorsType=embedded&editorsMode=embedded&fileName=" + fileId + "&directUrl=" + directUrl;
jq("#mainProgress").addClass("embedded");
jq("#beginEmbedded").addClass("disable");
@ -289,6 +302,17 @@ if (typeof jQuery != "undefined") {
}
};
function getUrlVars() {
var vars = [], hash;
var hashes = window.location.href.slice(window.location.href.indexOf('?') + 1).split('&');
for (var i = 0; i < hashes.length; i++) {
hash = hashes[i].split('=');
vars.push(hash[0]);
vars[hash[0]] = hash[1];
}
return vars;
};
var fileList = jq("tr.tableRow");
var mouseIsOverTooltip = false;
@ -299,12 +323,12 @@ if (typeof jQuery != "undefined") {
if (hideTooltipTimeout != null) {
clearTimeout(hideTooltipTimeout);
}
jq(".info").on("touchend", function () {
jq("#info").on("touchend", function () {
showUserTooltip(true);
});
}
} else {
jq(".info").mouseover(function (event) {
jq("#info").mouseover(function (event) {
if (fileList.length > 0) {
if (hideTooltipTimeout != null) {
clearTimeout(hideTooltipTimeout);
@ -328,4 +352,18 @@ if (typeof jQuery != "undefined") {
}, 500);
});
}
jq(".info-tooltip").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 class='arrow'></div></div>").appendTo("body");
var top = jq("#" + id).offset().top + jq("#" + id).outerHeight() / 2 - jq("div.tooltip").outerHeight() / 2;
var left = jq("#" + id).offset().left + jq("#" + id).outerWidth() + 20;
jq("div.tooltip").css({ "top": top, "left": left });
}).mouseout(function () {
jq("div.tooltip").remove();
});
}

View File

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

View File

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<!--
For more information on how to configure your ASP.NET application, please visit
http://go.microsoft.com/fwlink/?LinkId=152368
@ -26,11 +26,11 @@
</system.web>
<system.webServer>
<validation validateIntegratedModeConfiguration="false" />
<httpProtocol>
<customHeaders>
<add name="Access-Control-Allow-Origin" value="*" />
</customHeaders>
</httpProtocol>
<httpProtocol>
<customHeaders>
<add name="Access-Control-Allow-Origin" value="*" />
</customHeaders>
</httpProtocol>
<handlers>
<remove name="ExtensionlessUrlHandler-Integrated-4.0" />
<remove name="OPTIONSVerbHandler" />
@ -46,13 +46,21 @@
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" />
<bindingRedirect oldVersion="0.0.0.0-12.0.0.0" newVersion="12.0.0.0" />
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-13.0.0.0" newVersion="13.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="WebGrease" publicKeyToken="31bf3856ad364e35" />
<assemblyIdentity name="WebGrease" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-1.6.5135.21930" newVersion="1.6.5135.21930" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Web.Helpers" publicKeyToken="31bf3856ad364e35" />
<bindingRedirect oldVersion="1.0.0.0-3.0.0.0" newVersion="3.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Web.WebPages" publicKeyToken="31bf3856ad364e35" />
<bindingRedirect oldVersion="1.0.0.0-3.0.0.0" newVersion="3.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" />
<bindingRedirect oldVersion="1.0.0.0-5.2.7.0" newVersion="5.2.7.0" />
@ -63,7 +71,4 @@
</dependentAssembly>
</assemblyBinding>
</runtime>
<entityFramework>
<defaultConnectionFactory type="System.Data.Entity.Infrastructure.SqlConnectionFactory, EntityFramework" />
</entityFramework>
</configuration>

View File

@ -1,17 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Antlr" version="3.5.0.2" targetFramework="net45" />
<package id="EntityFramework" version="6.4.4" targetFramework="net45" />
<package id="Antlr" version="3.5.0.2" targetFramework="net48" />
<package id="EntityFramework" version="6.4.4" targetFramework="net48" />
<package id="JWT" version="9.0.3" targetFramework="net48" />
<package id="Microsoft.AspNet.Mvc" version="5.2.7" targetFramework="net45" />
<package id="Microsoft.AspNet.Razor" version="3.2.7" targetFramework="net45" />
<package id="Microsoft.AspNet.Web.Optimization" version="1.1.3" targetFramework="net45" />
<package id="Microsoft.AspNet.WebApi.Client" version="5.2.7" targetFramework="net45" />
<package id="Microsoft.AspNet.WebApi.Core" version="5.2.7" targetFramework="net45" />
<package id="Microsoft.AspNet.WebApi.WebHost" version="5.2.7" targetFramework="net45" />
<package id="Microsoft.AspNet.WebPages" version="3.2.7" targetFramework="net45" />
<package id="Microsoft.CSharp" version="4.7.0" targetFramework="net45" />
<package id="Microsoft.Web.Infrastructure" version="1.0.0.0" targetFramework="net45" />
<package id="Newtonsoft.Json" version="13.0.1" targetFramework="net45" />
<package id="WebGrease" version="1.6.0" targetFramework="net45" />
<package id="Microsoft.AspNet.Mvc" version="5.2.7" targetFramework="net48" />
<package id="Microsoft.AspNet.Razor" version="3.2.7" targetFramework="net48" />
<package id="Microsoft.AspNet.Web.Optimization" version="1.1.3" targetFramework="net48" />
<package id="Microsoft.AspNet.WebApi.Client" version="5.2.7" targetFramework="net48" />
<package id="Microsoft.AspNet.WebApi.Core" version="5.2.7" targetFramework="net48" />
<package id="Microsoft.AspNet.WebApi.WebHost" version="5.2.7" targetFramework="net48" />
<package id="Microsoft.AspNet.WebPages" version="3.2.7" targetFramework="net48" />
<package id="Microsoft.CSharp" version="4.7.0" targetFramework="net48" />
<package id="Microsoft.Web.Infrastructure" version="1.0.0.0" targetFramework="net48" />
<package id="Newtonsoft.Json" version="13.0.1" targetFramework="net48" />
<package id="WebGrease" version="1.6.0" targetFramework="net48" />
</packages>

View File

@ -1,7 +1,7 @@
<?xml version="1.0"?>
<appSettings>
<clear />
<add key="version" value="1.3.0"/>
<add key="version" value="1.4.0"/>
<add key="filesize-max" value="52428800"/>
<add key="storage-path" value=""/>
@ -16,7 +16,7 @@
<add key="files.docservice.verify-peer-off" value="true"/>
<add key="files.docservice.languages" value="en:English|hy:Armenian|az:Azerbaijani|eu:Basque|be:Belarusian|bg:Bulgarian|ca:Catalan|zh:Chinese (People's Republic of China)|zh-TW:Chinese (Traditional, Taiwan)|cs:Czech|da:Danish|nl:Dutch|fi:Finnish|fr:French|gl:Galego|de:German|el:Greek|hu:Hungarian|id:Indonesian|it:Italian|ja:Japanese|ko:Korean|lv:Latvian|lo:Lao|ms:Malay (Malaysia)|nb:Norwegian|pl:Polish|pt:Portuguese (Brazil)|pt-PT:Portuguese (Portugal)|ro:Romanian|ru:Russian|sk:Slovak|sl:Slovenian|es:Spanish|sv:Swedish|tr:Turkish|uk:Ukrainian|vi:Vietnamese"/>
<add key="files.docservice.languages" value="en:English|hy:Armenian|az:Azerbaijani|eu:Basque|be:Belarusian|bg:Bulgarian|ca:Catalan|zh:Chinese (People's Republic of China)|zh-TW:Chinese (Traditional, Taiwan)|cs:Czech|da:Danish|nl:Dutch|fi:Finnish|fr:French|gl:Galego|de:German|el:Greek|hu:Hungarian|id:Indonesian|it:Italian|ja:Japanese|ko:Korean|lv:Latvian|lo:Lao|ms:Malay (Malaysia)|nb:Norwegian|pl:Polish|pt:Portuguese (Brazil)|pt-PT:Portuguese (Portugal)|ro:Romanian|ru:Russian|sk:Slovak|sl:Slovenian|es:Spanish|sv:Swedish|tr:Turkish|uk:Ukrainian|vi:Vietnamese|aa-AA: Test Language"/>
<add key="files.docservice.url.site" value="http://documentserver/"/>

View File

@ -167,7 +167,7 @@ label .checkbox {
background-image: url("images/file_docxf.svg");
}
.create-sample {
.side-option {
color: #666666;
line-height: 24px;
}
@ -744,3 +744,28 @@ html {
.user-descr > b {
margin-left: 25px;
}
.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;
left: -4px;
position: absolute;
top: 50%;
transform: translate(-50%, -50%);
}

View File

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

View File

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

View File

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

View File

@ -23,6 +23,8 @@
<IISExpressWindowsAuthentication />
<IISExpressUseClassicPipelineMode />
<TargetFrameworkProfile />
<Use64BitIISExpress />
<UseGlobalApplicationHostFile />
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
@ -48,29 +50,29 @@
<HintPath>packages\JWT.9.0.3\lib\net46\JWT.dll</HintPath>
</Reference>
<Reference Include="Microsoft.CSharp" />
<Reference Include="Microsoft.Web.Infrastructure">
<Reference Include="Microsoft.Web.Infrastructure, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>packages\Microsoft.Web.Infrastructure.1.0.0.0\lib\net40\Microsoft.Web.Infrastructure.dll</HintPath>
</Reference>
<Reference Include="Newtonsoft.Json, Version=10.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<HintPath>packages\Newtonsoft.Json.10.0.3\lib\net45\Newtonsoft.Json.dll</HintPath>
<Reference Include="Newtonsoft.Json, Version=13.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<HintPath>packages\Newtonsoft.Json.13.0.1\lib\net45\Newtonsoft.Json.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Web.Extensions" />
<Reference Include="System.Web" />
<Reference Include="System.Web.Helpers">
<Reference Include="System.Web.Helpers, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>packages\Microsoft.AspNet.WebPages.3.2.7\lib\net45\System.Web.Helpers.dll</HintPath>
</Reference>
<Reference Include="System.Web.Razor">
<Reference Include="System.Web.Razor, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>packages\Microsoft.AspNet.Razor.3.2.7\lib\net45\System.Web.Razor.dll</HintPath>
</Reference>
<Reference Include="System.Web.Services" />
<Reference Include="System.Web.WebPages">
<Reference Include="System.Web.WebPages, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>packages\Microsoft.AspNet.WebPages.3.2.7\lib\net45\System.Web.WebPages.dll</HintPath>
</Reference>
<Reference Include="System.Web.WebPages.Deployment">
<Reference Include="System.Web.WebPages.Deployment, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>packages\Microsoft.AspNet.WebPages.3.2.7\lib\net45\System.Web.WebPages.Deployment.dll</HintPath>
</Reference>
<Reference Include="System.Web.WebPages.Razor">
<Reference Include="System.Web.WebPages.Razor, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>packages\Microsoft.AspNet.WebPages.3.2.7\lib\net45\System.Web.WebPages.Razor.dll</HintPath>
</Reference>
</ItemGroup>
@ -159,10 +161,12 @@
<Content Include="assets\AUTHORS.md" />
<Content Include="assets\LICENSE" />
<Content Include="assets\new\new.docx" />
<Content Include="assets\new\new.docxf" />
<Content Include="assets\new\new.pptx" />
<Content Include="assets\new\new.xlsx" />
<Content Include="assets\sample\csv.csv" />
<Content Include="assets\sample\sample.docx" />
<Content Include="assets\sample\sample.docxf" />
<Content Include="assets\sample\sample.pptx" />
<Content Include="assets\sample\sample.xlsx" />
<None Include="packages.config" />

View File

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

View File

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<appSettings configSource="settings.config" />
<system.web>
@ -9,9 +9,9 @@
</system.web>
<system.webServer>
<httpProtocol>
<customHeaders>
<add name="Access-Control-Allow-Origin" value="*" />
</customHeaders>
<customHeaders>
<add name="Access-Control-Allow-Origin" value="*" />
</customHeaders>
</httpProtocol>
<security>
<requestFiltering>
@ -25,4 +25,20 @@
</requestFiltering>
</security>
</system.webServer>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Web.Helpers" publicKeyToken="31bf3856ad364e35" />
<bindingRedirect oldVersion="1.0.0.0-3.0.0.0" newVersion="3.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Web.WebPages" publicKeyToken="31bf3856ad364e35" />
<bindingRedirect oldVersion="1.0.0.0-3.0.0.0" newVersion="3.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-13.0.0.0" newVersion="13.0.0.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>

View File

@ -1,8 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="JWT" version="9.0.3" targetFramework="net48" />
<package id="Microsoft.AspNet.Razor" version="3.2.7" targetFramework="net45" />
<package id="Microsoft.AspNet.WebPages" version="3.2.7" targetFramework="net45" />
<package id="Microsoft.Web.Infrastructure" version="1.0.0.0" targetFramework="net45" />
<package id="Newtonsoft.Json" version="10.0.3" targetFramework="net48" />
<package id="Microsoft.AspNet.Razor" version="3.2.7" targetFramework="net48" />
<package id="Microsoft.AspNet.WebPages" version="3.2.7" targetFramework="net48" />
<package id="Microsoft.Web.Infrastructure" version="1.0.0.0" targetFramework="net48" />
<package id="Newtonsoft.Json" version="13.0.1" targetFramework="net48" />
</packages>

View File

@ -16,11 +16,24 @@
*
*/
var directUrl;
if (typeof jQuery != "undefined") {
jq = jQuery.noConflict();
directUrl = getUrlVars()["directUrl"] == "true";
mustReload = false;
if (directUrl)
jq("#directUrl").prop("checked", directUrl);
else
directUrl = jq("#directUrl").prop("checked");
jq("#directUrl").change(function () {
window.location = "?directUrl=" + jq(this).prop("checked");
});
jq(function () {
jq('#fileupload').fileupload({
dataType: 'json',
@ -219,7 +232,7 @@ if (typeof jQuery != "undefined") {
jq(document).on("click", "#beginEdit:not(.disable)", function () {
var fileId = encodeURIComponent(jq('#hiddenFileName').val());
var url = "doceditor.aspx?fileID=" + fileId;
var url = "doceditor.aspx?fileID=" + fileId + "&directUrl=" + directUrl;
window.open(url, "_blank");
jq('#hiddenFileName').val("");
jq.unblockUI();
@ -227,7 +240,7 @@ if (typeof jQuery != "undefined") {
jq(document).on("click", "#beginView:not(.disable)", function () {
var fileId = encodeURIComponent(jq('#hiddenFileName').val());
var url = "doceditor.aspx?editorsMode=view&fileID=" + fileId;
var url = "doceditor.aspx?editorsMode=view&fileID=" + fileId + "&directUrl=" + directUrl;
window.open(url, "_blank");
jq('#hiddenFileName').val("");
jq.unblockUI();
@ -235,7 +248,7 @@ if (typeof jQuery != "undefined") {
jq(document).on("click", "#beginEmbedded:not(.disable)", function () {
var fileId = encodeURIComponent(jq('#hiddenFileName').val());
var url = "doceditor.aspx?editorsType=embedded&editorsMode=embedded&fileID=" + fileId;
var url = "doceditor.aspx?editorsType=embedded&editorsMode=embedded&fileID=" + fileId + "&directUrl=" + directUrl;
jq("#mainProgress").addClass("embedded");
jq("#beginEmbedded").addClass("disable");
@ -288,6 +301,17 @@ if (typeof jQuery != "undefined") {
}
};
function getUrlVars() {
var vars = [], hash;
var hashes = window.location.href.slice(window.location.href.indexOf('?') + 1).split('&');
for (var i = 0; i < hashes.length; i++) {
hash = hashes[i].split('=');
vars.push(hash[0]);
vars[hash[0]] = hash[1];
}
return vars;
};
var fileList = jq("tr.tableRow");
var mouseIsOverTooltip = false;
@ -298,12 +322,12 @@ if (typeof jQuery != "undefined") {
if (hideTooltipTimeout != null) {
clearTimeout(hideTooltipTimeout);
}
jq(".info").on("touchend", function () {
jq("#info").on("touchend", function () {
showUserTooltip(true);
});
}
} else {
jq(".info").mouseover(function (event) {
jq("#info").mouseover(function (event) {
if (fileList.length > 0) {
if (hideTooltipTimeout != null) {
clearTimeout(hideTooltipTimeout);
@ -327,4 +351,18 @@ if (typeof jQuery != "undefined") {
}, 500);
});
}
jq(".info-tooltip").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 class='arrow'></div></div>").appendTo("body");
var top = jq("#" + id).offset().top + jq("#" + id).outerHeight() / 2 - jq("div.tooltip").outerHeight() / 2;
var left = jq("#" + id).offset().left + jq("#" + id).outerWidth() + 20;
jq("div.tooltip").css({ "top": top, "left": left });
}).mouseout(function () {
jq("div.tooltip").remove();
});
}

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8" ?>
<appSettings>
<clear />
<add key="version" value="1.3.0"/>
<add key="version" value="1.4.0"/>
<add key="filesize-max" value="52428800"/>
<add key="storage-path" value=""/>
@ -15,7 +15,7 @@
<add key="files.docservice.header" value="Authorization" />
<add key="files.docservice.verify-peer-off" value="true"/>
<add key="files.docservice.languages" value="en:English|hy:Armenian|az:Azerbaijani|eu:Basque|be:Belarusian|bg:Bulgarian|ca:Catalan|zh:Chinese (People's Republic of China)|zh-TW:Chinese (Traditional, Taiwan)|cs:Czech|da:Danish|nl:Dutch|fi:Finnish|fr:French|gl:Galego|de:German|el:Greek|hu:Hungarian|id:Indonesian|it:Italian|ja:Japanese|ko:Korean|lv:Latvian|lo:Lao|ms:Malay (Malaysia)|nb:Norwegian|pl:Polish|pt:Portuguese (Brazil)|pt-PT:Portuguese (Portugal)|ro:Romanian|ru:Russian|sk:Slovak|sl:Slovenian|es:Spanish|sv:Swedish|tr:Turkish|uk:Ukrainian|vi:Vietnamese"/>
<add key="files.docservice.languages" value="en:English|hy:Armenian|az:Azerbaijani|eu:Basque|be:Belarusian|bg:Bulgarian|ca:Catalan|zh:Chinese (People's Republic of China)|zh-TW:Chinese (Traditional, Taiwan)|cs:Czech|da:Danish|nl:Dutch|fi:Finnish|fr:French|gl:Galego|de:German|el:Greek|hu:Hungarian|id:Indonesian|it:Italian|ja:Japanese|ko:Korean|lv:Latvian|lo:Lao|ms:Malay (Malaysia)|nb:Norwegian|pl:Polish|pt:Portuguese (Brazil)|pt-PT:Portuguese (Portugal)|ro:Romanian|ru:Russian|sk:Slovak|sl:Slovenian|es:Spanish|sv:Swedish|tr:Turkish|uk:Ukrainian|vi:Vietnamese|aa-AA: Test Language"/>
<add key="files.docservice.url.site" value="http://documentserver/"/>

View File

@ -61,10 +61,15 @@
<version>1.18.20</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.13.4</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.12.6.1</version>
<version>2.13.4.2</version>
</dependency>
<dependency>
<groupId>org.modelmapper</groupId>
@ -78,6 +83,31 @@
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-checkstyle-plugin</artifactId>
<version>2.17</version>
<executions>
<execution>
<id>validate</id>
<phase>validate</phase>
<configuration>
<configLocation>google_checks.xml</configLocation>
<encoding>UTF-8</encoding>
<failsOnError>true</failsOnError>
<failOnViolation>true</failOnViolation>
<logViolationsToConsole>true</logViolationsToConsole>
<violationSeverity>warning</violationSeverity>
<consoleOutput>true</consoleOutput>
<includeTestSourceDirectory>true
</includeTestSourceDirectory>
</configuration>
<goals>
<goal>check</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,4 +1,4 @@
server.version=1.3.0
server.version=1.4.0
server.address=
server.port=4000
@ -27,7 +27,7 @@ files.docservice.header=Authorization
files.docservice.verify-peer-off=true
files.docservice.languages=en:English|hy:Armenian|az:Azerbaijani|eu:Basque|be:Belarusian|bg:Bulgarian|ca:Catalan|zh:Chinese (People's Republic of China)|zh-TW:Chinese (Traditional, Taiwan)|cs:Czech|da:Danish|nl:Dutch|fi:Finnish|fr:French|gl:Galego|de:German|el:Greek|hu:Hungarian|id:Indonesian|it:Italian|ja:Japanese|ko:Korean|lv:Latvian|lo:Lao|ms:Malay (Malaysia)|nb:Norwegian|pl:Polish|pt:Portuguese (Brazil)|pt-PT:Portuguese (Portugal)|ro:Romanian|ru:Russian|sk:Slovak|sl:Slovenian|es:Spanish|sv:Swedish|tr:Turkish|uk:Ukrainian|vi:Vietnamese
files.docservice.languages=en:English|hy:Armenian|az:Azerbaijani|eu:Basque|be:Belarusian|bg:Bulgarian|ca:Catalan|zh:Chinese (People's Republic of China)|zh-TW:Chinese (Traditional, Taiwan)|cs:Czech|da:Danish|nl:Dutch|fi:Finnish|fr:French|gl:Galego|de:German|el:Greek|hu:Hungarian|id:Indonesian|it:Italian|ja:Japanese|ko:Korean|lv:Latvian|lo:Lao|ms:Malay (Malaysia)|nb:Norwegian|pl:Polish|pt:Portuguese (Brazil)|pt-PT:Portuguese (Portugal)|ro:Romanian|ru:Russian|sk:Slovak|sl:Slovenian|es:Spanish|sv:Swedish|tr:Turkish|uk:Ukrainian|vi:Vietnamese|aa-AA:Test Language
spring.datasource.url=jdbc:h2:mem:usersdb
spring.datasource.driverClassName=org.h2.Driver

View File

@ -72,6 +72,7 @@ header img {
}
.main{
display: table;
height: calc(100% - 112px);
min-height: 536px;
}
@ -166,7 +167,7 @@ label .checkbox {
background-image: url("img/file_docxf.svg");
}
.create-sample {
.side-option {
color: #666666;
line-height: 24px;
}
@ -750,3 +751,28 @@ html {
.user-descr > b {
margin-left: 25px;
}
.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;
left: -4px;
position: absolute;
top: 50%;
transform: translate(-50%, -50%);
}

View File

@ -16,11 +16,24 @@
*
*/
var directUrl;
if (typeof jQuery !== "undefined") {
jq = jQuery.noConflict();
directUrl = getUrlVars()["directUrl"] == "true";
mustReload = false;
if (directUrl)
jq("#directUrl").prop("checked", directUrl);
else
directUrl = jq("#directUrl").prop("checked");
jq("#directUrl").change(function() {
window.location = "?directUrl=" + jq(this).prop("checked");
});
jq(function () {
jq("#fileupload").fileupload({
dataType: "json",
@ -228,7 +241,7 @@ if (typeof jQuery !== "undefined") {
jq(document).on("click", "#beginEdit:not(.disable)", function () {
var fileId = encodeURIComponent(jq("#hiddenFileName").val());
var url = UrlEditor + "?action=edit&fileName=" + fileId;
var url = UrlEditor + "?action=edit&fileName=" + fileId + "&directUrl=" + directUrl;
window.open(url, "_blank");
jq("#hiddenFileName").val("");
jq.unblockUI();
@ -236,7 +249,7 @@ if (typeof jQuery !== "undefined") {
jq(document).on("click", "#beginView:not(.disable)", function () {
var fileId = encodeURIComponent(jq("#hiddenFileName").val());
var url = UrlEditor + "?action=view&fileName=" + fileId;
var url = UrlEditor + "?action=view&fileName=" + fileId + "&directUrl=" + directUrl;
window.open(url, "_blank");
jq("#hiddenFileName").val("");
jq.unblockUI();
@ -244,7 +257,7 @@ if (typeof jQuery !== "undefined") {
jq(document).on("click", "#beginEmbedded:not(.disable)", function () {
var fileId = encodeURIComponent(jq("#hiddenFileName").val());
var url = UrlEditor + "?type=embedded&action=embedded&fileName=" + fileId;
var url = UrlEditor + "?type=embedded&action=embedded&fileName=" + fileId + "&directUrl=" + directUrl;
jq("#mainProgress").addClass("embedded");
jq("#beginEmbedded").addClass("disable");
@ -300,6 +313,17 @@ if (typeof jQuery !== "undefined") {
}
};
function getUrlVars() {
var vars = [], hash;
var hashes = window.location.href.slice(window.location.href.indexOf('?') + 1).split('&');
for (var i = 0; i < hashes.length; i++) {
hash = hashes[i].split('=');
vars.push(hash[0]);
vars[hash[0]] = hash[1];
}
return vars;
};
jq("#portal-info")[0].innerHTML += jq("#portal-info")[0].attributes.tooltip.value;
var fileList = jq("tr.tableRow");
@ -312,12 +336,12 @@ if (typeof jQuery !== "undefined") {
if (hideTooltipTimeout != null) {
clearTimeout(hideTooltipTimeout);
}
jq(".info").on("touchend", function () {
jq("#info").on("touchend", function () {
showUserTooltip(true);
});
}
} else {
jq(".info").mouseover(function (event) {
jq("#info").mouseover(function (event) {
if (fileList.length > 0) {
if (hideTooltipTimeout != null) {
clearTimeout(hideTooltipTimeout);
@ -342,4 +366,18 @@ if (typeof jQuery !== "undefined") {
});
}
jq(".info-tooltip").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 class='arrow'></div></div>").appendTo("body");
var top = jq("#" + id).offset().top + jq("#" + id).outerHeight() / 2 - jq("div.tooltip").outerHeight() / 2;
var left = jq("#" + id).offset().left + jq("#" + id).outerWidth() + 20;
jq("div.tooltip").css({"top": top, "left": left});
}).mouseout(function () {
jq("div.tooltip").remove();
});
}

View File

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

View File

@ -85,6 +85,31 @@
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-checkstyle-plugin</artifactId>
<version>2.17</version>
<executions>
<execution>
<id>validate</id>
<phase>validate</phase>
<configuration>
<configLocation>google_checks.xml</configLocation>
<encoding>UTF-8</encoding>
<failsOnError>true</failsOnError>
<failOnViolation>true</failOnViolation>
<logViolationsToConsole>true</logViolationsToConsole>
<violationSeverity>warning</violationSeverity>
<consoleOutput>true</consoleOutput>
<includeTestSourceDirectory>true
</includeTestSourceDirectory>
</configuration>
<goals>
<goal>check</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,4 +1,4 @@
version=1.3.0
version=1.4.0
filesize-max=5242880
storage-folder=app_data
@ -16,7 +16,7 @@ files.docservice.url.api=web-apps/apps/api/documents/api.js
files.docservice.url.preloader=web-apps/apps/api/documents/cache-scripts.html
files.docservice.url.example=
files.docservice.languages=en:English|hy:Armenian|az:Azerbaijani|eu:Basque|be:Belarusian|bg:Bulgarian|ca:Catalan|zh:Chinese (People's Republic of China)|zh-TW:Chinese (Traditional, Taiwan)|cs:Czech|da:Danish|nl:Dutch|fi:Finnish|fr:French|gl:Galego|de:German|el:Greek|hu:Hungarian|id:Indonesian|it:Italian|ja:Japanese|ko:Korean|lv:Latvian|lo:Lao|ms:Malay (Malaysia)|nb:Norwegian|pl:Polish|pt:Portuguese (Brazil)|pt-PT:Portuguese (Portugal)|ro:Romanian|ru:Russian|sk:Slovak|sl:Slovenian|es:Spanish|sv:Swedish|tr:Turkish|uk:Ukrainian|vi:Vietnamese
files.docservice.languages=en:English|hy:Armenian|az:Azerbaijani|eu:Basque|be:Belarusian|bg:Bulgarian|ca:Catalan|zh:Chinese (People's Republic of China)|zh-TW:Chinese (Traditional, Taiwan)|cs:Czech|da:Danish|nl:Dutch|fi:Finnish|fr:French|gl:Galego|de:German|el:Greek|hu:Hungarian|id:Indonesian|it:Italian|ja:Japanese|ko:Korean|lv:Latvian|lo:Lao|ms:Malay (Malaysia)|nb:Norwegian|pl:Polish|pt:Portuguese (Brazil)|pt-PT:Portuguese (Portugal)|ro:Romanian|ru:Russian|sk:Slovak|sl:Slovenian|es:Spanish|sv:Swedish|tr:Turkish|uk:Ukrainian|vi:Vietnamese|aa-AA:Test Language
files.docservice.secret=
files.docservice.header=Authorization

View File

@ -167,7 +167,7 @@ label .checkbox {
background-image: url("img/file_docxf.svg");
}
.create-sample {
.side-option {
color: #666666;
line-height: 24px;
}
@ -747,3 +747,28 @@ html {
.user-descr > b {
margin-left: 25px;
}
.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;
left: -4px;
position: absolute;
top: 50%;
transform: translate(-50%, -50%);
}

View File

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

View File

@ -16,11 +16,24 @@
*
*/
var directUrl;
if (typeof jQuery !== "undefined") {
jq = jQuery.noConflict();
directUrl = getUrlVars()["directUrl"] == "true";
mustReload = false;
if (directUrl)
jq("#directUrl").prop("checked", directUrl);
else
directUrl = jq("#directUrl").prop("checked");
jq("#directUrl").change(function() {
window.location = "?directUrl=" + jq(this).prop("checked");
});
jq(function () {
jq("#fileupload").fileupload({
dataType: "json",
@ -218,7 +231,7 @@ if (typeof jQuery !== "undefined") {
jq(document).on("click", "#beginEdit:not(.disable)", function () {
var fileId = encodeURIComponent(jq("#hiddenFileName").val());
var url = UrlEditor + "?mode=edit&fileName=" + fileId;
var url = UrlEditor + "?mode=edit&fileName=" + fileId + "&directUrl=" + directUrl;
window.open(url, "_blank");
jq("#hiddenFileName").val("");
jq.unblockUI();
@ -226,7 +239,7 @@ if (typeof jQuery !== "undefined") {
jq(document).on("click", "#beginView:not(.disable)", function () {
var fileId = encodeURIComponent(jq("#hiddenFileName").val());
var url = UrlEditor + "?mode=view&fileName=" + fileId;
var url = UrlEditor + "?mode=view&fileName=" + fileId + "&directUrl=" + directUrl;
window.open(url, "_blank");
jq("#hiddenFileName").val("");
jq.unblockUI();
@ -234,7 +247,7 @@ if (typeof jQuery !== "undefined") {
jq(document).on("click", "#beginEmbedded:not(.disable)", function () {
var fileId = encodeURIComponent(jq("#hiddenFileName").val());
var url = UrlEditor + "?type=embedded&mode=embedded&fileName=" + fileId;
var url = UrlEditor + "?type=embedded&mode=embedded&fileName=" + fileId + "&directUrl=" + directUrl;
jq("#mainProgress").addClass("embedded");
jq("#beginEmbedded").addClass("disable");
@ -287,6 +300,17 @@ if (typeof jQuery !== "undefined") {
}
};
function getUrlVars() {
var vars = [], hash;
var hashes = window.location.href.slice(window.location.href.indexOf('?') + 1).split('&');
for (var i = 0; i < hashes.length; i++) {
hash = hashes[i].split('=');
vars.push(hash[0]);
vars[hash[0]] = hash[1];
}
return vars;
};
var fileList = jq("tr.tableRow");
var mouseIsOverTooltip = false;
@ -297,12 +321,12 @@ if (typeof jQuery !== "undefined") {
if (hideTooltipTimeout != null) {
clearTimeout(hideTooltipTimeout);
}
jq(".info").on("touchend", function () {
jq("#info").on("touchend", function () {
showUserTooltip(true);
});
}
} else {
jq(".info").mouseover(function (event) {
jq("#info").mouseover(function (event) {
if (fileList.length > 0) {
if (hideTooltipTimeout != null) {
clearTimeout(hideTooltipTimeout);
@ -326,4 +350,18 @@ if (typeof jQuery !== "undefined") {
}, 500);
});
}
jq(".info-tooltip").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 class='arrow'></div></div>").appendTo("body");
var top = jq("#" + id).offset().top + jq("#" + id).outerHeight() / 2 - jq("div.tooltip").outerHeight() / 2;
var left = jq("#" + id).offset().left + jq("#" + id).outerWidth() + 20;
jq("div.tooltip").css({"top": top, "left": left});
}).mouseout(function () {
jq("div.tooltip").remove();
});
}

View File

@ -0,0 +1 @@
public

View File

@ -0,0 +1,15 @@
module.exports = {
env: {
browser: true,
commonjs: true,
es2021: true,
},
extends: ['airbnb-base'],
overrides: [
],
parserOptions: {
ecmaVersion: 'latest',
},
rules: {
},
};

View File

@ -44,6 +44,7 @@ const cfgSignatureAuthorizationHeaderPrefix = configServer.get('token.authorizat
const cfgSignatureSecretExpiresIn = configServer.get('token.expiresIn');
const cfgSignatureSecret = configServer.get('token.secret');
const urllib = require("urllib");
const { emitWarning } = require("process");
const verifyPeerOff = configServer.get('verify_peer_off');
if(verifyPeerOff) {
@ -347,7 +348,7 @@ app.post("/convert", function (req, res) { // define a handler for converting f
response.end();
};
var callback = function (err, data) {
var callback = async function (err, res) {
if (err) { // if an error occurs
if (err.name === "ConnectionTimeoutError" || err.name === "ResponseTimeoutError") { // check what type of error it is
writeResult(fileName, 0, null); // despite the timeout errors, write the file to the result object
@ -358,7 +359,7 @@ app.post("/convert", function (req, res) { // define a handler for converting f
}
try {
var responseUri = documentService.getResponseUri(data.toString());
var responseUri = documentService.getResponseUri(res.toString());
var result = responseUri.key;
var newFileUri = responseUri.value; // get the callback url
@ -369,10 +370,11 @@ app.post("/convert", function (req, res) { // define a handler for converting f
var correctName = req.docManager.getCorrectName(fileUtility.getFileName(fileName, true) + internalFileExt); // get the file name with a new extension
urllib.request(newFileUri, {method: "GET"},function(err, data) {
fileSystem.writeFileSync(req.docManager.storagePath(correctName), data); // write a file with a new extension, but with the content from the origin file
});
const {status, data} = await urllib.request(newFileUri, {method: "GET"});
if (status != 200) throw new Error("Conversion service returned status: " + status);
fileSystem.writeFileSync(req.docManager.storagePath(correctName), data); // write a file with a new extension, but with the content from the origin file
fileSystem.unlinkSync(req.docManager.storagePath(fileName)); // remove file with the origin extension
var userAddress = req.docManager.curUserHostAddress();
@ -467,7 +469,62 @@ app.get("/csv", function (req, res) { // define a handler for downloading csv f
filestream.pipe(res); // send file information to the response by streams
})
app.post("/track", function (req, res) { // define a handler for tracking file changes
app.post("/reference", function (req, res) { //define a handler for renaming file
req.docManager = new docManager(req, res);
var result = function(data) {
res.writeHead(200, {"Content-Type": "application/json" });
res.write(JSON.stringify(data));
res.end();
};
var referenceData = req.body.referenceData;
if (!!referenceData) {
var portalName = referenceData.portalName;
if (portalName != req.docManager.getServerUrl()) {
result({ "error": "You do not have access to this site" });
return;
}
var fileId = JSON.parse(referenceData.fileId);
var userAddress = fileId.userAddress;
if (userAddress != req.docManager.curUserHostAddress()) {
result({ "error": "You do not have access to this file" });
return;
}
var fileName = fileId.fileName;
if (!req.docManager.existsSync(req.docManager.storagePath(fileName, userAddress))) {
result({ "error": "File is not exist" });
return;
}
} else if (!!req.body.path) {
var fileName = fileUtility.getFileName(req.body.path);
if (!req.docManager.existsSync(req.docManager.storagePath(fileName, userAddress))) {
result({ "error": "File is not exist" });
return;
}
}
if (!fileName) {
result({ "error": "File is not found" });
return;
}
result({
url: req.docManager.getDownloadUrl(fileName, true),
directUrl: req.docManager.getDownloadUrl(fileName),
referenceData: {
fileId: JSON.stringify({ fileName: fileName, userAddress: req.docManager.curUserHostAddress()}),
portalName: req.docManager.getServerUrl()
},
path: fileName,
});
});
app.post("/track", async function (req, res) { // define a handler for tracking file changes
req.docManager = new docManager(req, res);
@ -476,11 +533,15 @@ app.post("/track", function (req, res) { // define a handler for tracking file
var version = 0;
// track file changes
var processTrack = function (response, body, fileName, userAddress) {
var processTrack = async function (response, body, fileName, userAddress) {
// callback file saving process
var callbackProcessSave = function (downloadUri, body, fileName, userAddress, newFileName) {
var callbackProcessSave = async function (downloadUri, body, fileName, userAddress, newFileName) {
try {
const {status, data} = await urllib.request(downloadUri, {method: "GET"});
if (status != 200) throw new Error("Document editing service returned status: " + status);
var storagePath = req.docManager.storagePath(newFileName, userAddress);
var historyPath = req.docManager.historyPath(newFileName, userAddress); // get the path to the history data
@ -497,9 +558,12 @@ app.post("/track", function (req, res) { // define a handler for tracking file
var downloadZip = body.changesurl;
if (downloadZip) {
var path_changes = req.docManager.diffPath(newFileName, userAddress, version); // get the path to the file with document versions differences
urllib.request(downloadZip, {method: "GET"},function(err, data) {
const {status, data} = await urllib.request(downloadZip, {method: "GET"});
if (status == 200) {
fileSystem.writeFileSync(path_changes, data); // write the document version differences to the archive
});
} else {
emitWarning("Document editing service returned status: " + status);
}
}
var changeshistory = body.changeshistory || JSON.stringify(body.history);
@ -514,9 +578,7 @@ app.post("/track", function (req, res) { // define a handler for tracking file
var path_prev = path.join(versionPath, "prev" + fileUtility.getFileExtension(fileName)); // get the path to the previous file version
fileSystem.renameSync(req.docManager.storagePath(fileName, userAddress), path_prev); // and write it to the current path
urllib.request(downloadUri, {method: "GET"},function(err, data) {
fileSystem.writeFileSync(storagePath, data);
});
fileSystem.writeFileSync(storagePath, data);
var forcesavePath = req.docManager.forcesavePath(newFileName, userAddress, false); // get the path to the forcesaved file
if (forcesavePath != "") { // if this path is empty
@ -524,6 +586,7 @@ app.post("/track", function (req, res) { // define a handler for tracking file
}
} catch (ex) {
console.log(ex);
response.write("{\"error\":1}");
response.end();
return;
@ -534,7 +597,7 @@ app.post("/track", function (req, res) { // define a handler for tracking file
}
// file saving process
var processSave = function (downloadUri, body, fileName, userAddress) {
var processSave = async function (downloadUri, body, fileName, userAddress) {
if (!downloadUri) {
response.write("{\"error\":1}");
@ -555,18 +618,18 @@ app.post("/track", function (req, res) { // define a handler for tracking file
var key = documentService.generateRevisionId(downloadUri);
newFileName = req.docManager.getCorrectName(fileUtility.getFileName(fileName, true) + downloadExt, userAddress); // get the correct file name if it already exists
try {
documentService.getConvertedUriSync(downloadUri, downloadExt, curExt, key, function (err, data) {
documentService.getConvertedUriSync(downloadUri, downloadExt, curExt, key, async function (err, data) {
if (err) {
callbackProcessSave(downloadUri, body, fileName, userAddress, newFileName);
await callbackProcessSave(downloadUri, body, fileName, userAddress, newFileName);
return;
}
try {
var res = documentService.getResponseUri(data);
callbackProcessSave(res.value, body, fileName, userAddress, fileName);
await callbackProcessSave(res.value, body, fileName, userAddress, fileName);
return;
} catch (ex) {
console.log(ex);
callbackProcessSave(downloadUri, body, fileName, userAddress, newFileName);
await callbackProcessSave(downloadUri, body, fileName, userAddress, newFileName);
return;
}
});
@ -575,12 +638,16 @@ app.post("/track", function (req, res) { // define a handler for tracking file
console.log(ex);
}
}
callbackProcessSave(downloadUri, body, fileName, userAddress, newFileName);
await callbackProcessSave(downloadUri, body, fileName, userAddress, newFileName);
};
// callback file force saving process
var callbackProcessForceSave = function (downloadUri, body, fileName, userAddress, newFileName = false){
var callbackProcessForceSave = async function (downloadUri, body, fileName, userAddress, newFileName = false){
try {
const {status, data} = await urllib.request(downloadUri, {method: "GET"});
if (status != 200) throw new Error("Document editing service returned status: " + status);
var downloadExt = "." + body.fileType;
/// TODO [Delete in version 7.0 or higher]
@ -608,9 +675,7 @@ app.post("/track", function (req, res) { // define a handler for tracking file
}
}
urllib.request(downloadUri, {method: "GET"},function(err, data) {
fileSystem.writeFileSync(forcesavePath, data);
});
fileSystem.writeFileSync(forcesavePath, data);
if (isSubmitForm) {
var uid =body.actions[0].userid
@ -627,7 +692,7 @@ app.post("/track", function (req, res) { // define a handler for tracking file
}
// file force saving process
var processForceSave = function (downloadUri, body, fileName, userAddress) {
var processForceSave = async function (downloadUri, body, fileName, userAddress) {
if (!downloadUri) {
response.write("{\"error\":1}");
@ -645,18 +710,18 @@ app.post("/track", function (req, res) { // define a handler for tracking file
if (downloadExt != curExt) {
var key = documentService.generateRevisionId(downloadUri);
try {
documentService.getConvertedUriSync(downloadUri, downloadExt, curExt, key, function (err, data) {
documentService.getConvertedUriSync(downloadUri, downloadExt, curExt, key, async function (err, data) {
if (err) {
callbackProcessForceSave(downloadUri, body, fileName, userAddress, true);
await callbackProcessForceSave(downloadUri, body, fileName, userAddress, true);
return;
}
try {
var res = documentService.getResponseUri(data);
callbackProcessForceSave(res.value, body, fileName, userAddress, false);
await callbackProcessForceSave(res.value, body, fileName, userAddress, false);
return;
} catch (ex) {
console.log(ex);
callbackProcessForceSave(downloadUri, body, fileName, userAddress, true);
await callbackProcessForceSave(downloadUri, body, fileName, userAddress, true);
return;
}
});
@ -665,7 +730,7 @@ app.post("/track", function (req, res) { // define a handler for tracking file
console.log(ex);
}
}
callbackProcessForceSave (downloadUri, body, fileName, userAddress, false);
await callbackProcessForceSave (downloadUri, body, fileName, userAddress, false);
};
if (body.status == 1) { // editing
@ -681,10 +746,10 @@ app.post("/track", function (req, res) { // define a handler for tracking file
}
}
} else if (body.status == 2 || body.status == 3) { // MustSave, Corrupted
processSave(body.url, body, fileName, userAddress); // save file
await processSave(body.url, body, fileName, userAddress); // save file
return;
} else if (body.status == 6 || body.status == 7) { // MustForceSave, CorruptedForceSave
processForceSave(body.url, body, fileName, userAddress); // force save file
await processForceSave(body.url, body, fileName, userAddress); // force save file
return;
}
@ -693,14 +758,14 @@ app.post("/track", function (req, res) { // define a handler for tracking file
};
// read request body
var readbody = function (request, response, fileName, userAddress) {
var readbody = async function (request, response, fileName, userAddress) {
var content = "";
request.on('data', function (data) { // get data from the request
request.on('data', async function (data) { // get data from the request
content += data;
});
request.on('end', function () {
request.on('end', async function () {
var body = JSON.parse(content);
processTrack(response, body, fileName, userAddress); // and track file changes
await processTrack(response, body, fileName, userAddress); // and track file changes
});
};
@ -732,14 +797,14 @@ app.post("/track", function (req, res) { // define a handler for tracking file
res.end();
return;
}
processTrack(res, body, fileName, userAddress);
await processTrack(res, body, fileName, userAddress);
return;
}
if (req.body.hasOwnProperty("status")) { // if the request body has status parameter
processTrack(res, req.body, fileName, userAddress); // track file changes
await processTrack(res, req.body, fileName, userAddress); // track file changes
} else {
readbody(req, res, fileName, userAddress); // otherwise, read request body first
await readbody(req, res, fileName, userAddress); // otherwise, read request body first
}
});
@ -769,6 +834,19 @@ app.get("/editor", function (req, res) { // define a handler for editing docume
}
}
var referenceData = {
fileId: JSON.stringify({ fileName: fileName, userAddress: req.docManager.curUserHostAddress()}),
portalName: req.docManager.getServerUrl()
};
var type = req.query.type || ""; // type: embedded/mobile/desktop
if (type == "") {
type = new RegExp(configServer.get("mobileRegEx"), "i").test(req.get('User-Agent')) ? "mobile" : "desktop";
} else if (type != "mobile"
&& type != "embedded") {
type = "desktop";
}
var templatesImageUrl = req.docManager.getTemplateImageUrl(fileUtility.getFileType(fileName));
var createUrl = req.docManager.getCreateUrl(fileUtility.getFileType(fileName), userid, type, lang);
var templates = [
@ -810,14 +888,6 @@ app.get("/editor", function (req, res) { // define a handler for editing docume
var directUrl = req.docManager.getDownloadUrl(fileName);
var mode = req.query.mode || "edit"; // mode: view/edit/review/comment/fillForms/embedded
var type = req.query.type || ""; // type: embedded/mobile/desktop
if (type == "") {
type = new RegExp(configServer.get("mobileRegEx"), "i").test(req.get('User-Agent')) ? "mobile" : "desktop";
} else if (type != "mobile"
&& type != "embedded") {
type = "desktop";
}
var canEdit = configServer.get('editedDocs').indexOf(fileExt) != -1; // check if this file can be edited
if ((!canEdit && mode == "edit" || mode == "fillForms") && configServer.get('fillDocs').indexOf(fileExt) != -1) {
mode = "fillForms";
@ -935,7 +1005,8 @@ app.get("/editor", function (req, res) { // define a handler for editing docume
fileChoiceUrl: fileChoiceUrl,
submitForm: submitForm,
plugins: JSON.stringify(plugins),
actionData: actionData
actionData: actionData,
referenceData: userid != "uid-0" ? referenceData : null
},
history: history,
historyData: historyData,

View File

@ -1,5 +1,5 @@
{
"version": "1.3.0",
"version": "1.4.0",
"log": {
"appenders": [
{
@ -84,7 +84,8 @@
"sv": "Swedish",
"tr": "Turkish",
"uk": "Ukrainian",
"vi": "Vietnamese"
"vi": "Vietnamese",
"aa-AA": "Test Language"
}
},
"plugins": {

View File

@ -22,9 +22,20 @@ var urlModule = require("url");
var urllib = require("urllib");
const xmlParser = require("fast-xml-parser");
const he = require("he");
const siteUrl = configServer.get("siteUrl"); // the path to the editors installation
var cache = null;
async function initWopi(docManager) {
let absSiteUrl = siteUrl;
if (absSiteUrl.indexOf("/") === 0) {
absSiteUrl = docManager.getServerHost() + siteUrl;
}
// get the wopi discovery information
await getDiscoveryInfo(absSiteUrl);
}
// get the wopi discovery information
async function getDiscoveryInfo(siteUrl) {
let actions = [];
@ -125,6 +136,7 @@ function getActionUrl(host, userAddress, action, filename) {
return action.urlsrc.replace(/<.*&>/g, "") + "WOPISrc=" + host + "/wopi/files/" + filename + "@" + userAddress;
}
exports.initWopi = initWopi;
exports.getDiscoveryInfo = getDiscoveryInfo;
exports.getAction = getAction;
exports.getActions = getActions;

View File

@ -23,7 +23,7 @@ const docManager = require("../docManager");
const fileUtility = require("../fileUtility");
const config = require('config');
const configServer = config.get('server');
const siteUrl = configServer.get('siteUrl'); // the path to the editors installation
const siteUrl = configServer.get("siteUrl"); // the path to the editors installation
const users = require("../users");
exports.registerRoutes = function(app) {
@ -33,24 +33,10 @@ exports.registerRoutes = function(app) {
req.docManager = new docManager(req, res);
let absSiteUrl = siteUrl;
if (absSiteUrl.indexOf("/") === 0) {
absSiteUrl = req.docManager.getServerHost() + siteUrl;
//todo: remove
if (absSiteUrl.indexOf("example") !== -1) {
let host = req.get("host");
let pos = host.indexOf("/", "https://".length);
if (pos > -1)
{
host = host.substring(0, pos);
}
absSiteUrl = req.docManager.getProtocol() + "://" + host + siteUrl;
}
}
await utils.initWopi(req.docManager);
// get the wopi discovery information
let actions = await utils.getDiscoveryInfo(absSiteUrl);
let actions = await utils.getDiscoveryInfo();
let wopiEnable = actions.length != 0 ? true : false;
let docsExtEdit = []; // Supported extensions for WOPI
@ -111,6 +97,8 @@ exports.registerRoutes = function(app) {
try {
req.docManager = new docManager(req, res);
await utils.initWopi(req.docManager);
var fileName = req.docManager.getCorrectName(req.params['id'])
var fileExt = fileUtility.getFileExtension(fileName, true); // get the file extension from the request
var user = users.getUser(req.query.userid); // get a user by the id

File diff suppressed because it is too large Load Diff

View File

@ -3,7 +3,9 @@
"version": "4.1.0",
"private": false,
"scripts": {
"start": "node ./bin/www"
"start": "node ./bin/www",
"lint": "eslint .",
"lint:fix": "eslint --fix ."
},
"bin": "bin/www",
"description": "OnlineEditorsExampleNodeJS",
@ -40,5 +42,10 @@
"public/**/*",
"views/*"
]
},
"devDependencies": {
"eslint": "^8.28.0",
"eslint-config-airbnb-base": "^15.0.0",
"eslint-plugin-import": "^2.26.0"
}
}

View File

@ -1,54 +1,37 @@
"width": "100%",
"height": "100%",
"type": "<%- editor.type %>",
"documentType": "<%- editor.documentType %>",
"token": "<%- editor.token %>",
"document": {
"title": "<%- file.name %>",
"url": "<%- file.uri %>",
"document": {
"directUrl": "<%- file.directUrl %>",
"fileType": "<%- file.ext %>",
"key": "<%- editor.key %>",
"info": {
"owner": "Me",
"uploaded": "<%- file.created %>",
"favorite": <%- file.favorite %>
},
"key": "<%- editor.key %>",
"permissions": {
"chat": <%- editor.chat %>,
"comment": <%- editor.comment %>,
"copy": <%- editor.copy %>,
"download": <%- editor.download %>,
"edit": <%- editor.isEdit %>,
"print": <%- editor.print %>,
"fillForms": <%- editor.fillForms %>,
"modifyFilter": <%- editor.modifyFilter %>,
"modifyContentControl": <%- editor.modifyContentControl %>,
"modifyFilter": <%- editor.modifyFilter %>,
"print": <%- editor.print %>,
"review": <%- editor.review %>,
"reviewGroups": <%- editor.reviewGroups %>,
"commentGroups": <%- editor.commentGroups %>,
"userInfoGroups": <%- editor.userInfoGroups %>
}
},
"referenceData": <%- JSON.stringify(editor.referenceData) %>,
"title": "<%- file.name %>",
"url": "<%- file.uri %>"
},
"documentType": "<%- editor.documentType %>",
"editorConfig": {
"actionLink": <%- editor.actionData %>,
"coEditing": <%- JSON.stringify(editor.coEditing) %>,
"mode": "<%- editor.mode %>",
"lang": "<%- editor.lang %>",
"callbackUrl": "<%- editor.callbackUrl %>",
"coEditing": <%- JSON.stringify(editor.coEditing) %>,
"createUrl": <%- JSON.stringify(editor.createUrl) %>,
"templates": <%- JSON.stringify(editor.templates) %>,
"user": {
"group": "<%- editor.userGroup %>",
"id": "<%- editor.userid %>",
"name": "<%- editor.name %>"
},
"embedded": {
"saveUrl": "<%- file.uriUser %>",
"embedUrl": "<%- file.uriUser %>",
"shareUrl": "<%- file.uriUser %>",
"toolbarDocked": "top"
},
"customization": {
"about": true,
"comments": true,
@ -59,6 +42,24 @@
},
"submitForm": <%- editor.submitForm %>
},
"embedded": {
"embedUrl": "<%- file.uriUser %>",
"saveUrl": "<%- file.uriUser %>",
"shareUrl": "<%- file.uriUser %>",
"toolbarDocked": "top"
},
"fileChoiceUrl": "<%- editor.fileChoiceUrl %>",
"plugins": <%- editor.plugins %>
}
"lang": "<%- editor.lang %>",
"mode": "<%- editor.mode %>",
"plugins": <%- editor.plugins %>,
"templates": <%- JSON.stringify(editor.templates) %>,
"user": {
"group": "<%- editor.userGroup %>",
"id": "<%- editor.userid %>",
"name": "<%- editor.name %>"
}
},
"height": "100%",
"token": "<%- editor.token %>",
"type": "<%- editor.type %>",
"width": "100%"

View File

@ -151,6 +151,20 @@
innerAlert("onRequestSendNotify: " + data);
};
var onRequestReferenceData = function(event) { // user refresh external data source
innerAlert("onRequestReferenceData");
innerAlert(event.data);
let xhr = new XMLHttpRequest();
xhr.open("POST", "reference");
xhr.setRequestHeader("Content-Type", "application/json");
xhr.send(JSON.stringify(event.data));
xhr.onload = function () {
innerAlert(xhr.responseText);
docEditor.setReferenceData(JSON.parse(xhr.responseText));
}
};
var onRequestSaveAs = function (event) { // the user is trying to save file by clicking Save Copy as... button
var title = event.data.title;
var url = event.data.url;
@ -186,20 +200,21 @@
}
};
config = {<%- include("config") %>,
events: {
"onAppReady": onAppReady,
"onDocumentStateChange": onDocumentStateChange,
"onRequestEditRights": onRequestEditRights,
"onError": onError,
"onOutdatedVersion": onOutdatedVersion,
"onMakeActionLink": onMakeActionLink,
"onMetaChange": onMetaChange,
"onRequestInsertImage": onRequestInsertImage,
"onRequestCompareFile": onRequestCompareFile,
"onRequestMailMergeRecipients": onRequestMailMergeRecipients,
}
};
config = {
<%- include("config") %>
};
config.events = {
"onAppReady": onAppReady,
"onDocumentStateChange": onDocumentStateChange,
"onRequestEditRights": onRequestEditRights,
"onError": onError,
"onOutdatedVersion": onOutdatedVersion,
"onMakeActionLink": onMakeActionLink,
"onMetaChange": onMetaChange,
"onRequestInsertImage": onRequestInsertImage,
"onRequestCompareFile": onRequestCompareFile,
"onRequestMailMergeRecipients": onRequestMailMergeRecipients,
};
if (<%- JSON.stringify(editor.userid) %> != null) {
config.events.onRequestHistory = onRequestHistory;
@ -208,6 +223,7 @@
config.events.onRequestRename = onRequestRename;
config.events.onRequestUsers = onRequestUsers;
config.events.onRequestSendNotify = onRequestSendNotify;
config.events.onRequestReferenceData = onRequestReferenceData;
}
if (config.editorConfig.createUrl) {

View File

@ -1,6 +1,6 @@
<?php
$GLOBALS['version'] = "1.3.0";
$GLOBALS['version'] = "1.4.0";
$GLOBALS['FILE_SIZE_MAX'] = 5242880;
$GLOBALS['STORAGE_PATH'] = "";
@ -84,6 +84,7 @@ $GLOBALS['LANGUAGES'] = array(
'sv' => 'Swedish',
'tr' => 'Turkish',
'uk' => 'Ukrainian',
'vi' => 'Vietnamese'
'vi' => 'Vietnamese',
'aa-AA' => 'Test Language'
);
?>

View File

@ -166,7 +166,7 @@ label .checkbox {
background-image: url("images/file_docxf.svg");
}
.create-sample {
.side-option {
color: #666666;
line-height: 24px;
}
@ -740,3 +740,28 @@ html {
.user-descr > b {
margin-left: 25px;
}
.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;
left: -4px;
position: absolute;
top: 50%;
transform: translate(-50%, -50%);
}

View File

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

View File

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

View File

@ -16,11 +16,24 @@
*
*/
var directUrl;
if (typeof jQuery != "undefined") {
jq = jQuery.noConflict();
directUrl = getUrlVars()["directUrl"] == "true";
mustReload = false;
if (directUrl)
jq("#directUrl").prop("checked", directUrl);
else
directUrl = jq("#directUrl").prop("checked");
jq("#directUrl").change(function() {
window.location = "?directUrl=" + jq(this).prop("checked");
});
user = getUrlVars()["user"];
if ("" != user && undefined != user)
jq("#user").val(user);
@ -234,7 +247,7 @@ if (typeof jQuery != "undefined") {
jq(document).on("click", "#beginEdit:not(.disable)", function () {
var fileId = encodeURIComponent(jq('#hiddenFileName').val());
var url = "doceditor.php?fileID=" + fileId + "&user=" + user;
var url = "doceditor.php?fileID=" + fileId + "&user=" + user + "&directUrl=" + directUrl;
window.open(url, "_blank");
jq('#hiddenFileName').val("");
jq.unblockUI();
@ -243,7 +256,7 @@ if (typeof jQuery != "undefined") {
jq(document).on("click", "#beginView:not(.disable)", function () {
var fileId = encodeURIComponent(jq('#hiddenFileName').val());
var url = "doceditor.php?action=view&fileID=" + fileId + "&user=" + user;
var url = "doceditor.php?action=view&fileID=" + fileId + "&user=" + user + "&directUrl=" + directUrl;
window.open(url, "_blank");
jq('#hiddenFileName').val("");
jq.unblockUI();
@ -252,7 +265,7 @@ if (typeof jQuery != "undefined") {
jq(document).on("click", "#beginEmbedded:not(.disable)", function () {
var fileId = encodeURIComponent(jq('#hiddenFileName').val());
var url = "doceditor.php?type=embedded&fileID=" + fileId + "&user=" + user;
var url = "doceditor.php?type=embedded&fileID=" + fileId + "&user=" + user + "&directUrl=" + directUrl;
jq("#mainProgress").addClass("embedded");
jq("#beginEmbedded").addClass("disable");
@ -330,12 +343,12 @@ if (typeof jQuery != "undefined") {
if (hideTooltipTimeout != null) {
clearTimeout(hideTooltipTimeout);
}
jq(".info").on("touchend", function () {
jq("#info").on("touchend", function () {
showUserTooltip(true);
});
}
} else {
jq(".info").mouseover(function (event) {
jq("#info").mouseover(function (event) {
if (fileList.length > 0) {
if (hideTooltipTimeout != null) {
clearTimeout(hideTooltipTimeout);
@ -359,6 +372,20 @@ if (typeof jQuery != "undefined") {
}, 500);
});
}
jq(".info-tooltip").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 class='arrow'></div></div>").appendTo("body");
var top = jq("#" + id).offset().top + jq("#" + id).outerHeight() / 2 - jq("div.tooltip").outerHeight() / 2;
var left = jq("#" + id).offset().left + jq("#" + id).outerWidth() + 20;
jq("div.tooltip").css({"top": top, "left": left});
}).mouseout(function () {
jq("div.tooltip").remove();
});
}
function getUrlVars() {

View File

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

View File

@ -1,6 +1,6 @@
import os
VERSION = '1.3.0'
VERSION = '1.4.0'
FILE_SIZE_MAX = 5242880
STORAGE_PATH = 'app_data'
@ -91,7 +91,8 @@ LANGUAGES = {
'sv': 'Swedish',
'tr': 'Turkish',
'uk': 'Ukrainian',
'vi': 'Vietnamese'
'vi': 'Vietnamese',
'aa-AA': 'Test Language'
}
if os.environ.get("EXAMPLE_DOMAIN"): # generates a link for example domain

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -175,7 +175,7 @@ label .checkbox {
background-image: url("../images/file_docxf.svg");
}
.create-sample {
.side-option {
color: #666666;
line-height: 24px;
}
@ -749,3 +749,28 @@ html {
.user-descr > b {
margin-left: 25px;
}
.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;
left: -4px;
position: absolute;
top: 50%;
transform: translate(-50%, -50%);
}

View File

@ -24,11 +24,24 @@
*
*/
var directUrl;
if (typeof jQuery !== "undefined") {
jq = jQuery.noConflict();
directUrl = getUrlVars()["directUrl"] == "true";
mustReload = false;
if (directUrl)
jq("#directUrl").prop("checked", directUrl);
else
directUrl = jq("#directUrl").prop("checked");
jq("#directUrl").change(function() {
window.location = "?directUrl=" + jq(this).prop("checked");
});
jq(function () {
jq("#fileupload").fileupload({
dataType: "json",
@ -226,7 +239,7 @@ if (typeof jQuery !== "undefined") {
jq(document).on("click", "#beginEdit:not(.disable)", function () {
var fileId = encodeURIComponent(jq("#hiddenFileName").val());
var url = UrlEditor + "?mode=edit&filename=" + fileId;
var url = UrlEditor + "?mode=edit&filename=" + fileId+ "&directUrl=" + directUrl;
window.open(url, "_blank");
jq("#hiddenFileName").val("");
jq.unblockUI();
@ -234,7 +247,7 @@ if (typeof jQuery !== "undefined") {
jq(document).on("click", "#beginView:not(.disable)", function () {
var fileId = encodeURIComponent(jq("#hiddenFileName").val());
var url = UrlEditor + "?mode=view&filename=" + fileId;
var url = UrlEditor + "?mode=view&filename=" + fileId+ "&directUrl=" + directUrl;
window.open(url, "_blank");
jq("#hiddenFileName").val("");
jq.unblockUI();
@ -242,7 +255,7 @@ if (typeof jQuery !== "undefined") {
jq(document).on("click", "#beginEmbedded:not(.disable)", function () {
var fileId = encodeURIComponent(jq("#hiddenFileName").val());
var url = UrlEditor + "?type=embedded&mode=embedded&filename=" + fileId;
var url = UrlEditor + "?type=embedded&mode=embedded&filename=" + fileId + "&directUrl=" + directUrl;
jq("#mainProgress").addClass("embedded");
jq("#beginEmbedded").addClass("disable");
@ -304,12 +317,12 @@ if (typeof jQuery !== "undefined") {
if (hideTooltipTimeout != null) {
clearTimeout(hideTooltipTimeout);
}
jq(".info").on("touchend", function () {
jq("#info").on("touchend", function () {
showUserTooltip(true);
});
}
} else {
jq(".info").mouseover(function (event) {
jq("#info").mouseover(function (event) {
if (fileList.length > 0) {
if (hideTooltipTimeout != null) {
clearTimeout(hideTooltipTimeout);
@ -333,4 +346,29 @@ if (typeof jQuery !== "undefined") {
}, 500);
});
}
function getUrlVars() {
var vars = [], hash;
var hashes = window.location.href.slice(window.location.href.indexOf('?') + 1).split('&');
for (var i = 0; i < hashes.length; i++) {
hash = hashes[i].split('=');
vars.push(hash[0]);
vars[hash[0]] = hash[1];
}
return vars;
};
jq(".info-tooltip").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 class='arrow'></div></div>").appendTo("body");
var top = jq("#" + id).offset().top + jq("#" + id).outerHeight() / 2 - jq("div.tooltip").outerHeight() / 2;
var left = jq("#" + id).offset().left + jq("#" + id).outerWidth() + 20;
jq("div.tooltip").css({"top": top, "left": left});
}).mouseout(function () {
jq("div.tooltip").remove();
});
}

View File

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

View File

@ -2,7 +2,7 @@ source 'https://rubygems.org'
gem 'mimemagic', github: 'mimemagicrb/mimemagic', ref: '01f92d86d15d85cfd0f20dabd025dcbd36a8a60f'
# Bundle edge Rails instead: gem 'rails', github: 'rails/rails'
gem 'rails', '6.1.4.1'
gem 'rails', '7.0.3.1'
# Use sqlite3 as the database for Active Record
gem 'sqlite3', '1.4.2'
# Use SCSS for stylesheets
@ -19,9 +19,11 @@ gem 'jquery-rails'
# Turbolinks makes following links in your web application faster. Read more: https://github.com/rails/turbolinks
gem 'turbolinks'
# Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder
gem 'jbuilder', '~> 2.9.1'
gem 'jbuilder', '~> 2.11.5'
# bundle exec rake doc:rails generates the API under doc/api.
gem 'sdoc', '~> 0.4.0', group: :doc
gem 'sdoc', '~> 2.4.0', group: :doc
gem "tzinfo-data"
# Use ActiveModel has_secure_password
# gem 'bcrypt', '~> 3.1.7'
@ -37,12 +39,9 @@ group :development, :test do
gem 'byebug'
# Access an IRB console on exception pages or by using <%= console %> in views
gem 'web-console', '~> 2.0'
gem 'web-console', '~> 4.2.0'
end
# Windows does not include zoneinfo files, so bundle the tzinfo-data gem
gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby]
gem 'uuid'
gem 'rack-cors'

View File

@ -8,67 +8,72 @@ GIT
GEM
remote: https://rubygems.org/
specs:
actioncable (6.1.4.1)
actionpack (= 6.1.4.1)
activesupport (= 6.1.4.1)
actioncable (7.0.3.1)
actionpack (= 7.0.3.1)
activesupport (= 7.0.3.1)
nio4r (~> 2.0)
websocket-driver (>= 0.6.1)
actionmailbox (6.1.4.1)
actionpack (= 6.1.4.1)
activejob (= 6.1.4.1)
activerecord (= 6.1.4.1)
activestorage (= 6.1.4.1)
activesupport (= 6.1.4.1)
actionmailbox (7.0.3.1)
actionpack (= 7.0.3.1)
activejob (= 7.0.3.1)
activerecord (= 7.0.3.1)
activestorage (= 7.0.3.1)
activesupport (= 7.0.3.1)
mail (>= 2.7.1)
actionmailer (6.1.4.1)
actionpack (= 6.1.4.1)
actionview (= 6.1.4.1)
activejob (= 6.1.4.1)
activesupport (= 6.1.4.1)
net-imap
net-pop
net-smtp
actionmailer (7.0.3.1)
actionpack (= 7.0.3.1)
actionview (= 7.0.3.1)
activejob (= 7.0.3.1)
activesupport (= 7.0.3.1)
mail (~> 2.5, >= 2.5.4)
net-imap
net-pop
net-smtp
rails-dom-testing (~> 2.0)
actionpack (6.1.4.1)
actionview (= 6.1.4.1)
activesupport (= 6.1.4.1)
rack (~> 2.0, >= 2.0.9)
actionpack (7.0.3.1)
actionview (= 7.0.3.1)
activesupport (= 7.0.3.1)
rack (~> 2.0, >= 2.2.0)
rack-test (>= 0.6.3)
rails-dom-testing (~> 2.0)
rails-html-sanitizer (~> 1.0, >= 1.2.0)
actiontext (6.1.4.1)
actionpack (= 6.1.4.1)
activerecord (= 6.1.4.1)
activestorage (= 6.1.4.1)
activesupport (= 6.1.4.1)
actiontext (7.0.3.1)
actionpack (= 7.0.3.1)
activerecord (= 7.0.3.1)
activestorage (= 7.0.3.1)
activesupport (= 7.0.3.1)
globalid (>= 0.6.0)
nokogiri (>= 1.8.5)
actionview (6.1.4.1)
activesupport (= 6.1.4.1)
actionview (7.0.3.1)
activesupport (= 7.0.3.1)
builder (~> 3.1)
erubi (~> 1.4)
rails-dom-testing (~> 2.0)
rails-html-sanitizer (~> 1.1, >= 1.2.0)
activejob (6.1.4.1)
activesupport (= 6.1.4.1)
activejob (7.0.3.1)
activesupport (= 7.0.3.1)
globalid (>= 0.3.6)
activemodel (6.1.4.1)
activesupport (= 6.1.4.1)
activerecord (6.1.4.1)
activemodel (= 6.1.4.1)
activesupport (= 6.1.4.1)
activestorage (6.1.4.1)
actionpack (= 6.1.4.1)
activejob (= 6.1.4.1)
activerecord (= 6.1.4.1)
activesupport (= 6.1.4.1)
marcel (~> 1.0.0)
activemodel (7.0.3.1)
activesupport (= 7.0.3.1)
activerecord (7.0.3.1)
activemodel (= 7.0.3.1)
activesupport (= 7.0.3.1)
activestorage (7.0.3.1)
actionpack (= 7.0.3.1)
activejob (= 7.0.3.1)
activerecord (= 7.0.3.1)
activesupport (= 7.0.3.1)
marcel (~> 1.0)
mini_mime (>= 1.1.0)
activesupport (6.1.4.1)
activesupport (7.0.3.1)
concurrent-ruby (~> 1.0, >= 1.0.2)
i18n (>= 1.6, < 2)
minitest (>= 5.1)
tzinfo (~> 2.0)
zeitwerk (~> 2.3)
binding_of_caller (1.0.0)
debug_inspector (>= 0.0.1)
bindex (0.8.1)
builder (3.2.4)
byebug (11.1.3)
coffee-rails (5.0.0)
@ -80,24 +85,24 @@ GEM
coffee-script-source (1.12.2)
concurrent-ruby (1.1.10)
crass (1.0.6)
debug_inspector (1.1.0)
erubi (1.10.0)
digest (3.1.0)
erubi (1.11.0)
execjs (2.8.1)
ffi (1.15.5)
ffi (1.15.5-x64-mingw32)
ffi (1.15.5-x64-mingw-ucrt)
globalid (1.0.0)
activesupport (>= 5.0)
i18n (1.12.0)
concurrent-ruby (~> 1.0)
jbuilder (2.9.1)
activesupport (>= 4.2.0)
jbuilder (2.11.5)
actionview (>= 5.0.0)
activesupport (>= 5.0.0)
jquery-rails (4.5.0)
rails-dom-testing (>= 1, < 3)
railties (>= 4.2.0)
thor (>= 0.14, < 2.0)
json (1.8.6)
jwt (2.4.1)
loofah (2.18.0)
loofah (2.19.0)
crass (~> 1.0.2)
nokogiri (>= 1.5.9)
macaddr (1.7.2)
@ -107,61 +112,75 @@ GEM
marcel (1.0.2)
method_source (1.0.0)
mini_mime (1.1.2)
minitest (5.16.2)
minitest (5.16.3)
net-imap (0.2.3)
digest
net-protocol
strscan
net-pop (0.1.1)
digest
net-protocol
timeout
net-protocol (0.1.3)
timeout
net-smtp (0.3.1)
digest
net-protocol
timeout
nio4r (2.5.8)
nokogiri (1.13.8-x64-mingw32)
nokogiri (1.13.9-x64-mingw-ucrt)
racc (~> 1.4)
nokogiri (1.13.8-x86_64-linux)
nokogiri (1.13.9-x86_64-linux)
racc (~> 1.4)
psych (4.0.5)
stringio
racc (1.6.0)
rack (2.2.4)
rack-cors (1.1.1)
rack (>= 2.0.0)
rack-test (2.0.2)
rack (>= 1.3)
rails (6.1.4.1)
actioncable (= 6.1.4.1)
actionmailbox (= 6.1.4.1)
actionmailer (= 6.1.4.1)
actionpack (= 6.1.4.1)
actiontext (= 6.1.4.1)
actionview (= 6.1.4.1)
activejob (= 6.1.4.1)
activemodel (= 6.1.4.1)
activerecord (= 6.1.4.1)
activestorage (= 6.1.4.1)
activesupport (= 6.1.4.1)
rails (7.0.3.1)
actioncable (= 7.0.3.1)
actionmailbox (= 7.0.3.1)
actionmailer (= 7.0.3.1)
actionpack (= 7.0.3.1)
actiontext (= 7.0.3.1)
actionview (= 7.0.3.1)
activejob (= 7.0.3.1)
activemodel (= 7.0.3.1)
activerecord (= 7.0.3.1)
activestorage (= 7.0.3.1)
activesupport (= 7.0.3.1)
bundler (>= 1.15.0)
railties (= 6.1.4.1)
sprockets-rails (>= 2.0.0)
railties (= 7.0.3.1)
rails-dom-testing (2.0.3)
activesupport (>= 4.2.0)
nokogiri (>= 1.6)
rails-html-sanitizer (1.4.3)
loofah (~> 2.3)
railties (6.1.4.1)
actionpack (= 6.1.4.1)
activesupport (= 6.1.4.1)
railties (7.0.3.1)
actionpack (= 7.0.3.1)
activesupport (= 7.0.3.1)
method_source
rake (>= 0.13)
rake (>= 12.2)
thor (~> 1.0)
zeitwerk (~> 2.5)
rake (13.0.6)
rdoc (4.3.0)
rdoc (6.4.0)
psych (>= 4.0.0)
sass-rails (6.0.0)
sassc-rails (~> 2.1, >= 2.1.1)
sassc (2.4.0)
ffi (~> 1.9)
sassc (2.4.0-x64-mingw32)
ffi (~> 1.9)
sassc-rails (2.1.2)
railties (>= 4.0.0)
sassc (>= 2.0)
sprockets (> 3.0)
sprockets-rails
tilt
sdoc (0.4.2)
json (~> 1.7, >= 1.7.7)
rdoc (~> 4.0)
sdoc (2.4.0)
rdoc (>= 5.0)
sprockets (4.1.1)
concurrent-ruby (~> 1.0)
rack (> 1, < 3)
@ -170,25 +189,28 @@ GEM
activesupport (>= 5.2)
sprockets (>= 3.0.0)
sqlite3 (1.4.2)
stringio (3.0.2)
strscan (3.0.4)
systemu (2.6.5)
thor (1.2.1)
tilt (2.0.11)
timeout (0.3.0)
turbolinks (5.2.1)
turbolinks-source (~> 5.2)
turbolinks-source (5.2.0)
tzinfo (2.0.5)
concurrent-ruby (~> 1.0)
tzinfo-data (1.2022.1)
tzinfo-data (1.2022.4)
tzinfo (>= 1.0.0)
uglifier (4.2.0)
execjs (>= 0.3.0, < 3)
uuid (2.3.9)
macaddr (~> 1.0)
web-console (2.3.0)
activemodel (>= 4.0)
binding_of_caller (>= 0.7.2)
railties (>= 4.0)
sprockets-rails (>= 2.0, < 4.0)
web-console (4.2.0)
actionview (>= 6.0.0)
activemodel (>= 6.0.0)
bindex (>= 0.4.0)
railties (>= 6.0.0)
webrick (1.7.0)
websocket-driver (0.7.5)
websocket-extensions (>= 0.1.0)
@ -196,27 +218,27 @@ GEM
zeitwerk (2.6.0)
PLATFORMS
x64-mingw32
x64-mingw-ucrt
x86_64-linux
DEPENDENCIES
byebug
coffee-rails (~> 5.0.0)
jbuilder (~> 2.9.1)
jbuilder (~> 2.11.5)
jquery-rails
jwt (~> 2.4.1)
mimemagic!
rack-cors
rails (= 6.1.4.1)
rails (= 7.0.3.1)
sass-rails (~> 6.0)
sdoc (~> 0.4.0)
sdoc (~> 2.4.0)
sqlite3 (= 1.4.2)
turbolinks
tzinfo-data
uglifier (>= 4.2.0)
uuid
web-console (~> 2.0)
web-console (~> 4.2.0)
webrick
BUNDLED WITH
2.2.22
2.3.7

View File

@ -16,11 +16,35 @@
*
*/
var directUrl;
var userId;
if (typeof jQuery != "undefined") {
jq = jQuery.noConflict();
directUrl = getUrlVars()["directUrl"] == "true";
userId = getUrlVars()["userId"];
mustReload = false;
if (directUrl)
jq("#directUrl").prop("checked", directUrl);
else
directUrl = jq("#directUrl").prop("checked");
jq("#directUrl").change(function() {
window.location = "?directUrl=" + jq(this).prop("checked") + "&userId=" + userId;
});
if (userId)
jq("#user").val(userId);
else
userId = jq("#user").val();
jq("#user").change(function() {
window.location = "?directUrl=" + directUrl + "&userId=" + jq(this).val();
});
jq(function () {
jq('#fileupload').fileupload({
dataType: 'json',
@ -173,7 +197,6 @@ if (typeof jQuery != "undefined") {
};
var initSelectors = function () {
var userSel = jq("#user");
var langSel = jq("#language");
function getCookie(name) {
@ -186,14 +209,9 @@ if (typeof jQuery != "undefined") {
document.cookie = name + "=" + value + "; expires=" + new Date(Date.now() + 1000 * 60 * 60 * 24 * 7).toUTCString(); //week
}
var userId = getCookie("uid");
if (userId) userSel.val(userId);
var langId = getCookie("ulang");
if (langId) langSel.val(langId);
userSel.on("change", function () {
setCookie("uid", userSel.val());
});
langSel.on("change", function () {
setCookie("ulang", langSel.val());
});
@ -218,7 +236,7 @@ if (typeof jQuery != "undefined") {
jq(document).on("click", "#beginEdit:not(.disable)", function () {
var fileId = encodeURIComponent(jq('#hiddenFileName').val());
var url = UrlEditor + "?fileName=" + fileId;
var url = UrlEditor + "?fileName=" + fileId + "&directUrl=" + directUrl + "&userId=" + userId;
window.open(url, "_blank");
jq('#hiddenFileName').val("");
jq.unblockUI();
@ -226,7 +244,7 @@ if (typeof jQuery != "undefined") {
jq(document).on("click", "#beginView:not(.disable)", function () {
var fileId = encodeURIComponent(jq('#hiddenFileName').val());
var url = UrlEditor + "?editorsMode=view&fileName=" + fileId;
var url = UrlEditor + "?editorsMode=view&fileName=" + fileId + "&directUrl=" + directUrl + "&userId=" + userId;
window.open(url, "_blank");
jq('#hiddenFileName').val("");
jq.unblockUI();
@ -234,7 +252,7 @@ if (typeof jQuery != "undefined") {
jq(document).on("click", "#beginEmbedded:not(.disable)", function () {
var fileId = encodeURIComponent(jq('#hiddenFileName').val());
var url = UrlEditor + "?editorsType=embedded&editorsMode=embedded&fileName=" + fileId;
var url = UrlEditor + "?editorsType=embedded&editorsMode=embedded&fileName=" + fileId + "&directUrl=" + directUrl + "&userId=" + userId;
jq("#mainProgress").addClass("embedded");
jq("#beginEmbedded").addClass("disable");
@ -256,6 +274,9 @@ if (typeof jQuery != "undefined") {
if (jq("#createSample").is(":checked")) {
url += "&sample=true";
}
if (userId) {
url += "&userId=" + userId;
}
var w = window.open(url, "_blank");
w.onload = function () {
window.location.reload();
@ -286,6 +307,17 @@ if (typeof jQuery != "undefined") {
}
};
function getUrlVars() {
var vars = [], hash;
var hashes = window.location.href.slice(window.location.href.indexOf('?') + 1).split('&');
for (var i = 0; i < hashes.length; i++) {
hash = hashes[i].split('=');
vars.push(hash[0]);
vars[hash[0]] = hash[1];
}
return vars;
};
var fileList = jq("tr.tableRow");
var mouseIsOverTooltip = false;
@ -296,12 +328,12 @@ if (typeof jQuery != "undefined") {
if (hideTooltipTimeout != null) {
clearTimeout(hideTooltipTimeout);
}
jq(".info").on("touchend", function () {
jq("#info").on("touchend", function () {
showUserTooltip(true);
});
}
} else {
jq(".info").mouseover(function (event) {
jq("#info").mouseover(function (event) {
if (fileList.length > 0) {
if (hideTooltipTimeout != null) {
clearTimeout(hideTooltipTimeout);
@ -325,4 +357,18 @@ if (typeof jQuery != "undefined") {
}, 500);
});
}
jq(".info-tooltip").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 class='arrow'></div></div>").appendTo("body");
var top = jq("#" + id).offset().top + jq("#" + id).outerHeight() / 2 - jq("div.tooltip").outerHeight() / 2;
var left = jq("#" + id).offset().left + jq("#" + id).outerWidth() + 20;
jq("div.tooltip").css({"top": top, "left": left});
}).mouseout(function () {
jq("div.tooltip").remove();
});
}

View File

@ -168,7 +168,7 @@ label .checkbox {
background-image: url("file_docxf.svg");
}
.create-sample {
.side-option {
color: #666666;
line-height: 24px;
}
@ -742,3 +742,28 @@ html {
.user-descr > b {
margin-left: 25px;
}
.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;
left: -4px;
position: absolute;
top: 50%;
transform: translate(-50%, -50%);
}

View File

@ -24,9 +24,8 @@ class HomeController < ApplicationController
def editor
DocumentHelper.init(request.remote_ip, request.base_url)
user = Users.get_user(cookies[:uid])
@file = FileModel.new(:file_name => File.basename(params[:fileName]), :mode => params[:editorsMode], :type => params[:editorsType], :user_ip => request.remote_ip, :lang => cookies[:ulang], :user => user, :action_data => params[:actionLink])
user = Users.get_user(params[:userId])
@file = FileModel.new(:file_name => File.basename(params[:fileName]), :mode => params[:editorsMode], :type => params[:editorsType], :user_ip => request.remote_ip, :lang => cookies[:ulang], :user => user, :action_data => params[:actionLink], :direct_url => params[:directUrl])
end
@ -34,10 +33,9 @@ class HomeController < ApplicationController
def sample
DocumentHelper.init(request.remote_ip, request.base_url)
user = Users.get_user(cookies[:uid])
user = Users.get_user(params[:userId])
file_name = DocumentHelper.create_demo(params[:fileExt], params[:sample], user)
redirect_to :controller => 'home', :action => 'editor', :fileName => file_name
redirect_to :controller => 'home', :action => 'editor', :fileName => file_name, :userId => user.id
end
@ -73,7 +71,7 @@ class HomeController < ApplicationController
end
# create file meta information
user = Users.get_user(cookies[:uid])
user = Users.get_user(params[:userId])
DocumentHelper.create_meta(file_name, user.id, user.name, nil)
@ -134,7 +132,7 @@ class HomeController < ApplicationController
end
file_name = correct_name
user = Users.get_user(cookies[:uid])
user = Users.get_user(params[:userId])
DocumentHelper.create_meta(file_name, user.id, user.name, nil) # create meta data of the new file
end
@ -177,7 +175,7 @@ class HomeController < ApplicationController
# add headers to the response to specify the page parameters
response.headers['Content-Length'] = File.size(file_path).to_s
response.headers['Content-Type'] = MimeMagic.by_path(file_path).eql?(nil) ? nil : MimeMagic.by_path(file_path).type
response.headers['Content-Disposition'] = "attachment;filename*=UTF-8\'\'" + URI.escape(file, Regexp.new("[^#{URI::PATTERN::UNRESERVED}]"))
response.headers['Content-Disposition'] = "attachment;filename*=UTF-8\'\'" + ERB::Util.url_encode(file)
send_file file_path, :x_sendfile => true
rescue => ex
@ -262,7 +260,7 @@ class HomeController < ApplicationController
# add headers to the response to specify the page parameters
response.headers['Content-Length'] = File.size(csvPath).to_s
response.headers['Content-Type'] = MimeMagic.by_path(csvPath).type
response.headers['Content-Disposition'] = "attachment;filename*=UTF-8\'\'" + URI.escape(file_name, Regexp.new("[^#{URI::PATTERN::UNRESERVED}]"))
response.headers['Content-Disposition'] = "attachment;filename*=UTF-8\'\'" + ERB::Util.url_encode(file_name)
send_file csvPath, :x_sendfile => true
end
@ -295,7 +293,7 @@ class HomeController < ApplicationController
# add headers to the response to specify the page parameters
response.headers['Content-Length'] = File.size(file_path).to_s
response.headers['Content-Type'] = MimeMagic.by_path(file_path).eql?(nil) ? nil : MimeMagic.by_path(file_path).type
response.headers['Content-Disposition'] = "attachment;filename*=UTF-8\'\'" + URI.escape(file_name, Regexp.new("[^#{URI::PATTERN::UNRESERVED}]"))
response.headers['Content-Disposition'] = "attachment;filename*=UTF-8\'\'" + ERB::Util.url_encode(file_name)
send_file file_path, :x_sendfile => true
rescue => ex
@ -335,7 +333,7 @@ class HomeController < ApplicationController
File.open(DocumentHelper.storage_path(file_name, nil), 'wb') do |file|
file.write(data)
end
user = Users.get_user(cookies[:uid])
user = Users.get_user(params[:userId])
DocumentHelper.create_meta(file_name, user.id, user.name, nil) # create meta data of the new file
render plain: '{"file" : "' + file_name + '"}'

View File

@ -230,7 +230,7 @@ class DocumentHelper
# get file url
def get_file_uri(file_name, for_document_server)
uri = get_server_url(for_document_server) + '/' + Rails.configuration.storagePath + '/' + cur_user_host_address(nil) + '/' + URI::encode(file_name)
uri = get_server_url(for_document_server) + '/' + Rails.configuration.storagePath + '/' + cur_user_host_address(nil) + '/' + ERB::Util.url_encode(file_name)
return uri
end
@ -239,7 +239,7 @@ class DocumentHelper
def get_historypath_uri(file_name,version,file,is_serverUrl=true)
# for redirection to my link
user_host = is_serverUrl ? '&userAddress=' + cur_user_host_address(nil) : ""
uri = get_server_url(is_serverUrl) + '/downloadhistory/?fileName=' + URI::encode(file_name) + '&ver='+ version.to_s + '&file='+ URI::encode(file) + user_host
uri = get_server_url(is_serverUrl) + '/downloadhistory/?fileName=' + ERB::Util.url_encode(file_name) + '&ver='+ version.to_s + '&file='+ ERB::Util.url_encode(file) + user_host
return uri
end
@ -255,7 +255,7 @@ class DocumentHelper
# get callback url
def get_callback(file_name)
get_server_url(true) + '/track?fileName=' + URI::encode(file_name) + '&userAddress=' + cur_user_host_address(nil)
get_server_url(true) + '/track?fileName=' + ERB::Util.url_encode(file_name) + '&userAddress=' + cur_user_host_address(nil)
end
@ -270,7 +270,7 @@ class DocumentHelper
def get_download_url(file_name, is_serverUrl=true)
user_host = is_serverUrl ? '&userAddress=' + cur_user_host_address(nil) : ""
get_server_url(is_serverUrl) + '/download?fileName=' + URI::encode(file_name) + user_host
get_server_url(is_serverUrl) + '/download?fileName=' + ERB::Util.url_encode(file_name) + user_host
end

View File

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

View File

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

View File

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

View File

@ -44,7 +44,7 @@
<a class="try-editor form" data-type="docxf">Form template</a>
</li>
</ul>
<label class="create-sample">
<label class="side-option">
<input id="createSample" class="checkbox" type="checkbox" />With sample content
</label>
</div>
@ -60,7 +60,7 @@
<tr>
<td valign="middle">
<span class="select-user">Username</span>
<img class="info" data-id="user" src="assets/info.svg" />
<img id="info" class="info" data-id="user" src="assets/info.svg" />
<select class="select-user" id="user">
<% for user in Users.get_all_users() do %>
<option value="<%= user.id %>"><%= user.name ? user.name : "Anonymous" %></option>
@ -70,7 +70,10 @@
</tr>
<tr>
<td valign="middle">
<span class="select-user">Language editors interface</span>
<span class="select-user">Language</span>
<img class="info info-tooltip" data-id="language"
data-tooltip="Choose the language for ONLYOFFICE editors interface"
src="assets/info.svg" />
<select class="select-user" id="language">
<% Rails.configuration.languages.each { |key, language|%>
<option value="<%=key %>"> <%=language %> </option>
@ -78,6 +81,14 @@
</select>
</td>
</tr>
<tr>
<td valign="middle">
<label class="side-option">
<input id="directUrl" type="checkbox" class="checkbox" />Try opening on client
<img id="directUrlInfo" class="info info-tooltip" data-id="directUrlInfo" data-tooltip="Some files can be opened in the user's browser without connecting to the document server." src="assets/info.svg" />
</label>
</td>
</tr>
</tbody>
</table>
</div>
@ -87,6 +98,8 @@
<%
DocumentHelper.init(request.remote_ip, request.base_url)
docs = DocumentHelper.get_stored_files(nil)
directUrl = request.params[:directUrl]
userId = request.params[:userId]
%>
<div class="main-panel">
<div id="portal-info" style="display: <%= docs.length > 0 ? "none" : "table-cell" %>">
@ -128,7 +141,9 @@
<%
docs.each { |d|
isFillFormDoc = DocumentHelper.fill_forms_exts.include?(File.extname(d).downcase)
editUrl = "editor?fileName=#{URI::encode(d)}"
userIdParam = userId == nil ? "" : "&userId=#{userId}";
directUrlParam = directUrl == nil ? "" : "&directUrl=#{directUrl}";
editUrl = "editor?fileName=#{ERB::Util.url_encode(d)}" + directUrlParam + userIdParam;
docType = FileUtility.get_file_type(d)
canEdit = DocumentHelper.edited_exts.include?(File.extname(d).downcase) %>
<tr class="tableRow" title="<%= d %> [<%= DocumentHelper.get_file_version(DocumentHelper.history_dir(DocumentHelper.storage_path(d, nil))) %>]">
@ -221,7 +236,7 @@
</a>
</td>
<td class="contentCells contentCells-shift contentCells-icon downloadContentCellShift">
<a href="<%= "download?fileName=#{URI::encode(d)}" %>">
<a href="<%= "download?fileName=#{ERB::Util.url_encode(d)}" %>">
<img class="icon-download" src="assets/download.svg" alt="Download" title="Download" />
</a>
</td>

View File

@ -26,7 +26,7 @@ module OnlineEditorsExampleRuby
end
end
Rails.configuration.version="1.3.0"
Rails.configuration.version="1.4.0"
Rails.configuration.fileSizeMax=5242880
Rails.configuration.storagePath="app_data"
@ -88,7 +88,8 @@ module OnlineEditorsExampleRuby
'sv' => 'Swedish',
'tr' => 'Turkish',
'uk' => 'Ukrainian',
'vi' => 'Vietnamese'
'vi' => 'Vietnamese',
'aa-AA' => 'Test Language'
}
end
end