Compare commits

..

18 Commits

530 changed files with 13778 additions and 16727 deletions

View File

@ -3,10 +3,10 @@ name: Artifact Csharp MVC
on:
workflow_dispatch:
push:
branches: [master]
branches: [master, main]
paths: ['web/documentserver-example/csharp-mvc/**']
pull_request:
branches: [master]
branches: [master, main]
paths: ['web/documentserver-example/csharp-mvc/**']
jobs:
@ -21,9 +21,11 @@ jobs:
cwd=$(pwd)
git submodule update --init --recursive
cd ./web/documentserver-example/csharp-mvc
mkdir -p ./deploy/'DotNet (Csharp MVC) Example'
mkdir -p ./deploy/'DotNet (Csharp MVN) Example'
rsync -av --exclude='deploy' ./ ./deploy/'DotNet (Csharp MVC) Example'
rm -rf ./deploy/'DotNet (Csharp MVC) Example'/assets/.git
cd ./deploy/'DotNet (Csharp MVC) Example'/assets
rm -rf ./.git/
rm .git
- name: Upload Artifact
uses: actions/upload-artifact@v3
with:

View File

@ -3,10 +3,10 @@ name: Artifact Csharp
on:
workflow_dispatch:
push:
branches: [master]
branches: [master, main]
paths: ['web/documentserver-example/csharp/**']
pull_request:
branches: [master]
branches: [master, main, develop]
paths: ['web/documentserver-example/csharp/**']
jobs:
@ -18,11 +18,14 @@ jobs:
- name: Build Artifact
run: |
cd ${{ github.workspace }}
cwd=$(pwd)
git submodule update --init --recursive
cd ./web/documentserver-example/csharp
mkdir -p ./deploy/'DotNet (Csharp) Example'
rsync -av --exclude='deploy' ./ ./deploy/'DotNet (Csharp) Example'
rm -rf ./deploy/'DotNet (Csharp) Example'/assets/.git
cd ./deploy/'DotNet (Csharp) Example'/assets
rm -rf ./.git/
rm .git
- name: Upload Artifact
uses: actions/upload-artifact@v3
with:

View File

@ -3,10 +3,10 @@ name: Artifact Java
on:
workflow_dispatch:
push:
branches: [master]
branches: [master, main]
paths: ['web/documentserver-example/java/**']
pull_request:
branches: [master]
branches: [master, main]
paths: ['web/documentserver-example/java/**']
jobs:
@ -18,12 +18,14 @@ jobs:
- name: Build Artifact
run: |
cd ${{ github.workspace }}
cwd=$(pwd)
git submodule update --init --recursive
cd ./web/documentserver-example/java
mkdir -p ./deploy/'Java Example'
rsync -av --exclude='deploy' ./ ./deploy/'Java Example'
rm -rf ./deploy/'Java Example'/src/main/resources/assets/document-formats/.git
rm -rf ./deploy/'Java Example'/src/main/resources/assets/document-templates/.git
cd ./deploy/'Java Example'/src/main/resources/assets
rm -rf ./.git/
rm .git
- name: Upload Artifact
uses: actions/upload-artifact@v3
with:

View File

@ -3,10 +3,10 @@ name: Artifact Nodejs
on:
workflow_dispatch:
push:
branches: [master]
branches: [master, main]
paths: ['web/documentserver-example/nodejs/**']
pull_request:
branches: [master]
branches: [master, main]
paths: ['web/documentserver-example/nodejs/**']
jobs:
@ -18,12 +18,14 @@ jobs:
- name: Build Artifact
run: |
cd ${{ github.workspace }}
cwd=$(pwd)
git submodule update --init --recursive
cd ./web/documentserver-example/nodejs
mkdir -p ./deploy/'Node.js Example'
rsync -av --exclude='deploy' ./ ./deploy/'Node.js Example'
rm -rf ./deploy/'Node.js Example'/public/assets/document-formats/.git
rm -rf ./deploy/'Node.js Example'/public/assets/document-templates/.git
cd ./deploy/'Node.js Example'/public/assets
rm -rf ./.git/
rm .git
- name: Upload Artifact
uses: actions/upload-artifact@v3
with:

View File

@ -3,10 +3,10 @@ name: Artifact PHP
on:
workflow_dispatch:
push:
branches: [master]
branches: [master, main]
paths: ['web/documentserver-example/php/**']
pull_request:
branches: [master]
branches: [master, main]
paths: ['web/documentserver-example/php/**']
jobs:
@ -18,12 +18,14 @@ jobs:
- name: Build Artifact
run: |
cd ${{ github.workspace }}
cwd=$(pwd)
git submodule update --init --recursive
cd ./web/documentserver-example/php
mkdir -p ./deploy/'PHP Example'
rsync -av --exclude='deploy' ./ ./deploy/'PHP Example'
rm -rf ./deploy/'PHP Example'/assets/document-formats/.git
rm -rf ./deploy/'PHP Example'/assets/document-templates/.git
cd ./deploy/'PHP Example'/assets
rm -rf ./.git/
rm .git
- name: Upload Artifact
uses: actions/upload-artifact@v3
with:

View File

@ -3,10 +3,10 @@ name: Artifact Python
on:
workflow_dispatch:
push:
branches: [master]
branches: [master, main]
paths: ['web/documentserver-example/python/**']
pull_request:
branches: [master]
branches: [master, main]
paths: ['web/documentserver-example/python/**']
jobs:
@ -18,12 +18,14 @@ jobs:
- name: Build Artifact
run: |
cd ${{ github.workspace }}
cwd=$(pwd)
git submodule update --init --recursive
cd ./web/documentserver-example/python
mkdir -p ./deploy/'Python Example'
rsync -av --exclude='deploy' ./ ./deploy/'Python Example'
rm -rf ./deploy/'Python Example'/assets/document-formats/.git
rm -rf ./deploy/'Python Example'/assets/document-templates/.git
cd ./deploy/'Python Example'/assets
rm -rf ./.git/
rm .git
- name: Upload Artifact
uses: actions/upload-artifact@v3
with:

View File

@ -3,10 +3,10 @@ name: Artifact Ruby
on:
workflow_dispatch:
push:
branches: [master]
branches: [master, main]
paths: ['web/documentserver-example/ruby/**']
pull_request:
branches: [master]
branches: [master, main]
paths: ['web/documentserver-example/ruby/**']
jobs:
@ -18,12 +18,14 @@ jobs:
- name: Build Artifact
run: |
cd ${{ github.workspace }}
cwd=$(pwd)
git submodule update --init --recursive
cd ./web/documentserver-example/ruby
mkdir -p ./deploy/'Ruby Example'
rsync -av --exclude='deploy' ./ ./deploy/'Ruby Example'
rm -rf ./deploy/'Ruby Example'/public/assets/document-formats/.git
rm -rf ./deploy/'Ruby Example'/public/assets/document-templates/.git
cd ./deploy/'Ruby Example'/public/assets
rm -rf ./.git/
rm .git
- name: Upload Artifact
uses: actions/upload-artifact@v3
with:

View File

@ -3,10 +3,10 @@ name: Artifact Java Spring
on:
workflow_dispatch:
push:
branches: [master]
branches: [master, main]
paths: ['web/documentserver-example/java-spring/**']
pull_request:
branches: [master]
branches: [master, main]
paths: ['web/documentserver-example/java-spring/**']
jobs:
@ -23,8 +23,9 @@ jobs:
cd ./web/documentserver-example/java-spring
mkdir -p ./deploy/'Java Spring Example'
rsync -av --exclude='deploy' ./ ./deploy/'Java Spring Example'
rm -rf ./deploy/'Java Spring Example'/src/main/resources/assets/document-formats/.git
rm -rf ./deploy/'Java Spring Example'/src/main/resources/assets/document-templates/.git
cd ./deploy/'Java Spring Example'/src/main/resources/assets
rm -rf ./.git/
rm .git
- name: Upload Artifact
uses: actions/upload-artifact@v3
with:

View File

@ -26,4 +26,4 @@ jobs:
tools: cs2pr, phpcs
- name: Lint
run: phpcs src index.php
run: phpcs .

View File

@ -21,17 +21,20 @@ jobs:
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.11'
python-version: '3.10'
- name: Install Dependencies
run: |
make dev
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: |
make lint
# TODO: Configure mypy
# - name: Types mypy
# run: |
# make types
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

View File

@ -16,22 +16,16 @@ jobs:
run:
working-directory: ./web/documentserver-example/ruby
steps:
- name: Checkout Repository
uses: actions/checkout@v3
- name: Setup Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: '3.2.2'
- name: Update Submodules
run: |
git submodule update --init --recursive
- name: Install Dependencies
run: |
bundle update
- name: Rubocop
run: |
bundle exec rubocop
- 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

View File

@ -13,10 +13,8 @@ jobs:
steps:
- name: Checkout Repository
uses: actions/checkout@v3
- name: Clone Submodules
run: |
cd ${{ github.workspace }}
git submodule update --init --recursive
- name: Install Zip
run: sudo apt-get install zip
- name: Get Info
run: |
echo "version=$(grep -Eo '[0-9]+(\.[0-9]+)+' CHANGELOG.md | head -n 1)" >> $GITHUB_OUTPUT
@ -27,66 +25,91 @@ jobs:
- name: Build Csharp MVC Artifact
run: |
cd ${{ github.workspace }}
cwd=$(pwd)
git submodule update --init --recursive
cd ./web/documentserver-example/csharp-mvc
mkdir -p ./'DotNet (Csharp MVC) Example'
rsync -av --exclude='DotNet (Csharp MVC) Example' ./ ./'DotNet (Csharp MVC) Example'
cd ./'DotNet (Csharp MVC) Example'/assets
rm -rf .git
rm -rf ./.git/
rm .git
- name: Build Csharp Artifact
run: |
cd ${{ github.workspace }}
cwd=$(pwd)
git submodule update --init --recursive
cd ./web/documentserver-example/csharp
mkdir -p ./'DotNet (Csharp) Example'
rsync -av --exclude='DotNet (Csharp) Example' ./ ./'DotNet (Csharp) Example'
rm -rf ./'DotNet (Csharp) Example'/assets/.git
cd ./'DotNet (Csharp) Example'/assets
rm -rf ./.git/
rm .git
- name: Build Java Artifact
run: |
cd ${{ github.workspace }}
cwd=$(pwd)
git submodule update --init --recursive
cd ./web/documentserver-example/java
mkdir -p ./'Java Example'
rsync -av --exclude='Java Example' ./ ./'Java Example'
rm -rf ./'Java Example'/src/main/resources/assets/document-formats/.git
rm -rf ./'Java Example'/src/main/resources/assets/document-templates/.git
cd ./'Java Example'/src/main/resources/assets
rm -rf ./.git/
rm .git
- name: Build Nodejs Artifact
run: |
cd ${{ github.workspace }}
cwd=$(pwd)
git submodule update --init --recursive
cd ./web/documentserver-example/nodejs
mkdir -p ./'Node.js Example'
rsync -av --exclude='Node.js Example' ./ ./'Node.js Example'
rm -rf ./'Node.js Example'/public/assets/document-formats/.git
rm -rf ./'Node.js Example'/public/assets/document-templates/.git
cd ./'Node.js Example'/public/assets
rm -rf ./.git/
rm .git
- name: Build PHP Artifact
run: |
cd ${{ github.workspace }}
cwd=$(pwd)
git submodule update --init --recursive
cd ./web/documentserver-example/php
mkdir -p ./'PHP Example'
rsync -av --exclude='PHP Example' ./ ./'PHP Example'
rm -rf ./'PHP Example'/assets/document-formats/.git
rm -rf ./'PHP Example'/assets/document-templates/.git
cd ./'PHP Example'/assets
rm -rf ./.git/
rm .git
- name: Build Python Artifact
run: |
cd ${{ github.workspace }}
cwd=$(pwd)
git submodule update --init --recursive
cd ./web/documentserver-example/python
mkdir -p ./'Python Example'
rsync -av --exclude='Python Example' ./ ./'Python Example'
rm -rf ./'Python Example'/assets/document-formats/.git
rm -rf ./'Python Example'/assets/document-templates/.git
cd ./'Python Example'/assets
rm -rf ./.git/
rm .git
- name: Build Ruby Artifact
run: |
cd ${{ github.workspace }}
cwd=$(pwd)
git submodule update --init --recursive
cd ./web/documentserver-example/ruby
mkdir -p ./'Ruby Example'
rsync -av --exclude='Ruby Example' ./ ./'Ruby Example'
rm -rf ./'Ruby Example'/public/assets/document-formats/.git
rm -rf ./'Ruby Example'/public/assets/document-templates/.git
cd ./'Ruby Example'/public/assets
rm -rf ./.git/
rm .git
- name: Build Spring Artifact
run: |
cd ${{ github.workspace }}
cwd=$(pwd)
git submodule update --init --recursive
cd ./web/documentserver-example/java-spring
mkdir -p ./'Java Spring Example'
rsync -av --exclude='Java Spring Example' ./ ./'Java Spring Example'
rm -rf ./'Java Spring Example'/src/main/resources/assets/document-formats/.git
rm -rf ./'Java Spring Example'/src/main/resources/assets/document-templates/.git
cd ./'Java Spring Example'/src/main/resources/assets
rm -rf ./.git/
rm .git
- name: Pack Artifacts
run: |
cd ${{ github.workspace }}/web/documentserver-example/csharp-mvc

56
.gitmodules vendored
View File

@ -1,3 +1,23 @@
[submodule "web/documentserver-example/java/src/main/resources/assets"]
path = web/documentserver-example/java/src/main/resources/assets
url = https://github.com/ONLYOFFICE/document-templates
branch = main/en
[submodule "web/documentserver-example/csharp-mvc/assets"]
path = web/documentserver-example/csharp-mvc/assets
url = https://github.com/ONLYOFFICE/document-templates
branch = main/en
[submodule "web/documentserver-example/csharp/assets"]
path = web/documentserver-example/csharp/assets
url = https://github.com/ONLYOFFICE/document-templates
branch = main/en
[submodule "web/documentserver-example/ruby/public/assets"]
path = web/documentserver-example/ruby/public/assets
url = https://github.com/ONLYOFFICE/document-templates
branch = main/en
[submodule "web/documentserver-example/java-spring/src/main/resources/assets"]
path = web/documentserver-example/java-spring/src/main/resources/assets
url = https://github.com/ONLYOFFICE/document-templates
branch = main/en
[submodule "web/documentserver-example/nodejs/public/assets/document-templates"]
path = web/documentserver-example/nodejs/public/assets/document-templates
url = https://github.com/ONLYOFFICE/document-templates
@ -5,14 +25,7 @@
[submodule "web/documentserver-example/nodejs/public/assets/document-formats"]
path = web/documentserver-example/nodejs/public/assets/document-formats
url = https://github.com/ONLYOFFICE/document-formats
branch = feature/v8.0
[submodule "web/documentserver-example/csharp-mvc/assets/document-templates"]
path = web/documentserver-example/csharp-mvc/assets/document-templates
url = https://github.com/ONLYOFFICE/document-templates
branch = main/en
[submodule "web/documentserver-example/csharp-mvc/assets/document-formats"]
path = web/documentserver-example/csharp-mvc/assets/document-formats
url = https://github.com/ONLYOFFICE/document-formats
branch = master
[submodule "web/documentserver-example/php/assets/document-templates"]
path = web/documentserver-example/php/assets/document-templates
url = https://github.com/ONLYOFFICE/document-templates
@ -25,34 +38,7 @@
path = web/documentserver-example/python/assets/document-templates
url = https://github.com/ONLYOFFICE/document-templates
branch = main/en
[submodule "web/documentserver-example/java/src/main/resources/assets/document-templates"]
path = web/documentserver-example/java/src/main/resources/assets/document-templates
url = https://github.com/ONLYOFFICE/document-templates
branch = main/en
[submodule "web/documentserver-example/ruby/assets/document-templates"]
path = web/documentserver-example/ruby/assets/document-templates
url = https://github.com/ONLYOFFICE/document-templates
branch = main/en
[submodule "web/documentserver-example/java-spring/src/main/resources/assets/document-templates"]
path = web/documentserver-example/java-spring/src/main/resources/assets/document-templates
url = https://github.com/ONLYOFFICE/document-templates
branch = main/en
[submodule "web/documentserver-example/python/assets/document-formats"]
path = web/documentserver-example/python/assets/document-formats
url = https://github.com/ONLYOFFICE/document-formats
branch = master
[submodule "web/documentserver-example/ruby/assets/document-formats"]
path = web/documentserver-example/ruby/assets/document-formats
url = https://github.com/ONLYOFFICE/document-formats
branch = master
[submodule "web/documentserver-example/java/src/main/resources/assets/document-formats"]
path = web/documentserver-example/java/src/main/resources/assets/document-formats
url = https://github.com/ONLYOFFICE/document-formats
branch = master
[submodule "web/documentserver-example/csharp/assets/document-templates"]
path = web/documentserver-example/csharp/assets/document-templates
url = https://github.com/ONLYOFFICE/document-templates
branch = main/en
[submodule "web/documentserver-example/csharp/assets/document-formats"]
path = web/documentserver-example/csharp/assets/document-formats
url = https://github.com/ONLYOFFICE/document-formats

View File

@ -113,10 +113,6 @@ Prime JWT - is intended to be fast and easy to use. Prime JWT has a single e
License: Apache 2.0
License File: prime-jwt.license
Project Lombok - Spice up your java: Automatic Resource Management, automatic generation of getters, setters, equals, hashCode and toString, and more! (https://projectlombok.org/LICENSE)
License: MIT
License File: lombok.license
web/documentserver-example/java-spring
@ -311,14 +307,6 @@ PHPUnit - The PHP Unit Testing framework. (https://github.com/sebastianb
License: BSD 3-Clause
License File: phpunit.license
property-access - Provides functions to read and write from/to an object or array using a simple string notation. (https://github.com/symfony/property-access/blob/6.3/LICENSE)
License: MIT
License File: property-access.license
serializer - Handles serializing and deserializing data structures, including object graphs, into array structures or other formats like XML and JSON. (https://github.com/symfony/serializer/blob/6.3/LICENSE)
License: MIT
License File: serializer.license
web/documentserver-example/python
@ -358,10 +346,6 @@ jQuery.UI - jQuery UI is an open source library of interface components —
License: MIT
License File: jQuery.UI.license
msgspec - A fast serialization and validation library, with builtin support for JSON, MessagePack, YAML, and TOML. (https://github.com/jcrist/msgspec/blob/0.18.1/LICENSE)
License: BSD 3-Clause
License File: msgspec.license
mypy - Optional static typing for Python. (https://github.com/python/mypy/blob/master/LICENSE)
License: MIT
License File: mypy.license

View File

@ -1,56 +1,14 @@
# Change Log
- java-spring: using java docs-integration-sdk
- en-GB skin language
- save as for pdf
- fill permission in embedded mode
- delete all files
- handling conversion -9 error
- nodejs: wopi formsubmit icon
- nodejs: tabs menu
- change insert image
- different goback for users
- nodejs: converting function on index page
- nodejs: close editor
## 1.8.0
- nodejs: pdf, djvu, xps, oxps as pdf documentType
- nodejs: filling pdf
- version number to page meta
- ar skin languages
- sr-Latn-RS skin languages
- getting history via api
- using a repo with a list of formats
- convert after uploading only tagged formats
- link in referenceData
- setUsers for region protection
- onRequestOpen method
- user avatar
- trimming long name of uploading file
- onRequestSelectDocument method
- onRequestSelectSpreadsheet method
- key in referenceData
- restore from history
## 1.7.0
- nodejs: onRequestSelectDocument method
- nodejs: onRequestSelectSpreadsheet method
- nodejs: onRequestOpen
- nodejs: submitForm
- nodejs: key in referenceData
- nodejs: change reference source
- php: using a repo with a list of formats
- nodejs: using a repo with a list of formats
- nodejs: delete file without reloading the page
- nodejs: getting history by a separate request
- nodejs: restore from history
- php: using a repo with a list of formats
- php: restore from history
- python: restore from history
- ruby: restore from history
- csharp-mvc: getting history by a separate request
- csharp-mvc: restore from history
- csharp: getting history by a separate request
- csharp: restore from history
- php: restore from history
## 1.6.0
- nodejs: setUsers for region protection

View File

@ -1,21 +1,19 @@
## Integration examples
These test examples are simple document management systems that can be built into your application for testing.
Test examples are simple document management systems that can be built into your application for testing.
Do NOT use these integration examples on your own server without proper code modifications!
In case you enabled any of the test examples, disable it before going for production.
These examples show the way to integrate [ONLYOFFICE Docs][2] into your own website or application using one of the programming languages.
The package contains examples written in .Net (C# MVC), .Net (C#), Java, Java Spring, Node.js, PHP, Python and Ruby.
The package contains examples written in .Net (C# MVC), .Net (C#), Java, Node.js, PHP and Ruby.
You should change `http://documentserver` to your server address in these files:
* [.Net (C# MVC)](https://github.com/ONLYOFFICE/document-server-integration/tree/master/web/documentserver-example/csharp-mvc) - `web/documentserver-example/csharp-mvc/web.appsettings.config`
* [.Net (C#)](https://github.com/ONLYOFFICE/document-server-integration/tree/master/web/documentserver-example/csharp) - `web/documentserver-example/csharp/settings.config`
* [Java](https://github.com/ONLYOFFICE/document-server-integration/tree/master/web/documentserver-example/java) - `web/documentserver-example/java/src/main/resources/settings.properties`
* [Java Spring](https://github.com/ONLYOFFICE/document-server-integration/tree/master/web/documentserver-example/java-spring) - `web/documentserver-example/java-spring/src/main/resources/application.properties`
* [Node.js](https://github.com/ONLYOFFICE/document-server-integration/tree/master/web/documentserver-example/nodejs) - `web/documentserver-example/nodejs/config/default.json`
* [PHP](https://github.com/ONLYOFFICE/document-server-integration/tree/master/web/documentserver-example/php) - `web/documentserver-example/php/src/configuration/ConfigurationManager.php`
* [Python](https://github.com/ONLYOFFICE/document-server-integration/tree/master/web/documentserver-example/python) - `web/documentserver-example/python/src/configuration/configuration.py`
* [Ruby](https://github.com/ONLYOFFICE/document-server-integration/tree/master/web/documentserver-example/ruby) - `web/documentserver-example/ruby/app/configuration/configuration.rb`
* [PHP](https://github.com/ONLYOFFICE/document-server-integration/tree/master/web/documentserver-example/php) - `web/documentserver-example/php/config.php`
* [Ruby](https://github.com/ONLYOFFICE/document-server-integration/tree/master/web/documentserver-example/ruby) - `web/documentserver-example/ruby/config/application.rb`
More information on how to use these examples can be found here: [http://api.onlyoffice.com/editors/demopreview](http://api.onlyoffice.com/editors/demopreview "http://api.onlyoffice.com/editors/demopreview")

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1 +1,8 @@
<svg width="30" height="40" viewBox="0 0 30 40" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M0 3c0-1.65685 1.34315-3 3-3h20l7 7v30c0 1.6569-1.3431 3-3 3H3c-1.65685 0-3-1.3431-3-3V3z" fill="#1E7AAA"/><path d="M23 0l7 7h-4c-1.6569 0-3-1.34315-3-3V0z" fill="#000" fill-opacity=".25"/><path d="M6 15h18v1H6v-1zM6 19h18v1H6v-1zM6 23h18v1H6v-1zM6 27h18v1H6v-1z" fill="#fff"/></svg>
<svg width="30" height="40" viewBox="0 0 30 40" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M0 3C0 1.34315 1.34315 0 3 0H21.674C22.4697 0 23.2327 0.316071 23.7953 0.87868L29.1213 6.20465C29.6839 6.76726 30 7.53032 30 8.32597V37C30 38.6569 28.6569 40 27 40H3C1.34315 40 0 38.6569 0 37V3Z" fill="#3779A6"/>
<path d="M22.9167 0L30.0001 7.08333H25.9167C24.2599 7.08333 22.9167 5.74019 22.9167 4.08333V0Z" fill="#1D5880"/>
<path d="M6.17627 14.7059H23.8233V15.8823H6.17627V14.7059Z" fill="white"/>
<path d="M6.17627 18.5294H23.8233V19.7059H6.17627V18.5294Z" fill="white"/>
<path d="M6.17627 22.3529H23.8233V23.5294H6.17627V22.3529Z" fill="white"/>
<path d="M6.17627 26.1765H23.8233V27.3529H6.17627V26.1765Z" fill="white"/>
</svg>

Before

Width:  |  Height:  |  Size: 387 B

After

Width:  |  Height:  |  Size: 738 B

View File

@ -1 +1,6 @@
<svg width="30" height="40" viewBox="0 0 30 40" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M0 3c0-1.65685 1.34315-3 3-3h20l7 7v30c0 1.6569-1.3431 3-3 3H3c-1.65685 0-3-1.3431-3-3V3z" fill="#27ABA3"/><path d="M23 0l7 7h-4c-1.6569 0-3-1.34315-3-3V0z" fill="#008078"/><path fill-rule="evenodd" clip-rule="evenodd" d="M24 14H6v7h18v-7zm-.8182 5.9978H6.81818V15H23.1818v4.9978zM24 23H6v7h18v-7zm-.8182 5.9978H6.81818V24H23.1818v4.9978z" fill="#fff"/></svg>
<svg width="30" height="40" viewBox="0 0 30 40" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M0 3C0 1.34315 1.34315 0 3 0H22.9167L30 7.08333V37C30 38.6569 28.6569 40 27 40H3C1.34315 40 0 38.6569 0 37V3Z" fill="#27ABA3"/>
<path d="M22.9165 0L29.9998 7.08333H25.9165C24.2597 7.08333 22.9165 5.74019 22.9165 4.08333V0Z" fill="#008078"/>
<rect x="6.5" y="15.5" width="17" height="5" stroke="white"/>
<rect x="6.5" y="23.5" width="17" height="5" stroke="white"/>
</svg>

Before

Width:  |  Height:  |  Size: 463 B

After

Width:  |  Height:  |  Size: 477 B

View File

@ -1 +1,8 @@
<svg width="30" height="40" viewBox="0 0 30 40" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M0 3c0-1.65685 1.34315-3 3-3h20l7 7v30c0 1.6569-1.3431 3-3 3H3c-1.65685 0-3-1.3431-3-3V3z" fill="#F36700"/><path d="M23 0l7 7h-4c-1.6569 0-3-1.34315-3-3V0z" fill="#000" fill-opacity=".25"/><path stroke="#fff" stroke-opacity=".95" d="M6.5 15.5h17v12h-17z"/></svg>
<svg width="30" height="40" viewBox="0 0 30 40" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M0 3C0 1.34315 1.34315 0 3 0H22.9167L30 7.08333V37C30 38.6569 28.6569 40 27 40H3C1.34315 40 0 38.6569 0 37V3Z" fill="#F36700"/>
<path d="M22.9167 0L30.0001 7.08333H25.9168C24.2599 7.08333 22.9167 5.74019 22.9167 4.08333V0Z" fill="#AB531F"/>
<path d="M6.17627 16.1275H23.8233V17.3039H6.17627V16.1275Z" fill="white"/>
<path d="M6.17627 28.7745L6.17627 16.1275L7.35274 16.1275L7.35274 28.7745H6.17627Z" fill="white"/>
<path d="M23.8233 16.1275V28.7745H22.6469V16.1275L23.8233 16.1275Z" fill="white"/>
<path d="M6.17627 27.598H23.8233V28.7745H6.17627L6.17627 27.598Z" fill="white"/>
</svg>

Before

Width:  |  Height:  |  Size: 366 B

After

Width:  |  Height:  |  Size: 691 B

View File

@ -1 +1,6 @@
<svg width="30" height="40" viewBox="0 0 30 40" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M0 3c0-1.65685 1.34315-3 3-3h20l7 7v30c0 1.6569-1.3431 3-3 3H3c-1.65685 0-3-1.3431-3-3V3z" fill="#D0D5DA"/><path d="M23 0l7 7h-4c-1.6569 0-3-1.34315-3-3V0z" fill="#646464"/><path fill-rule="evenodd" clip-rule="evenodd" d="M7.5 23c-.27614 0-.5.2239-.5.5v4c0 .2761.22386.5.5.5h15c.2761 0 .5-.2239.5-.5v-4c0-.2761-.2239-.5-.5-.5h-2c-.2761 0-.5-.2239-.5-.5s.2239-.5.5-.5h2c.8284 0 1.5.6716 1.5 1.5v4c0 .8284-.6716 1.5-1.5 1.5h-15c-.82843 0-1.5-.6716-1.5-1.5v-4c0-.8284.67157-1.5 1.5-1.5h2c.27614 0 .5.2239.5.5s-.22386.5-.5.5h-2z" fill="#646464"/><path fill-rule="evenodd" clip-rule="evenodd" d="M20 20.0001L15 14l-5 6.0001h3v4c0 .5523.4477 1 1 1h2c.5523 0 1-.4477 1-1v-4h3z" fill="#646464"/></svg>
<svg width="30" height="40" viewBox="0 0 30 40" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M30 7.44186L22 0H3C1.22739 0 0 0.822551 0 2.32558V37.2093C0 38.7123 1.22739 40 3 40H27C28.7726 40 30 38.7123 30 37.2093V7.44186Z" fill="#D0D5DA"/>
<path d="M24.1042 7.27273H29.9631L22 0V5.32334C22 6.4105 22.949 7.27273 24.1042 7.27273Z" fill="#646464"/>
<path d="M16.9562 22.3485H12.9746V17.803H10.9839L14.9654 14.1667L18.947 17.803H16.9562V22.3485Z" fill="#646464"/>
<path d="M20.9378 23.7121C20.9378 24.1666 20.4401 24.6212 19.9424 24.6212H9.98848C9.49078 24.6212 8.99309 24.1666 8.99309 23.7121V22.3485C8.99309 21.8939 9.49078 21.4394 9.98848 21.4394H10.9839V20.0757H9.49078C8.49539 20.0757 7.5 20.9848 7.5 21.8939V24.1666C7.5 25.0757 8.61982 25.9848 9.49078 25.9848H20.4401C21.3111 25.9848 22.4309 25.0757 22.4309 24.1666V21.8939C22.4309 20.9848 21.4355 20.0757 20.4401 20.0757H18.947V21.4394H19.9424C20.4401 21.4394 20.9378 21.8939 20.9378 22.3485V23.7121Z" fill="#646464"/>
</svg>

Before

Width:  |  Height:  |  Size: 797 B

After

Width:  |  Height:  |  Size: 992 B

View File

@ -1 +1,12 @@
<svg width="30" height="40" viewBox="0 0 30 40" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M0 3c0-1.65685 1.34315-3 3-3h20l7 7v30c0 1.6569-1.3431 3-3 3H3c-1.65685 0-3-1.3431-3-3V3z" fill="#6AAA1E"/><path d="M23 0l7 7h-4c-1.6569 0-3-1.34315-3-3V0z" fill="#000" fill-opacity=".25"/><path fill-rule="evenodd" clip-rule="evenodd" d="M6 15h18v13H7.00001v-1H12v-3H7v4H6V15zm7 12h4v-3h-4v3zm5 0h5v-3h-5v3zm5-7v3h-5v-3h5zm-6 0v3h-4v-3h4zm-5 0v3H7v-3h5zm11-1v-3h-5v3h5zm-10-3h4v3h-4v-3zm-1 3v-3H7v3h5z" fill="#fff" fill-opacity=".95"/></svg>
<svg width="30" height="40" viewBox="0 0 30 40" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M0 3C0 1.34315 1.34315 0 3 0H22.9167L30 7.08333V37C30 38.6569 28.6569 40 27 40H3C1.34315 40 0 38.6569 0 37V3Z" fill="#78A73B"/>
<path d="M22.9167 0L30.0001 7.08333H25.9168C24.2599 7.08333 22.9167 5.74019 22.9167 4.08333V0Z" fill="#5A7D2B"/>
<path d="M6.17644 15.2941H23.8235V16.4706H6.17644V15.2941Z" fill="white"/>
<path d="M6.17644 19.1177H23.8235V20.2941H6.17644V19.1177Z" fill="white"/>
<path d="M6.17644 22.9412H23.8235V24.1177H6.17644V22.9412Z" fill="white"/>
<path d="M6.17644 26.7647H23.8235V27.9412H6.17644V26.7647Z" fill="white"/>
<path d="M5.88232 27.9412L5.88232 15.2941L7.0588 15.2941L7.0588 27.9412H5.88232Z" fill="white"/>
<path d="M11.4706 27.9412L11.4706 15.2941L12.647 15.2941V27.9412H11.4706Z" fill="white"/>
<path d="M17.0588 27.9412L17.0588 15.2941L18.2353 15.2941V27.9412H17.0588Z" fill="white"/>
<path d="M22.647 27.9412V15.2941H23.8235V27.9412H22.647Z" fill="white"/>
</svg>

Before

Width:  |  Height:  |  Size: 545 B

After

Width:  |  Height:  |  Size: 1004 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

View File

@ -1,6 +1,6 @@
/**
*
* (c) Copyright Ascensio System SIA 2024
* (c) Copyright Ascensio System SIA 2023
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -502,17 +502,6 @@
justify-content: space-between;
align-items: center;
}
.buttonsMobile.indent {
margin-bottom: 0;
flex-wrap: nowrap;
}
.button.file-type:hover,
.button.file-type {
height: 28px;
width: 100px;
margin-bottom: 10px !important;
font-size: 9px;
}
.button.gray{
margin: 0;
}

View File

@ -1,6 +1,6 @@
/**
*
* (c) Copyright Ascensio System SIA 2024
* (c) Copyright Ascensio System SIA 2023
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -230,33 +230,6 @@ label .checkbox {
color: #FF6F3D;
}
.button.file-type {
font-size: 11px;
color: #FFFFFF;
padding: 8px 8px;
margin-right: 10px;
}
.button.file-type.disable {
cursor: default;
}
.button.file-type.pale {
opacity: 30%;
}
.button.file-type.document {
background: #446995;
}
.button.file-type.spreadsheet {
background: #40865C;
}
.button.file-type.presentation {
background: #AA5252;
}
.upload-panel {
float: left;
padding: 24px 0;
@ -619,29 +592,6 @@ footer table tr td:first-child {
width: 4%;
}
.storedHeader {
display: flex;
width: 100%;
justify-content: space-between;
align-items: center;
}
.storedHeaderClearAll {
padding-right: 52px;
}
.clear-all {
display: inline-block;
width: 100px;
padding: 2px;
outline: 1px solid #E5E5E5;
text-align: center;
cursor:pointer;
text-transform: uppercase;
background-color: #F5F5F5;
color: #666666;
}
.select-user {
color: #444444;
font-family: Open Sans;
@ -791,16 +741,6 @@ html {
margin-left: 25px;
}
.buttonsMobile.indent{
padding-left: 35px;
margin-top: 10px;
margin-bottom: 10px;
}
.invisible {
display: none;
}
.tooltip {
background: #FFFFFF;
border-radius: 5px;

View File

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

View File

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

View File

@ -1,6 +1,6 @@
/**
*
* (c) Copyright Ascensio System SIA 2024
* (c) Copyright Ascensio System SIA 2023
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -31,12 +31,6 @@ namespace OnlineEditorsExampleMVC.Helpers
{
public class DocManagerHelper
{
//get server version
public static string GetVersion()
{
return WebConfigurationManager.AppSettings["version"];
}
// get max file size
public static long MaxFileSize
{
@ -57,24 +51,24 @@ namespace OnlineEditorsExampleMVC.Helpers
// get file extensions that can be viewed
public static List<string> ViewedExts
{
get { return FormatManager.ViewableExtensions(); }
get { return (WebConfigurationManager.AppSettings["files.docservice.viewed-docs"] ?? "").Split(new char[] { '|', ',' }, StringSplitOptions.RemoveEmptyEntries).ToList(); }
}
public static List<string> FillFormExts
{
get { return FormatManager.FillableExtensions(); }
get { return (WebConfigurationManager.AppSettings["files.docservice.fillform-docs"] ?? "").Split(new char[] { '|', ',' }, StringSplitOptions.RemoveEmptyEntries).ToList(); }
}
// get file extensions that can be edited
public static List<string> EditedExts
{
get { return FormatManager.EditableExtensions(); }
get { return (WebConfigurationManager.AppSettings["files.docservice.edited-docs"] ?? "").Split(new char[] { '|', ',' }, StringSplitOptions.RemoveEmptyEntries).ToList(); }
}
// get file extensions that can be converted
public static List<string> ConvertExts
{
get { return FormatManager.ConvertibleExtensions(); }
get { return (WebConfigurationManager.AppSettings["files.docservice.convert-docs"] ?? "").Split(new char[] { '|', ',' }, StringSplitOptions.RemoveEmptyEntries).ToList(); }
}
// get current user host address
@ -183,12 +177,7 @@ namespace OnlineEditorsExampleMVC.Helpers
// get a file name with an index if the file with such a name already exists
public static string GetCorrectName(string fileName, string userAddress = null)
{
int maxName;
int.TryParse(WebConfigurationManager.AppSettings["filename-max"], out maxName);
var baseName = Path.GetFileNameWithoutExtension(fileName);
if (baseName.Length > maxName){
baseName = baseName.Substring(0, maxName) + "[...]";
}
var ext = Path.GetExtension(fileName).ToLower();
var name = baseName + ext;
@ -226,7 +215,7 @@ namespace OnlineEditorsExampleMVC.Helpers
public static string CreateDemo(string fileExt, bool withContent)
{
var demoName = (withContent ? "sample." : "new.") + fileExt; // create sample or new template file with the necessary extension
var demoPath = "assets\\document-templates\\" + (withContent ? "sample\\" : "new\\"); // get the path to the sample document
var demoPath = "assets\\" + (withContent ? "sample\\" : "new\\"); // get the path to the sample document
var fileName = GetCorrectName(demoName); // get a file name with an index if the file with such a name already exists

View File

@ -1,6 +1,6 @@
/**
*
* (c) Copyright Ascensio System SIA 2024
* (c) Copyright Ascensio System SIA 2023
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -229,10 +229,6 @@ namespace OnlineEditorsExampleMVC.Helpers
switch (errorCode)
{
case -9:
// public const int c_nErrorConversionOutputFormatError = -9;
errorMessage = String.Format(errorMessageTemplate, "Error conversion output format");
break;
case -8:
// public const int c_nErrorFileVKey = -8;
errorMessage = String.Format(errorMessageTemplate, "Error document VKey");

View File

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

View File

@ -1,6 +1,6 @@
/**
*
* (c) Copyright Ascensio System SIA 2024
* (c) Copyright Ascensio System SIA 2023
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -256,22 +256,6 @@ namespace OnlineEditorsExampleMVC.Helpers
var action = jss.Deserialize<Dictionary<string, object>>(jss.Serialize(actions[0]));
var user = action["userid"].ToString(); // get the user id
DocManagerHelper.CreateMeta(fileName, user, "Filling Form", userAddress); // create meta data for the forcesaved file
string formsDataUrl = fileData["formsdataurl"].ToString();
if (!string.IsNullOrEmpty(formsDataUrl))
{
string formsName = DocManagerHelper.GetCorrectName(Path.GetFileNameWithoutExtension(fileName) + ".txt", userAddress);
string formsPath = DocManagerHelper.StoragePath(formsName, userAddress);
var bytesForms = DownloadFile(formsDataUrl);
SaveFile(bytesForms, formsPath);
}
else
{
throw new Exception("Document editing service did not return formsDataUrl");
}
}
} catch (Exception)
{

View File

@ -1,6 +1,6 @@
/**
*
* (c) Copyright Ascensio System SIA 2024
* (c) Copyright Ascensio System SIA 2023
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -31,9 +31,7 @@ namespace OnlineEditorsExampleMVC.Helpers
"Can perform all actions with comments",
"The file favorite state is undefined",
"Can create files from templates using data from the editor",
"Can see the information about all users",
"Has an avatar",
"Can submit forms"
"Can see the information about all users"
};
static List<string> descr_user_2 = new List<string>()
@ -43,9 +41,7 @@ namespace OnlineEditorsExampleMVC.Helpers
"Can view comments, edit his own comments and comments left by users with no group. Can remove his own comments only",
"This file is marked as favorite",
"Can create new files from the editor",
"Can see the information about users from Group2 and users who dont belong to any group",
"Has an avatar",
"Cant submit forms"
"Can see the information about users from Group2 and users who dont belong to any group"
};
static List<string> descr_user_3 = new List<string>()
@ -58,10 +54,7 @@ namespace OnlineEditorsExampleMVC.Helpers
"Cant download the file",
"Cant print the file",
"Can create new files from the editor",
"Can see the information about Group2 users",
"Cant submit forms",
"Can't close history",
"Can't restore the file version"
"Can see the information about Group2 users"
};
static List<string> descr_user_0 = new List<string>()
@ -78,7 +71,6 @@ namespace OnlineEditorsExampleMVC.Helpers
"Can't view chat",
"Can't protect file",
"View file without collaboration",
"Cant submit forms"
};
private static List<User> users = new List<User>() {
@ -93,9 +85,7 @@ namespace OnlineEditorsExampleMVC.Helpers
null,
new List<string>(),
descr_user_1,
true,
true,
new Goback(null, false)
true
),
new User(
"uid-2",
@ -113,14 +103,12 @@ namespace OnlineEditorsExampleMVC.Helpers
true,
new List<string>(),
descr_user_2,
false,
true,
new Goback("Go to Documents", null)
false
),
new User(
"uid-3",
"Hamish Mitchell",
null,
"mitchell@example.com",
"group-3",
new List<string>() { "group-2" },
new Dictionary<string,object>()
@ -133,9 +121,7 @@ namespace OnlineEditorsExampleMVC.Helpers
false,
new List<string>() { "copy", "download", "print" },
descr_user_3,
false,
false,
null
false
),
new User(
"uid-0",
@ -148,9 +134,7 @@ namespace OnlineEditorsExampleMVC.Helpers
null,
new List<string>() { "protect" },
descr_user_0,
false,
false,
null
false
)
};
@ -187,43 +171,6 @@ namespace OnlineEditorsExampleMVC.Helpers
}
return usersData;
}
public static List<Dictionary<string, object>> getUsersInfo(string id)
{
List<Dictionary<string, object>> usersData = new List<Dictionary<string, object>>();
if (id != "uid-0") {
foreach (User user in users)
{
usersData.Add(new Dictionary<string, object>()
{
{"id", user.id},
{"name", user.name },
{"email", user.email },
{"image", user.avatar ? DocManagerHelper.GetServerUrl(false) + "/Content/images/" + user.id + ".png" : null}
});
}
}
return usersData;
}
// get a list of users with their names and emails for protect
public static List<Dictionary<string, object>> getUsersForProtect(string id)
{
List<Dictionary<string, object>> usersData = new List<Dictionary<string, object>>();
foreach (User user in users)
{
if (!user.id.Equals(id) && user.name != null)
{
usersData.Add(new Dictionary<string, object>()
{
{"name", user.name },
{"email", user.email },
{"id", user.id}
});
}
}
return usersData;
}
}
public class User
@ -239,11 +186,8 @@ namespace OnlineEditorsExampleMVC.Helpers
public List<string> descriptions;
public bool templates;
public List<string> userInfoGroups;
public bool avatar;
public Goback goback;
public User(string id, string name, string email, string group, List<string> reviewGroups, Dictionary<string, object> commentGroups, List<string> userInfoGroups, bool? favorite, List<string> deniedPermissions, List<string> descriptions, bool templates, bool avatar, Goback goback)
public User(string id, string name, string email, string group, List<string> reviewGroups, Dictionary<string, object> commentGroups, List<string> userInfoGroups, bool? favorite, List<string> deniedPermissions, List<string> descriptions, bool templates)
{
this.id = id;
this.name = name;
@ -256,22 +200,6 @@ namespace OnlineEditorsExampleMVC.Helpers
this.descriptions = descriptions;
this.templates = templates;
this.userInfoGroups = userInfoGroups;
this.avatar = avatar;
this.goback = goback;
}
}
public class Goback
{
public string text;
public bool? blank;
public Goback(){}
public Goback(string text, bool? blank)
{
this.text = text;
this.blank = blank;
}
}
}

View File

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

View File

@ -1,6 +1,6 @@
/**
*
* (c) Copyright Ascensio System SIA 2024
* (c) Copyright Ascensio System SIA 2023
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -17,6 +17,7 @@
*/
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Web;
@ -88,7 +89,7 @@ namespace OnlineEditorsExampleMVC.Models
editorsMode = "fillForms";
canEdit = true;
}
var submitForm = editorsMode.Equals("fillForms") && id.Equals("uid-1"); // check if the Submit form button is displayed or not
var submitForm = editorsMode.Equals("fillForms") && id.Equals("uid-1") && false; // check if the Submit form button is displayed or not
var mode = canEdit && editorsMode != "view" ? "edit" : "view"; // set the mode parameter: change it to view if the document can't be edited
// favorite icon state
@ -157,7 +158,7 @@ namespace OnlineEditorsExampleMVC.Models
{ "download", !user.deniedPermissions.Contains("download") },
{ "edit", canEdit && (editorsMode == "edit" || editorsMode == "view" || editorsMode == "filter" || editorsMode == "blockcontent") },
{ "print", !user.deniedPermissions.Contains("print") },
{ "fillForms", editorsMode != "view" && editorsMode != "comment" && editorsMode != "blockcontent" },
{ "fillForms", editorsMode != "view" && editorsMode != "comment" && editorsMode != "embedded" && editorsMode != "blockcontent" },
{ "modifyFilter", editorsMode != "filter" },
{ "modifyContentControl", editorsMode != "blockcontent" },
{ "review", canEdit && (editorsMode == "edit" || editorsMode == "review") },
@ -190,8 +191,7 @@ namespace OnlineEditorsExampleMVC.Models
{
{ "id", !user.id.Equals("uid-0") ? user.id : null },
{ "name", user.name },
{ "group", user.group },
{ "image", user.avatar ? DocManagerHelper.GetServerUrl(false) + "/Content/images/" + user.id + ".png" : null}
{ "group", user.group }
}
},
{
@ -214,12 +214,10 @@ namespace OnlineEditorsExampleMVC.Models
{ "forcesave", false }, // adds the request for the forced file saving to the callback handler
{ "submitForm", submitForm }, // if the Submit form button is displayed or not
{
"goback", user.goback != null ? new Dictionary<string, object> // settings for the Open file location menu button and upper right corner button
"goback", new Dictionary<string, object> // settings for the Open file location menu button and upper right corner button
{
{ "url", DocManagerHelper.GetServerUrl(false) }, // the absolute URL to the website address which will be opened when clicking the Open file location menu button
{ "text", user.goback.text },
{ "blank", user.goback.blank }
} : new Dictionary<string, object>{}
{ "url", DocManagerHelper.GetServerUrl(false) } // the absolute URL to the website address which will be opened when clicking the Open file location menu button
}
}
}
}
@ -238,8 +236,125 @@ namespace OnlineEditorsExampleMVC.Models
return jss.Serialize(config);
}
// get the document history
public void GetHistory(out string history, out string historyData)
{
var storagePath = WebConfigurationManager.AppSettings["storage-path"];
var jss = new JavaScriptSerializer();
var histDir = DocManagerHelper.HistoryDir(DocManagerHelper.StoragePath(FileName, null));
history = null;
historyData = null;
if (DocManagerHelper.GetFileVersion(histDir) > 0) // if the file was modified (the file version is greater than 0)
{
var currentVersion = DocManagerHelper.GetFileVersion(histDir);
var hist = new List<Dictionary<string, object>>();
var histData = new Dictionary<string, object>();
for (var i = 1; i <= currentVersion; i++) // run through all the file versions
{
var obj = new Dictionary<string, object>();
var dataObj = new Dictionary<string, object>();
var verDir = DocManagerHelper.VersionDir(histDir, i); // get the path to the given file version
var key = i == currentVersion ? Key : File.ReadAllText(Path.Combine(verDir, "key.txt")); // get document key
obj.Add("key", key);
obj.Add("version", i);
if (i == 1) // check if the version number is equal to 1
{
var infoPath = Path.Combine(histDir, "createdInfo.json"); // get meta data of this file
if (File.Exists(infoPath))
{
var info = jss.Deserialize<Dictionary<string, object>>(File.ReadAllText(infoPath));
obj.Add("created", info["created"]); // write meta information to the object (user information and creation date)
obj.Add("user", new Dictionary<string, object>() {
{ "id", info["id"] },
{ "name", info["name"] },
});
}
}
var ext = Path.GetExtension(FileName).ToLower();
dataObj.Add("fileType", ext.Replace(".", ""));
dataObj.Add("key", key);
// write file url to the data object
string prevFileUrl;
string directPrevFileUrl;
if (Path.IsPathRooted(storagePath) && !string.IsNullOrEmpty(storagePath))
{
prevFileUrl = i == currentVersion ? DocManagerHelper.GetHistoryDownloadUrl(FileName, i.ToString(), "prev" + ext)
: DocManagerHelper.GetDownloadUrl(Directory.GetFiles(verDir, "prev.*")[0].Replace(storagePath + "\\", ""));
directPrevFileUrl = i == currentVersion ? DocManagerHelper.GetHistoryDownloadUrl(FileName, i.ToString(), "prev" + ext, false)
: DocManagerHelper.GetDownloadUrl(Directory.GetFiles(verDir, "prev.*")[0].Replace(storagePath + "\\", ""), false);
}
else {
prevFileUrl = i == currentVersion ? FileUri
: DocManagerHelper.GetHistoryDownloadUrl(FileName, i.ToString(), "prev" + ext);
directPrevFileUrl = i == currentVersion ? DocManagerHelper.GetHistoryDownloadUrl(FileName, i.ToString(), "prev" + ext, false)
: DocManagerHelper.GetDownloadUrl(Directory.GetFiles(verDir, "prev.*")[0].Replace(storagePath + "\\", ""), false);
}
dataObj.Add("url", prevFileUrl);
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)
{
// get the path to the changes.json file
var changes = jss.Deserialize<Dictionary<string, object>>(File.ReadAllText(Path.Combine(DocManagerHelper.VersionDir(histDir, i - 1), "changes.json")));
var changesArray = (ArrayList)changes["changes"];
var change = changesArray.Count > 0
? (Dictionary<string, object>)changesArray[0]
: new Dictionary<string, object>();
// write information about changes to the object
obj.Add("changes", change.Count > 0 ? changes["changes"] : null);
obj.Add("serverVersion", changes["serverVersion"]);
obj.Add("created", change.Count > 0 ? change["created"] : null);
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", 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");
dataObj.Add("changesUrl", changesUrl);
}
if(JwtManager.Enabled)
{
var token = JwtManager.Encode(dataObj);
dataObj.Add("token", token);
}
hist.Add(obj); // add object dictionary to the hist list
histData.Add((i - 1).ToString(), dataObj); // write data object information to the history data
}
// write history information about the current file version to the history object
history = jss.Serialize(new Dictionary<string, object>()
{
{ "currentVersion", currentVersion },
{ "history", hist }
});
historyData = jss.Serialize(histData);
}
}
// get a document which will be compared with the current document
public void GetDocumentData(out string compareConfig)
public void GetCompareFileData(out string compareConfig)
{
var jss = new JavaScriptSerializer();
@ -291,20 +406,20 @@ namespace OnlineEditorsExampleMVC.Models
{
Path = HttpRuntime.AppDomainAppVirtualPath
+ (HttpRuntime.AppDomainAppVirtualPath.EndsWith("/") ? "" : "/")
+ "Content\\images\\logo.svg"
+ "Content\\images\\logo.png"
};
var directMailMergeUrl = new UriBuilder(DocManagerHelper.GetServerUrl(false))
{
Path = HttpRuntime.AppDomainAppVirtualPath
+ (HttpRuntime.AppDomainAppVirtualPath.EndsWith("/") ? "" : "/")
+ "Content\\images\\logo.svg"
+ "Content\\images\\logo.png"
};
// create a logo config
var logoConfig = new Dictionary<string, object>
{
{ "fileType", "svg"},
{ "fileType", "png"},
{ "url", mailMergeUrl.ToString()}
};
@ -323,7 +438,7 @@ namespace OnlineEditorsExampleMVC.Models
}
// get a mail merge config
public void GetSpreadsheetConfig(out string dataSpreadsheet)
public void GetMailMergeConfig(out string dataMailMergeRecipients)
{
var jss = new JavaScriptSerializer();
@ -364,7 +479,7 @@ namespace OnlineEditorsExampleMVC.Models
mailMergeConfig.Add("token", mailmergeToken); // and add it to the mail merge config
}
dataSpreadsheet = jss.Serialize(mailMergeConfig);
dataMailMergeRecipients = jss.Serialize(mailMergeConfig);
}
//get a users for mentions
@ -375,22 +490,5 @@ namespace OnlineEditorsExampleMVC.Models
var user = Users.getUser(id);
usersForMentions = !user.id.Equals("uid-0") ? jss.Serialize(Users.getUsersForMentions(user.id)) : null;
}
public void GetUsersInfo(HttpRequest request, out string usersInfo)
{
var jss = new JavaScriptSerializer();
var id = request.Cookies.GetOrDefault("uid", null);
var user = Users.getUser(id);
usersInfo = jss.Serialize(Users.getUsersInfo(user.id));
}
//get a users for protect
public void GetUsersProtect(HttpRequest request, out string usersForProtect)
{
var jss = new JavaScriptSerializer();
var id = request.Cookies.GetOrDefault("uid", null);
var user = Users.getUser(id);
usersForProtect = !user.id.Equals("uid-0") ? jss.Serialize(Users.getUsersForProtect(user.id)) : null;
}
}
}

View File

@ -1,6 +1,6 @@
/**
*
* (c) Copyright Ascensio System SIA 2024
* (c) Copyright Ascensio System SIA 2023
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -16,14 +16,8 @@
*
*/
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.IO;
using static OnlineEditorsExampleMVC.Models.FileUtility;
using System.Linq;
using System.Text;
using Newtonsoft.Json.Converters;
namespace OnlineEditorsExampleMVC.Models
{
@ -41,188 +35,38 @@ namespace OnlineEditorsExampleMVC.Models
{
var ext = Path.GetExtension(fileName).ToLower();
if (FormatManager.DocumentExtensions().Contains(ext)) return FileType.Word; // word type for document extensions
if (FormatManager.SpreadsheetExtensions().Contains(ext)) return FileType.Cell; // cell type for spreadsheet extensions
if (FormatManager.PresentationExtensions().Contains(ext)) return FileType.Slide; // slide type for presentation extensions
if (ExtsDocument.Contains(ext)) return FileType.Word; // word type for document extensions
if (ExtsSpreadsheet.Contains(ext)) return FileType.Cell; // cell type for spreadsheet extensions
if (ExtsPresentation.Contains(ext)) return FileType.Slide; // slide type for presentation extensions
return FileType.Word; // the default type is word
}
}
public class EmptyTolerantStringEnumConverter : StringEnumConverter
{
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
if (reader.TokenType == JsonToken.String && string.IsNullOrWhiteSpace(reader.Value.ToString()))
return Activator.CreateInstance(objectType);
return base.ReadJson(reader, objectType, existingValue, serializer);
}
}
public class Format
{
public string Name { get; }
[JsonConverter(typeof(EmptyTolerantStringEnumConverter))]
public FileType Type { get; }
public List<string> Actions { get; }
public List<string> Convert { get; }
public List<string> Mime { get; }
public Format(string name, FileType type, List<string> actions, List<string> convert, List<string> mime)
{
Name = name;
Type = type;
Actions = actions;
Convert = convert;
Mime = mime;
}
public string Extension()
{
return "." + Name;
}
}
public static class FormatManager
{
private static List<Format> cachedFormats;
public static List<string> FillableExtensions()
{
return Fillable()
.Select(format => format.Extension())
.ToList();
}
public static List<Format> Fillable()
{
return All()
.Where(format => format.Actions.Contains("fill"))
.ToList();
}
public static List<string> ViewableExtensions()
{
return Viewable()
.Select(format => format.Extension())
.ToList();
}
public static List<Format> Viewable()
{
return All()
.Where(format => format.Actions.Contains("view"))
.ToList();
}
public static List<string> EditableExtensions()
{
return Editable()
.Select(format => format.Extension())
.ToList();
}
public static List<Format> Editable()
{
return All()
.Where(format => format.Actions.Contains("edit") || format.Actions.Contains("lossy-edit"))
.ToList();
}
public static List<string> ConvertibleExtensions()
{
return Convertible()
.Select(format => format.Extension())
.ToList();
}
public static List<Format> Convertible()
{
return All()
.Where(format => format.Actions.Contains("auto-convert"))
.ToList();
}
public static List<string> SpreadsheetExtensions()
{
return Spreadsheets()
.Select(format => format.Extension())
.ToList();
}
public static List<Format> Spreadsheets()
{
return All()
.Where(format => format.Type == FileType.Cell)
.ToList();
}
public static List<string> PresentationExtensions()
{
return Presentations()
.Select(format => format.Extension())
.ToList();
}
public static List<Format> Presentations()
{
return All()
.Where(format => format.Type == FileType.Slide)
.ToList();
}
public static List<string> DocumentExtensions()
{
return Documents()
.Select(format => format.Extension())
.ToList();
}
public static List<Format> Documents()
{
return All()
.Where(format => format.Type == FileType.Word)
.ToList();
}
public static List<string> AllExtensions()
{
return All()
.Select(format => format.Extension())
.ToList();
}
public static List<Format> All()
{
if (cachedFormats == null)
// document extensions
public static readonly List<string> ExtsDocument = new List<string>
{
var path = GetPath();
var lines = File.ReadLines(path, Encoding.UTF8);
var contents = string.Join(Environment.NewLine, lines);
var formats = JsonConvert.DeserializeObject<Format[]>(contents);
cachedFormats = formats.ToList();
}
".doc", ".docx", ".docm",
".dot", ".dotx", ".dotm",
".odt", ".fodt", ".ott", ".rtf", ".txt",
".html", ".htm", ".mht", ".xml",
".pdf", ".djvu", ".fb2", ".epub", ".xps", ".oxps", ".oform"
};
return cachedFormats;
}
private static string GetPath()
{
string path = Path.Combine(GetDirectory(), "onlyoffice-docs-formats.json");
if (File.Exists(path))
// spreadsheet extensions
public static readonly List<string> ExtsSpreadsheet = new List<string>
{
return path;
}
else
{
throw new FileNotFoundException("The JSON file does not exist.");
}
}
".xls", ".xlsx", ".xlsm", ".xlsb",
".xlt", ".xltx", ".xltm",
".ods", ".fods", ".ots", ".csv"
};
private static string GetDirectory()
{
string directory = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "assets", "document-formats");
return Path.GetFullPath(directory);
}
// presentation extensions
public static readonly List<string> ExtsPresentation = new List<string>
{
".pps", ".ppsx", ".ppsm",
".ppt", ".pptx", ".pptm",
".pot", ".potx", ".potm",
".odp", ".fodp", ".otp"
};
}
}

View File

@ -145,6 +145,7 @@
<Content Include="Content\images\icon_xlsx.svg" />
<Content Include="Content\images\info.svg" />
<Content Include="Content\images\loader16.gif" />
<Content Include="Content\images\logo.png" />
<Content Include="Content\images\logo.svg" />
<Content Include="Content\images\mobile-fill-forms.svg" />
<Content Include="Content\images\mobile.svg" />
@ -158,6 +159,7 @@
<Content Include="favicon.ico" />
<Content Include="Global.asax" />
<Content Include="LICENSE" />
<Content Include="Scripts\jquery-1.8.2.js" />
<Content Include="Scripts\jquery-ui.js" />
<Content Include="Scripts\jquery.blockUI.js" />
<Content Include="Scripts\jquery.dropdownToggle.js" />
@ -180,23 +182,17 @@
<Content Include="WebEditor.ashx" />
</ItemGroup>
<ItemGroup>
<Content Include="assets\document-templates\AUTHORS.md" />
<Content Include="assets\document-templates\LICENSE" />
<Content Include="assets\document-templates\new\new.docx" />
<Content Include="assets\document-templates\new\new.docxf" />
<Content Include="assets\document-templates\new\new.pptx" />
<Content Include="assets\document-templates\new\new.xlsx" />
<Content Include="assets\document-templates\README.md" />
<Content Include="assets\document-templates\sample\csv.csv" />
<Content Include="assets\document-templates\sample\sample.docx" />
<Content Include="assets\document-templates\sample\sample.docxf" />
<Content Include="assets\document-templates\sample\sample.pptx" />
<Content Include="assets\document-templates\sample\sample.xlsx" />
<Content Include="assets\document-formats\AUTHORS.md" />
<Content Include="assets\document-formats\CHANGELOG.md" />
<Content Include="assets\document-formats\LICENSE" />
<Content Include="assets\document-formats\onlyoffice-docs-formats.json" />
<Content Include="assets\document-formats\README.md" />
<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" />
</ItemGroup>
<PropertyGroup>

View File

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

View File

@ -14,7 +14,7 @@ See the detailed guide to learn how to install Document Server [for Windows](htt
Download the [.Net (C# MVC) example](https://api.onlyoffice.com/editors/demopreview) from our site.
To connect the editors to your website, specify the path to the editors installation and the path to the storage folder in the *web.appsettings.config* file:
To connect the editors to your website, specify the path to the editors installation and the path to the storage folder in the *settings.config* file:
```
<add key="storage-path" value=""/>
<add key="files.docservice.url.site" value="https://documentserver/" />

View File

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

View File

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

View File

@ -1,6 +1,6 @@
/**
*
* (c) Copyright Ascensio System SIA 2024
* (c) Copyright Ascensio System SIA 2023
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -17,27 +17,6 @@
*/
var directUrl;
var formatManager;
window.onload = function () {
fetch("webeditor.ashx?type=formats")
.then((response) => response.json())
.then((data) => {
if (data.formats) {
let formats = [];
data.formats.forEach(format => {
formats.push(new Format(
format.Name,
format.Type,
format.Actions,
format.Convert,
format.Mime
));
});
formatManager = new FormatManager(formats);
}
})
}
if (typeof jQuery != "undefined") {
jq = jQuery.noConflict();
@ -108,7 +87,7 @@ if (typeof jQuery != "undefined") {
});
var timer = null;
var checkConvert = function (filePass, fileType) {
var checkConvert = function (filePass) {
filePass = filePass ? filePass : null;
if (timer != null) {
clearTimeout(timer);
@ -124,7 +103,7 @@ if (typeof jQuery != "undefined") {
var posExt = fileName.lastIndexOf('.');
posExt = 0 <= posExt ? fileName.substring(posExt).trim().toLowerCase() : '';
if (!formatManager.isAutoConvertible(posExt)) {
if (ConverExtList.indexOf(posExt) == -1) {
jq("#step2").addClass("done").removeClass("current");
loadScripts();
return;
@ -137,7 +116,7 @@ if (typeof jQuery != "undefined") {
contentType: "text/xml",
type: "post",
dataType: "json",
data: JSON.stringify({ filename: fileName, filePass: filePass, fileExt: fileType }),
data: JSON.stringify({ filename: fileName, filePass: filePass }),
url: UrlConverter,
complete: function (data) {
var responseText = data.responseText;
@ -153,12 +132,6 @@ if (typeof jQuery != "undefined") {
}
return;
} else {
if (response.error.includes("Error conversion output format")) {
jq("#select-file-type").removeClass("invisible");
jq("#step2").removeClass("current");
jq("#hiddenFileName").attr("placeholder", filePass);
return;
}
jq(".current").removeClass("current");
jq(".step:not(.done)").addClass("error");
jq("#mainProgress .error-message").show().find("span").text(response.error);
@ -170,7 +143,7 @@ if (typeof jQuery != "undefined") {
jq("#hiddenFileName").val(response.filename);
if (response.step && response.step < 100) {
checkConvert(filePass, fileType);
checkConvert(filePass);
} else {
jq("#step2").addClass("done").removeClass("current");
loadScripts();
@ -205,10 +178,10 @@ if (typeof jQuery != "undefined") {
jq("#beginView, #beginEmbedded").removeClass("disable");
var fileName = jq("#hiddenFileName").val();
var posExt = fileName.lastIndexOf('.') + 1;
var posExt = fileName.lastIndexOf('.');
posExt = 0 <= posExt ? fileName.substring(posExt).trim().toLowerCase() : '';
if (formatManager.isEditable(posExt) || formatManager.isFillable(posExt)) {
if (EditedExtList.indexOf(posExt) != -1 || FillExtList.indexOf(posExt) != -1) {
jq("#beginEdit").removeClass("disable");
}
};
@ -240,15 +213,6 @@ if (typeof jQuery != "undefined") {
});
};
jq(document).on("click", ".file-type:not(.disable)", function () {
const currentElement = jq(this);
var fileType = currentElement.attr("data");
var filePass = jq("#hiddenFileName").attr("placeholder");
jq('.file-type').addClass(["disable", "pale"]);
currentElement.removeClass("pale");
checkConvert(filePass, fileType);
});
jq(document).on("click", "#enterPass", function () {
var filePass = jq("#filePass").val();
if (filePass) {
@ -330,23 +294,6 @@ if (typeof jQuery != "undefined") {
});
});
jq(document).on("click", ".clear-all", function () {
if (confirm("Delete all the files?")) {
var requestAddress = "webeditor.ashx"
+ "?type=remove";
jq.ajax({
async: true,
contentType: "text/xml",
url: requestAddress,
complete: function (data) {
if (JSON.parse(data.responseText).success) {
window.location.reload(true);
}
}
});
}
});
function showUserTooltip (isMobile) {
if ( jq("div#portal-info").is(":hidden") ) {
jq("div#portal-info").show();

View File

@ -14,7 +14,7 @@
<meta name="mobile-web-app-capable" content="yes" />
<!--
*
* (c) Copyright Ascensio System SIA 2024
* (c) Copyright Ascensio System SIA 2023
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -129,21 +129,17 @@
};
// the user is trying to select document for comparing by clicking the Document from Storage button
var onRequestSelectDocument = function (event) {
<% string documentData; %>
<% Model.GetDocumentData(out documentData); %>
var data = <%=documentData%>;
data.c = event.data.c;
docEditor.setRequestedDocument(data); // select a document for comparing
var onRequestCompareFile = function () {
<% string compareFileData; %>
<% Model.GetCompareFileData(out compareFileData); %>
docEditor.setRevisedFile(<%=compareFileData%>); // select a document for comparing
};
// the user is trying to select recipients data by clicking the Mail merge button
var onRequestSelectSpreadsheet = function (event) {
<% string dataSpreadsheet; %>
<% Model.GetSpreadsheetConfig(out dataSpreadsheet); %>
var data = <%= dataSpreadsheet%>;
data.c = event.data.c;
docEditor.setRequestedSpreadsheet(data); // insert recipient data for mail merge into the file
var onRequestMailMergeRecipients = function (event) {
<% string dataMailMergeRecipients; %>
<% Model.GetMailMergeConfig(out dataMailMergeRecipients); %>
docEditor.setMailMergeRecipients(<%= dataMailMergeRecipients%>); // insert recipient data for mail merge into the file
};
var onRequestSaveAs = function (event) { // the user is trying to save file by clicking Save Copy as... button
@ -182,125 +178,18 @@
}
};
var onRequestOpen = function (event) { // user open external data source
innerAlert("onRequestOpen");
var windowName = event.data.windowName;
requestReference(event.data, function (data) {
if (data.error) {
var winEditor = window.open("", windowName);
winEditor.close();
innerAlert(data.error, true);
return;
}
var link = data.link;
window.open(link, windowName);
});
};
var onRequestReferenceData = function (event) { // user refresh external data source
innerAlert("onRequestReferenceData");
requestReference(event.data, function (data) {
docEditor.setReferenceData(data);
});
};
var requestReference = function (data, callback) {
innerAlert(data);
data.directUrl = !!config.document.directUrl;
event.data.directUrl = !!config.document.directUrl;
let xhr = new XMLHttpRequest();
xhr.open("POST", "webeditor.ashx?type=reference");
xhr.setRequestHeader("Content-Type", "application/json");
xhr.send(JSON.stringify(data));
xhr.send(JSON.stringify(event.data));
xhr.onload = function () {
console.log(xhr.responseText);
callback(JSON.parse(xhr.responseText));
docEditor.setReferenceData(JSON.parse(xhr.responseText));
}
};
var onRequestHistory = function () {
let xhr = new XMLHttpRequest();
xhr.open("GET", "webeditor.ashx?type=gethistory&filename=<%= Model.FileName %>");
xhr.setRequestHeader("Content-Type", "application/json");
xhr.send();
xhr.onload = function () {
console.log(xhr.responseText);
docEditor.refreshHistory(JSON.parse(xhr.responseText));
}
};
var onRequestHistoryData = function (event) {
var ver = event.data;
let xhr = new XMLHttpRequest();
xhr.open("GET", "webeditor.ashx?type=getversiondata&filename=<%= Model.FileName %>&version=" + ver + "&directUrl=" + !!config.document.directUrl);
xhr.setRequestHeader("Content-Type", "application/json");
xhr.send();
xhr.onload = function () {
console.log(xhr.responseText);
docEditor.setHistoryData(JSON.parse(xhr.responseText)); // send the link to the document for viewing the version history
}
};
var onRequestRestore = function (event) {
var fileName = "<%= Model.FileName %>";
var version = event.data.version;
var data = {
fileName: fileName,
version: version
};
let xhr = new XMLHttpRequest();
xhr.open("POST", "webeditor.ashx?type=restore&directUrl=" + !!config.document.directUrl);
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.send(JSON.stringify(data));
xhr.onload = function () {
docEditor.refreshHistory(JSON.parse(xhr.responseText));
}
}
<% string usersForMentions; %>
<% Model.GetUsersMentions(Request, out usersForMentions); %>
<% string usersInfo; %>
<% Model.GetUsersInfo(Request, out usersInfo); %>
<% string usersForProtect; %>
<% Model.GetUsersProtect(Request, out usersForProtect); %>
var onRequestUsers = function (event) {
if (event && event.data){
var c = event.data.c;
}
switch (c) {
case "info":
users = [];
var allUsers = <%= usersInfo %>;
for (var i = 0; i < event.data.id.length; i++) {
for (var j = 0; j < allUsers.length; j++) {
if (allUsers[j].id == event.data.id[i]) {
users.push(allUsers[j]);
break;
}
}
}
break;
case "protect":
var users = <%= usersForProtect %>;
break;
default:
users = <%= usersForMentions %>;
}
docEditor.setUsers({
"c": c,
"users": users,
});
};
var onRequestSendNotify = function (event) {
event.data.actionLink = replaceActionLink(location.href, JSON.stringify(event.data.actionLink));
var data = JSON.stringify(event.data);
innerAlert("onRequestSendNotify: " + data);
};
config = <%= Model.GetDocConfig(Request, Url) %>;
config.width = "100%";
@ -314,41 +203,69 @@
"onMakeActionLink": onMakeActionLink,
"onMetaChange": onMetaChange,
"onRequestInsertImage": onRequestInsertImage,
"onRequestSelectDocument": onRequestSelectDocument,
"onRequestSelectSpreadsheet": onRequestSelectSpreadsheet,
"onRequestCompareFile": onRequestCompareFile,
"onRequestMailMergeRecipients": onRequestMailMergeRecipients,
};
<% string hist, histData; %>
<% Model.GetHistory(out hist, out histData); %>
<% string usersForMentions; %>
<% Model.GetUsersMentions(Request, out usersForMentions); %>
if (config.editorConfig.user.id) {
// the user is trying to show the document version history
config.events['onRequestHistory'] = onRequestHistory;
// the user is trying to click the specific document version in the document version history
config.events['onRequestHistoryData'] = onRequestHistoryData;
// the user is trying to go back to the document from viewing the document version history
if (config.editorConfig.user.id !== "uid-3") {
<% if (!string.IsNullOrEmpty(hist) && !string.IsNullOrEmpty(histData))
{ %>
// the user is trying to show the document version history
config.events['onRequestHistory'] = function () {
docEditor.refreshHistory(<%= hist %>); // show the document version history
};
// the user is trying to click the specific document version in the document version history
config.events['onRequestHistoryData'] = function (event) {
var ver = event.data;
var histData = <%= histData %>;
docEditor.setHistoryData(histData[ver - 1]); // send the link to the document for viewing the version history
};
// the user is trying to go back to the document from viewing the document version history
config.events['onRequestHistoryClose'] = function () {
document.location.reload();
};
config.events['onRequestRestore'] = onRequestRestore;
}
<% } %>
// add mentions for not anonymous users
<% if (!string.IsNullOrEmpty(usersForMentions))
{ %>
config.events['onRequestUsers'] = onRequestUsers;
config.events['onRequestUsers'] = function () {
docEditor.setUsers({ // set a list of users to mention in the comments
"users": <%= usersForMentions %>
});
};
<% } %>
config.events['onRequestSaveAs'] = onRequestSaveAs;
// the user is mentioned in a comment
config.events['onRequestSendNotify'] = onRequestSendNotify;
config.events['onRequestSendNotify'] = function (event) {
event.data.actionLink = replaceActionLink(location.href, JSON.stringify(event.data.actionLink));
var data = JSON.stringify(event.data);
innerAlert("onRequestSendNotify: " + data);
};
// prevent file renaming for anonymous users
config.events['onRequestRename'] = onRequestRename;
config.events['onRequestReferenceData'] = onRequestReferenceData;
// prevent switch the document from the viewing into the editing mode for anonymous users
config.events['onRequestEditRights'] = onRequestEditRights;
config.events['onRequestOpen'] = onRequestOpen;
}
if (config.editorConfig.createUrl) {
config.events.onRequestSaveAs = onRequestSaveAs;
};
var сonnectEditor = function () {
if ((config.document.fileType === "docxf" || config.document.fileType === "oform")
&& DocsAPI.DocEditor.version().split(".")[0] < 7) {
innerAlert("Please update ONLYOFFICE Docs to version 7.0 to work on fillable forms online.");
return;
}
docEditor = new DocsAPI.DocEditor("iframeEditor", config);
};

View File

@ -13,10 +13,9 @@
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width" />
<meta name="server-version" content=<%= DocManagerHelper.GetVersion() %> />
<!--
*
* (c) Copyright Ascensio System SIA 2024
* (c) Copyright Ascensio System SIA 2023
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -68,7 +67,7 @@
<a class="try-editor slide" data-type="pptx">Presentation</a>
</li>
<li>
<a class="try-editor form" data-type="docxf">PDF form</a>
<a class="try-editor form" data-type="docxf">Form template</a>
</li>
</ul>
<label class="side-option">
@ -151,14 +150,7 @@
if (storedFiles.Any())
{ %>
<div class="stored-list">
<div class="storedHeader">
<div class="storedHeaderText">
<span class="header-list">Your documents</span>
</div>
<div class="storedHeaderClearAll">
<div class="clear-all">Clear all</div>
</div>
</div>
<span class="header-list">Your documents</span>
<table class="tableHeader" cellspacing="0" cellpadding="0" width="100%">
<thead>
<tr>
@ -302,15 +294,6 @@
<div class="describeUpload">After these steps are completed, you can work with your document.</div>
<span id="step1" class="step">1. Loading the file.</span>
<span class="step-descr">The loading speed depends on file size and additional elements it contains.</span>
<div id="select-file-type" class="invisible">
<br />
<span class="step">Please select the current document type</span>
<div class="buttonsMobile indent">
<div class="button file-type document" data="docx">Document</div>
<div class="button file-type spreadsheet" data="xlsx">Spreadsheet</div>
<div class="button file-type presentation" data="pptx">Presentation</div>
</div>
</div>
<br />
<span id="step2" class="step">2. Conversion.</span>
<span class="step-descr">The file is converted to OOXML so that you can edit it.</span>
@ -373,6 +356,9 @@
<%: Scripts.Render("~/bundles/jquery", "~/bundles/scripts") %>
<script language="javascript" type="text/javascript">
var FillExtList = '<%= string.Join(",", DocManagerHelper.FillFormExts.ToArray()) %>';
var ConverExtList = '<%= string.Join(",", DocManagerHelper.ConvertExts.ToArray()) %>';
var EditedExtList = '<%= string.Join(",", DocManagerHelper.EditedExts.ToArray()) %>';
var UrlConverter = '<%= Url.Content("~/webeditor.ashx?type=convert") %>';
var UrlEditor = '<%= Url.Action("editor", "Home") %>';
</script>

View File

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

View File

@ -1,6 +1,6 @@
/**
*
* (c) Copyright Ascensio System SIA 2024
* (c) Copyright Ascensio System SIA 2023
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -17,7 +17,6 @@
*/
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Text;
@ -51,15 +50,6 @@ namespace OnlineEditorsExampleMVC
case "downloadhistory":
DownloadHistory(context);
break;
case "gethistory":
GetHistory(context);
break;
case "getversiondata":
GetVersionData(context);
break;
case "restore":
Restore(context);
break;
case "convert":
Convert(context);
break;
@ -87,9 +77,6 @@ namespace OnlineEditorsExampleMVC
case "reference":
Reference(context);
break;
case "formats":
Formats(context);
break;
}
}
@ -243,13 +230,7 @@ namespace OnlineEditorsExampleMVC
var fileUri = DocManagerHelper.GetDownloadUrl(fileName);
var extension = (Path.GetExtension(fileName).ToLower() ?? "").Trim('.');
string conversionExtension = "ooxml";
object fileExt;
if (body.TryGetValue("fileExt", out fileExt) && !String.IsNullOrEmpty(fileExt.ToString()))
{
conversionExtension = fileExt.ToString();
}
var internalExtension = "ooxml";
// check if the file with such an extension can be converted
if (DocManagerHelper.ConvertExts.Contains("." + extension))
@ -267,7 +248,7 @@ namespace OnlineEditorsExampleMVC
// get the url and file type of the converted file
Dictionary<string, string> newFileData;
var result = ServiceConverter.GetConvertedData(downloadUri.ToString(), extension, conversionExtension, key, true, out newFileData, filePass, lang);
var result = ServiceConverter.GetConvertedData(downloadUri.ToString(), extension, internalExtension, key, true, out newFileData, filePass, lang);
if (result != 100)
{
context.Response.Write("{ \"step\" : \"" + result + "\", \"filename\" : \"" + fileName + "\"}");
@ -402,17 +383,8 @@ namespace OnlineEditorsExampleMVC
context.Response.ContentType = "text/plain";
try
{
string fileName = context.Request["fileName"];
if (!String.IsNullOrEmpty(fileName))
{
fileName = Path.GetFileName(context.Request["fileName"]);
Remove(fileName); // remove a file and its history if it exists
}
else
{
RemoveUserDirectory(); // remove the user's directory
}
var fileName = Path.GetFileName(context.Request["fileName"]);
Remove(fileName); // remove a file and its history if it exists
context.Response.Write("{ \"success\": true }");
}
@ -432,14 +404,6 @@ namespace OnlineEditorsExampleMVC
if (Directory.Exists(histDir)) Directory.Delete(histDir, true);
}
// remove the user's directory
private static void RemoveUserDirectory()
{
var path = DocManagerHelper.StoragePath("", null); // get the path to the user directory
if (Directory.Exists(path)) Directory.Delete(path, true);
}
// get files information
private static void Files(HttpContext context)
{
@ -479,7 +443,7 @@ namespace OnlineEditorsExampleMVC
private static void Assets(HttpContext context)
{
var fileName = Path.GetFileName(context.Request["filename"]);
var filePath = HttpRuntime.AppDomainAppPath + "assets/document-templates/sample/" + fileName;
var filePath = HttpRuntime.AppDomainAppPath + "assets/sample/" + fileName;
download(filePath, context);
}
@ -487,7 +451,7 @@ namespace OnlineEditorsExampleMVC
private static void GetCsv(HttpContext context)
{
var fileName = "csv.csv";
var filePath = HttpRuntime.AppDomainAppPath + "assets/document-templates/sample/" + fileName;
var filePath = HttpRuntime.AppDomainAppPath + "assets/sample/" + fileName;
download(filePath, context);
}
@ -549,173 +513,6 @@ namespace OnlineEditorsExampleMVC
get { return false; }
}
private static void GetHistory(HttpContext context)
{
var jss = new JavaScriptSerializer();
var fileName = context.Request["filename"];
var history = GetHistory(fileName);
context.Response.Write(jss.Serialize(history));
}
private static void GetVersionData(HttpContext context)
{
var storagePath = WebConfigurationManager.AppSettings["storage-path"];
var jss = new JavaScriptSerializer();
var fileName = context.Request["filename"];
int version;
if (!int.TryParse(context.Request["version"], out version))
{
context.Response.Write("{ \"error\": \"Version number invalid!\"}");
return;
}
var versionData = new Dictionary<string, object>();
var histDir = DocManagerHelper.HistoryDir(DocManagerHelper.StoragePath(fileName, null));
var lastVersion = DocManagerHelper.GetFileVersion(histDir);
var verDir = DocManagerHelper.VersionDir(histDir, version);
var key = version == lastVersion
? ServiceConverter.GenerateRevisionId(DocManagerHelper.CurUserHostAddress()
+ "/" + fileName + "/"
+ File.GetLastWriteTime(DocManagerHelper.StoragePath(fileName, null)).GetHashCode())
: File.ReadAllText(Path.Combine(verDir, "key.txt"));
var ext = Path.GetExtension(fileName).ToLower();
versionData.Add("fileType", ext.Replace(".", ""));
versionData.Add("key", key);
// write file url to the data object
string prevFileUrl;
string directPrevFileUrl;
if (Path.IsPathRooted(storagePath) && !string.IsNullOrEmpty(storagePath))
{
prevFileUrl = version == lastVersion ? DocManagerHelper.GetDownloadUrl(fileName)
: DocManagerHelper.GetDownloadUrl(Directory.GetFiles(verDir, "prev.*")[0].Replace(storagePath + "\\", ""));
directPrevFileUrl = version == lastVersion ? DocManagerHelper.GetDownloadUrl(fileName, false)
: DocManagerHelper.GetDownloadUrl(Directory.GetFiles(verDir, "prev.*")[0].Replace(storagePath + "\\", ""), false);
}
else
{
prevFileUrl = version == lastVersion ? DocManagerHelper.GetFileUri(fileName, true)
: DocManagerHelper.GetHistoryDownloadUrl(fileName, version.ToString(), "prev" + ext);
directPrevFileUrl = version == lastVersion ? DocManagerHelper.GetFileUri(fileName, false)
: DocManagerHelper.GetHistoryDownloadUrl(fileName, version.ToString(), "prev" + ext, false);
}
versionData.Add("url", prevFileUrl);
var isEnableDirectUrl = string.Equals(DocManagerHelper.GetDirectUrl(), "true");
if (isEnableDirectUrl)
{
versionData.Add("directUrl", directPrevFileUrl); // write direct url to the data object
}
versionData.Add("version", version);
if (version > 1)
{
var prevVerDir = DocManagerHelper.VersionDir(histDir, version - 1);
var prevUrl = Path.IsPathRooted(storagePath) && !string.IsNullOrEmpty(storagePath)
? DocManagerHelper.GetDownloadUrl(Directory.GetFiles(prevVerDir, "prev.*")[0].Replace(storagePath + "\\", ""))
: DocManagerHelper.GetHistoryDownloadUrl(fileName, (version - 1).ToString(), "prev" + ext);
var prevKey = File.ReadAllText(Path.Combine(prevVerDir, "key.txt"));
Dictionary<string, object> dataPrev = new Dictionary<string, object>() { // write information about previous file version to the data object
{ "fileType", ext.Replace(".", "") },
{ "key", prevKey }, // write key and url information about previous file version
{ "url", prevUrl }
};
string directPrevUrl;
if (isEnableDirectUrl)
{
directPrevUrl = Path.IsPathRooted(storagePath) && !string.IsNullOrEmpty(storagePath)
? DocManagerHelper.GetDownloadUrl(Directory.GetFiles(prevVerDir, "prev.*")[0].Replace(storagePath + "\\", ""), false)
: DocManagerHelper.GetHistoryDownloadUrl(fileName, version.ToString(), "prev" + ext, false);
dataPrev.Add("directUrl", directPrevUrl);
}
versionData.Add("previous", dataPrev);
if (File.Exists(Path.Combine(prevVerDir, "diff.zip")))
{
var changesUrl = DocManagerHelper.GetHistoryDownloadUrl(fileName, (version - 1).ToString(), "diff.zip");
versionData.Add("changesUrl", changesUrl);
}
}
if (JwtManager.Enabled)
{
var token = JwtManager.Encode(versionData);
versionData.Add("token", token);
}
context.Response.Write(jss.Serialize(versionData));
}
private static void Restore(HttpContext context)
{
string fileData;
try
{
using (var receiveStream = context.Request.InputStream)
using (var readStream = new StreamReader(receiveStream))
{
fileData = readStream.ReadToEnd();
if (string.IsNullOrEmpty(fileData)) return;
}
}
catch (Exception e)
{
throw new HttpException((int)HttpStatusCode.BadRequest, e.Message);
}
var jss = new JavaScriptSerializer();
var body = jss.Deserialize<Dictionary<string, object>>(fileData);
var fileName = (string)body["fileName"];
var version = (int)body["version"];
var key = ServiceConverter.GenerateRevisionId(DocManagerHelper.CurUserHostAddress()
+ "/" + fileName + "/"
+ File.GetLastWriteTime(DocManagerHelper.StoragePath(fileName, null)).GetHashCode());
var histDir = DocManagerHelper.HistoryDir(DocManagerHelper.StoragePath(fileName, null));
var currentVersionDir = DocManagerHelper.VersionDir(histDir, DocManagerHelper.GetFileVersion(histDir));
var verDir = DocManagerHelper.VersionDir(histDir, version);
if (!Directory.Exists(currentVersionDir)) Directory.CreateDirectory(currentVersionDir);
var ext = Path.GetExtension(fileName).ToLower();
File.Copy(DocManagerHelper.StoragePath(fileName, null), Path.Combine(currentVersionDir, "prev" + ext));
File.WriteAllText(Path.Combine(currentVersionDir, "key.txt"), key);
var changesPath = Path.Combine(DocManagerHelper.VersionDir(histDir, version - 1), "changes.json");
if (File.Exists(changesPath))
{
File.Copy(changesPath, Path.Combine(currentVersionDir, "changes.json"));
}
File.Copy(Path.Combine(verDir, "prev" + ext), DocManagerHelper.StoragePath(fileName, null), true);
var fileInfo = new FileInfo(DocManagerHelper.StoragePath(fileName, null));
fileInfo.LastWriteTimeUtc = DateTime.UtcNow;
var history = GetHistory(fileName);
context.Response.Write(jss.Serialize(history));
}
// download a history file
private static void DownloadHistory(HttpContext context)
{
@ -838,27 +635,6 @@ namespace OnlineEditorsExampleMVC
}
}
if (fileName == "" && body.ContainsKey("link"))
{
string link = body["link"].ToString();
if (!link.Contains(DocManagerHelper.GetServerUrl(false)))
{
context.Response.Write(jss.Serialize(new Dictionary<string, string>() {
{ "url", link },
{ "directUrl", link }
}));
return;
}
Uri linkUri = new Uri(link);
fileName = HttpUtility.ParseQueryString(linkUri.Query).Get("fileName");
if (string.IsNullOrEmpty(fileName) || !File.Exists(DocManagerHelper.StoragePath(fileName, null)))
{
context.Response.Write("{ \"error\": \"File is not exist\"}");
return;
}
}
if (fileName == "")
{
try
@ -887,7 +663,6 @@ namespace OnlineEditorsExampleMVC
var data = new Dictionary<string, object>() {
{ "fileType", (Path.GetExtension(fileName) ?? "").ToLower().Trim('.') },
{ "key", ServiceConverter.GenerateRevisionId(DocManagerHelper.CurUserHostAddress() + "/" + fileName + "/" + File.GetLastWriteTime(DocManagerHelper.StoragePath(fileName, null)).GetHashCode())},
{ "url", DocManagerHelper.GetDownloadUrl(fileName)},
{ "directUrl", directUrl ? DocManagerHelper.GetDownloadUrl(fileName, false) : null },
{ "referenceData", new Dictionary<string, string>()
@ -900,8 +675,7 @@ namespace OnlineEditorsExampleMVC
{ "instanceId", DocManagerHelper.GetServerUrl(false) }
}
},
{ "path", fileName },
{ "link", DocManagerHelper.GetServerUrl(false) + "Editor?fileName=" + fileName }
{ "path", fileName }
};
if (JwtManager.Enabled)
@ -913,89 +687,6 @@ namespace OnlineEditorsExampleMVC
context.Response.Write(jss.Serialize(data));
}
// get the document history
private static Dictionary<string, object> GetHistory(string fileName)
{
var jss = new JavaScriptSerializer();
var histDir = DocManagerHelper.HistoryDir(DocManagerHelper.StoragePath(fileName, null));
var history = new Dictionary<string, object>();
var currentVersion = DocManagerHelper.GetFileVersion(histDir);
var currentKey = ServiceConverter.GenerateRevisionId(DocManagerHelper.CurUserHostAddress()
+ "/" + fileName + "/"
+ File.GetLastWriteTime(DocManagerHelper.StoragePath(fileName, null)).GetHashCode());
var versionList = new List<Dictionary<string, object>>();
for (var versionNum = 1; versionNum <= currentVersion; versionNum++)
{
var versionObj = new Dictionary<string, object>();
var verDir = DocManagerHelper.VersionDir(histDir, versionNum); // get the path to the given file version
var key = versionNum == currentVersion ? currentKey : File.ReadAllText(Path.Combine(verDir, "key.txt")); // get document key
versionObj.Add("key", key);
versionObj.Add("version", versionNum);
var changesPath = Path.Combine(DocManagerHelper.VersionDir(histDir, versionNum - 1), "changes.json");
if (versionNum == 1 || !File.Exists(changesPath)) // check if the version number is equal to 1
{
var infoPath = Path.Combine(histDir, "createdInfo.json"); // get meta data of this file
if (File.Exists(infoPath))
{
var info = jss.Deserialize<Dictionary<string, object>>(File.ReadAllText(infoPath));
versionObj.Add("created", info["created"]); // write meta information to the object (user information and creation date)
versionObj.Add("user", new Dictionary<string, object>()
{
{ "id", info["id"] },
{ "name", info["name"] },
});
}
}
else if (versionNum > 1) // check if the version number is greater than 1 (the file was modified)
{
// get the path to the changes.json file
var changes = jss.Deserialize<Dictionary<string, object>>(File.ReadAllText(changesPath));
var changesArray = (ArrayList)changes["changes"];
var change = changesArray.Count > 0
? (Dictionary<string, object>)changesArray[0]
: new Dictionary<string, object>();
// write information about changes to the object
versionObj.Add("changes", change.Count > 0 ? changes["changes"] : null);
versionObj.Add("serverVersion", changes["serverVersion"]);
versionObj.Add("created", change.Count > 0 ? change["created"] : null);
versionObj.Add("user", change.Count > 0 ? change["user"] : null);
}
versionList.Add(versionObj);
}
history.Add("currentVersion", currentVersion);
history.Add("history", versionList);
return history;
}
// return all the supported formats
private static void Formats(HttpContext context)
{
try
{
Dictionary<string, object> data = new Dictionary<string, object>
{
{ "formats", FormatManager.All() }
};
context.Response.ContentType = "application/json";
var jss = new JavaScriptSerializer();
context.Response.Write(jss.Serialize(data));
}
catch (Exception e)
{
context.Response.Write("{ \"error\": \"" + e.Message + "\"}");
}
}
}
}

View File

@ -1,12 +1,15 @@
<?xml version="1.0"?>
<appSettings>
<clear />
<add key="version" value="1.8.0"/>
<add key="version" value="1.6.0"/>
<add key="filesize-max" value="52428800"/>
<add key="storage-path" value=""/>
<add key="filename-max" value="50"/>
<add key="files.docservice.fillform-docs" value=".docx|.oform"/>
<add key="files.docservice.viewed-docs" value=".djvu|.oxps|.pdf|.xps"/>
<add key="files.docservice.edited-docs" value=".csv|.docm|.docx|.docxf|.dotm|.dotx|.epub|.fb2|.html|.odp|.ods|.odt|.otp|.ots|.ott|.potm|.potx|.ppsm|.ppsx|.pptm|.pptx|.rtf|.txt|.xlsm|.xlsx|.xltm|.xltx"/>
<add key="files.docservice.convert-docs" value=".doc|.dot|.dps|.dpt|.epub|.et|.ett|.fb2|.fodp|.fods|.fodt|.htm|.html|.mht|.mhtml|.odp|.ods|.odt|.otp|.ots|.ott|.pot|.pps|.ppt|.rtf|.stw|.sxc|.sxi|.sxw|.wps|.wpt|.xls|.xlsb|.xlt|.xml"/>
<add key="files.docservice.timeout" value="120000" />
<add key="files.docservice.secret" value="" />
<add key="files.docservice.header" value="Authorization" />
@ -15,7 +18,7 @@
<add key="files.docservice.verify-peer-off" value="true"/>
<add key="files.docservice.languages" value="en:English|ar:Arabic|hy:Armenian|az:Azerbaijani|eu:Basque|be:Belarusian|bg:Bulgarian|ca:Catalan|zh:Chinese (Simplified)|zh-TW:Chinese (Traditional)|cs:Czech|da:Danish|nl:Dutch|en-GB:English (United Kingdom)|fi:Finnish|fr:French|gl:Galego|de:German|el:Greek|hu:Hungarian|id:Indonesian|it:Italian|ja:Japanese|ko:Korean|lo:Lao|lv:Latvian|ms:Malay (Malaysia)|no:Norwegian|pl:Polish|pt:Portuguese (Brazil)|pt-PT:Portuguese (Portugal)|ro:Romanian|ru:Russian|sr-Latn-RS:Serbian|si:Sinhala (Sri Lanka)|sk:Slovak|sl:Slovenian|es:Spanish|sv:Swedish|tr:Turkish|uk:Ukrainian|vi:Vietnamese|aa-AA:Test Language"/>
<add key="files.docservice.languages" value="en:English|hy:Armenian|az:Azerbaijani|eu:Basque|be:Belarusian|bg:Bulgarian|ca:Catalan|zh:Chinese (Simplified)|zh-TW:Chinese (Traditional)|cs:Czech|da:Danish|nl:Dutch|fi:Finnish|fr:French|gl:Galego|de:German|el:Greek|hu:Hungarian|id:Indonesian|it:Italian|ja:Japanese|ko:Korean|lo:Lao|lv:Latvian|ms:Malay (Malaysia)|no:Norwegian|pl:Polish|pt:Portuguese (Brazil)|pt-PT:Portuguese (Portugal)|ro:Romanian|ru:Russian|si:Sinhala (Sri Lanka)|sk:Slovak|sl:Slovenian|es:Spanish|sv:Swedish|tr:Turkish|uk:Ukrainian|vi:Vietnamese|aa-AA: Test Language"/>
<add key="files.docservice.url.site" value="http://documentserver/"/>

View File

@ -1 +1,8 @@
<svg width="30" height="40" viewBox="0 0 30 40" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M0 3c0-1.65685 1.34315-3 3-3h20l7 7v30c0 1.6569-1.3431 3-3 3H3c-1.65685 0-3-1.3431-3-3V3z" fill="#1E7AAA"/><path d="M23 0l7 7h-4c-1.6569 0-3-1.34315-3-3V0z" fill="#000" fill-opacity=".25"/><path d="M6 15h18v1H6v-1zM6 19h18v1H6v-1zM6 23h18v1H6v-1zM6 27h18v1H6v-1z" fill="#fff"/></svg>
<svg width="30" height="40" viewBox="0 0 30 40" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M0 3C0 1.34315 1.34315 0 3 0H21.674C22.4697 0 23.2327 0.316071 23.7953 0.87868L29.1213 6.20465C29.6839 6.76726 30 7.53032 30 8.32597V37C30 38.6569 28.6569 40 27 40H3C1.34315 40 0 38.6569 0 37V3Z" fill="#3779A6"/>
<path d="M22.9167 0L30.0001 7.08333H25.9167C24.2599 7.08333 22.9167 5.74019 22.9167 4.08333V0Z" fill="#1D5880"/>
<path d="M6.17627 14.7059H23.8233V15.8823H6.17627V14.7059Z" fill="white"/>
<path d="M6.17627 18.5294H23.8233V19.7059H6.17627V18.5294Z" fill="white"/>
<path d="M6.17627 22.3529H23.8233V23.5294H6.17627V22.3529Z" fill="white"/>
<path d="M6.17627 26.1765H23.8233V27.3529H6.17627V26.1765Z" fill="white"/>
</svg>

Before

Width:  |  Height:  |  Size: 387 B

After

Width:  |  Height:  |  Size: 738 B

View File

@ -1 +1,6 @@
<svg width="30" height="40" viewBox="0 0 30 40" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M0 3c0-1.65685 1.34315-3 3-3h20l7 7v30c0 1.6569-1.3431 3-3 3H3c-1.65685 0-3-1.3431-3-3V3z" fill="#27ABA3"/><path d="M23 0l7 7h-4c-1.6569 0-3-1.34315-3-3V0z" fill="#008078"/><path fill-rule="evenodd" clip-rule="evenodd" d="M24 14H6v7h18v-7zm-.8182 5.9978H6.81818V15H23.1818v4.9978zM24 23H6v7h18v-7zm-.8182 5.9978H6.81818V24H23.1818v4.9978z" fill="#fff"/></svg>
<svg width="30" height="40" viewBox="0 0 30 40" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M0 3C0 1.34315 1.34315 0 3 0H22.9167L30 7.08333V37C30 38.6569 28.6569 40 27 40H3C1.34315 40 0 38.6569 0 37V3Z" fill="#27ABA3"/>
<path d="M22.9165 0L29.9998 7.08333H25.9165C24.2597 7.08333 22.9165 5.74019 22.9165 4.08333V0Z" fill="#008078"/>
<rect x="6.5" y="15.5" width="17" height="5" stroke="white"/>
<rect x="6.5" y="23.5" width="17" height="5" stroke="white"/>
</svg>

Before

Width:  |  Height:  |  Size: 463 B

After

Width:  |  Height:  |  Size: 477 B

View File

@ -1 +1,8 @@
<svg width="30" height="40" viewBox="0 0 30 40" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M0 3c0-1.65685 1.34315-3 3-3h20l7 7v30c0 1.6569-1.3431 3-3 3H3c-1.65685 0-3-1.3431-3-3V3z" fill="#F36700"/><path d="M23 0l7 7h-4c-1.6569 0-3-1.34315-3-3V0z" fill="#000" fill-opacity=".25"/><path stroke="#fff" stroke-opacity=".95" d="M6.5 15.5h17v12h-17z"/></svg>
<svg width="30" height="40" viewBox="0 0 30 40" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M0 3C0 1.34315 1.34315 0 3 0H22.9167L30 7.08333V37C30 38.6569 28.6569 40 27 40H3C1.34315 40 0 38.6569 0 37V3Z" fill="#F36700"/>
<path d="M22.9167 0L30.0001 7.08333H25.9168C24.2599 7.08333 22.9167 5.74019 22.9167 4.08333V0Z" fill="#AB531F"/>
<path d="M6.17627 16.1275H23.8233V17.3039H6.17627V16.1275Z" fill="white"/>
<path d="M6.17627 28.7745L6.17627 16.1275L7.35274 16.1275L7.35274 28.7745H6.17627Z" fill="white"/>
<path d="M23.8233 16.1275V28.7745H22.6469V16.1275L23.8233 16.1275Z" fill="white"/>
<path d="M6.17627 27.598H23.8233V28.7745H6.17627L6.17627 27.598Z" fill="white"/>
</svg>

Before

Width:  |  Height:  |  Size: 366 B

After

Width:  |  Height:  |  Size: 691 B

View File

@ -1 +1,6 @@
<svg width="30" height="40" viewBox="0 0 30 40" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M0 3c0-1.65685 1.34315-3 3-3h20l7 7v30c0 1.6569-1.3431 3-3 3H3c-1.65685 0-3-1.3431-3-3V3z" fill="#D0D5DA"/><path d="M23 0l7 7h-4c-1.6569 0-3-1.34315-3-3V0z" fill="#646464"/><path fill-rule="evenodd" clip-rule="evenodd" d="M7.5 23c-.27614 0-.5.2239-.5.5v4c0 .2761.22386.5.5.5h15c.2761 0 .5-.2239.5-.5v-4c0-.2761-.2239-.5-.5-.5h-2c-.2761 0-.5-.2239-.5-.5s.2239-.5.5-.5h2c.8284 0 1.5.6716 1.5 1.5v4c0 .8284-.6716 1.5-1.5 1.5h-15c-.82843 0-1.5-.6716-1.5-1.5v-4c0-.8284.67157-1.5 1.5-1.5h2c.27614 0 .5.2239.5.5s-.22386.5-.5.5h-2z" fill="#646464"/><path fill-rule="evenodd" clip-rule="evenodd" d="M20 20.0001L15 14l-5 6.0001h3v4c0 .5523.4477 1 1 1h2c.5523 0 1-.4477 1-1v-4h3z" fill="#646464"/></svg>
<svg width="30" height="40" viewBox="0 0 30 40" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M30 7.44186L22 0H3C1.22739 0 0 0.822551 0 2.32558V37.2093C0 38.7123 1.22739 40 3 40H27C28.7726 40 30 38.7123 30 37.2093V7.44186Z" fill="#D0D5DA"/>
<path d="M24.1042 7.27273H29.9631L22 0V5.32334C22 6.4105 22.949 7.27273 24.1042 7.27273Z" fill="#646464"/>
<path d="M16.9562 22.3485H12.9746V17.803H10.9839L14.9654 14.1667L18.947 17.803H16.9562V22.3485Z" fill="#646464"/>
<path d="M20.9378 23.7121C20.9378 24.1666 20.4401 24.6212 19.9424 24.6212H9.98848C9.49078 24.6212 8.99309 24.1666 8.99309 23.7121V22.3485C8.99309 21.8939 9.49078 21.4394 9.98848 21.4394H10.9839V20.0757H9.49078C8.49539 20.0757 7.5 20.9848 7.5 21.8939V24.1666C7.5 25.0757 8.61982 25.9848 9.49078 25.9848H20.4401C21.3111 25.9848 22.4309 25.0757 22.4309 24.1666V21.8939C22.4309 20.9848 21.4355 20.0757 20.4401 20.0757H18.947V21.4394H19.9424C20.4401 21.4394 20.9378 21.8939 20.9378 22.3485V23.7121Z" fill="#646464"/>
</svg>

Before

Width:  |  Height:  |  Size: 797 B

After

Width:  |  Height:  |  Size: 992 B

View File

@ -1 +1,12 @@
<svg width="30" height="40" viewBox="0 0 30 40" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M0 3c0-1.65685 1.34315-3 3-3h20l7 7v30c0 1.6569-1.3431 3-3 3H3c-1.65685 0-3-1.3431-3-3V3z" fill="#6AAA1E"/><path d="M23 0l7 7h-4c-1.6569 0-3-1.34315-3-3V0z" fill="#000" fill-opacity=".25"/><path fill-rule="evenodd" clip-rule="evenodd" d="M6 15h18v13H7.00001v-1H12v-3H7v4H6V15zm7 12h4v-3h-4v3zm5 0h5v-3h-5v3zm5-7v3h-5v-3h5zm-6 0v3h-4v-3h4zm-5 0v3H7v-3h5zm11-1v-3h-5v3h5zm-10-3h4v3h-4v-3zm-1 3v-3H7v3h5z" fill="#fff" fill-opacity=".95"/></svg>
<svg width="30" height="40" viewBox="0 0 30 40" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M0 3C0 1.34315 1.34315 0 3 0H22.9167L30 7.08333V37C30 38.6569 28.6569 40 27 40H3C1.34315 40 0 38.6569 0 37V3Z" fill="#78A73B"/>
<path d="M22.9167 0L30.0001 7.08333H25.9168C24.2599 7.08333 22.9167 5.74019 22.9167 4.08333V0Z" fill="#5A7D2B"/>
<path d="M6.17644 15.2941H23.8235V16.4706H6.17644V15.2941Z" fill="white"/>
<path d="M6.17644 19.1177H23.8235V20.2941H6.17644V19.1177Z" fill="white"/>
<path d="M6.17644 22.9412H23.8235V24.1177H6.17644V22.9412Z" fill="white"/>
<path d="M6.17644 26.7647H23.8235V27.9412H6.17644V26.7647Z" fill="white"/>
<path d="M5.88232 27.9412L5.88232 15.2941L7.0588 15.2941L7.0588 27.9412H5.88232Z" fill="white"/>
<path d="M11.4706 27.9412L11.4706 15.2941L12.647 15.2941V27.9412H11.4706Z" fill="white"/>
<path d="M17.0588 27.9412L17.0588 15.2941L18.2353 15.2941V27.9412H17.0588Z" fill="white"/>
<path d="M22.647 27.9412V15.2941H23.8235V27.9412H22.647Z" fill="white"/>
</svg>

Before

Width:  |  Height:  |  Size: 545 B

After

Width:  |  Height:  |  Size: 1004 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

View File

@ -1,6 +1,6 @@
/**
*
* (c) Copyright Ascensio System SIA 2024
* (c) Copyright Ascensio System SIA 2023
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -502,17 +502,6 @@
justify-content: space-between;
align-items: center;
}
.buttonsMobile.indent {
margin-bottom: 0;
flex-wrap: nowrap;
}
.button.file-type:hover,
.button.file-type {
height: 28px;
width: 100px;
margin-bottom: 10px !important;
font-size: 9px;
}
.button.gray{
margin: 0;
}

View File

@ -1,6 +1,6 @@
/**
*
* (c) Copyright Ascensio System SIA 2024
* (c) Copyright Ascensio System SIA 2023
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -230,33 +230,6 @@ label .checkbox {
color: #FF6F3D;
}
.button.file-type {
font-size: 11px;
color: #FFFFFF;
padding: 8px 8px;
margin-right: 10px;
}
.button.file-type.disable {
cursor: default;
}
.button.file-type.pale {
opacity: 30%;
}
.button.file-type.document {
background: #446995;
}
.button.file-type.spreadsheet {
background: #40865C;
}
.button.file-type.presentation {
background: #AA5252;
}
.upload-panel {
float: left;
padding: 24px 0;
@ -623,29 +596,6 @@ footer a:hover {
width: 4%;
}
.storedHeader {
display: flex;
width: 100%;
justify-content: space-between;
align-items: center;
}
.storedHeaderClearAll {
padding-right: 52px;
}
.clear-all {
display: inline-block;
width: 100px;
padding: 2px;
outline: 1px solid #E5E5E5;
text-align: center;
cursor:pointer;
text-transform: uppercase;
background-color: #F5F5F5;
color: #666666;
}
.select-user {
color: #444444;
font-family: Open Sans;
@ -795,16 +745,6 @@ html {
margin-left: 25px;
}
.buttonsMobile.indent{
padding-left: 35px;
margin-top: 10px;
margin-bottom: 10px;
}
.invisible {
display: none;
}
.tooltip {
background: #FFFFFF;
border-radius: 5px;

View File

@ -13,11 +13,10 @@
<head runat="server">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="viewport" content="width=device-width" />
<meta name="server-version" content=<%= GetVersion() %> />
<title>ONLYOFFICE</title>
<!--
*
* (c) Copyright Ascensio System SIA 2024
* (c) Copyright Ascensio System SIA 2023
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -71,7 +70,7 @@
<a class="try-editor slide" data-type="slide">Presentation</a>
</li>
<li>
<a class="try-editor form" data-type="docxf">PDF form</a>
<a class="try-editor form" data-type="docxf">Form template</a>
</li>
</ul>
<label class="side-option">
@ -153,14 +152,7 @@
if (storedFiles.Any())
{ %>
<div class="stored-list">
<div class="storedHeader">
<div class="storedHeaderText">
<span class="header-list">Your documents</span>
</div>
<div class="storedHeaderClearAll">
<div class="clear-all">Clear all</div>
</div>
</div>
<span class="header-list">Your documents</span>
<table class="tableHeader" cellspacing="0" cellpadding="0" width="100%">
<thead>
<tr >
@ -304,15 +296,6 @@
<div class="describeUpload">After these steps are completed, you can work with your document.</div>
<span id="step1" class="step">1. Loading the file.</span>
<span class="step-descr">The loading speed depends on file size and additional elements it contains.</span>
<div id="select-file-type" class="invisible">
<br />
<span class="step">Please select the current document type</span>
<div class="buttonsMobile indent">
<div class="button file-type document" data="docx">Document</div>
<div class="button file-type spreadsheet" data="xlsx">Spreadsheet</div>
<div class="button file-type presentation" data="pptx">Presentation</div>
</div>
</div>
<br />
<span id="step2" class="step">2. Conversion.</span>
<span class="step-descr">The file is converted to OOXML so that you can edit it.</span>
@ -380,8 +363,12 @@
<script language="javascript" type="text/javascript" src="script/jquery.iframe-transport.js"></script>
<script language="javascript" type="text/javascript" src="script/jquery.fileupload.js"></script>
<script language="javascript" type="text/javascript" src="script/jquery.dropdownToggle.js"></script>
<script language="javascript" type="text/javascript" src="script/formats.js"></script>
<script language="javascript" type="text/javascript" src="script/jscript.js"></script>
<script language="javascript" type="text/javascript">
var FillFormExtList = '<%= string.Join(",", FillFormsExts.ToArray()) %>';
var ConverExtList = '<%= string.Join(",", ConvertExts.ToArray()) %>';
var EditedExtList = '<%= string.Join(",", EditedExts.ToArray()) %>';
</script>
</body>
</html>

View File

@ -1,6 +1,6 @@
/**
*
* (c) Copyright Ascensio System SIA 2024
* (c) Copyright Ascensio System SIA 2023
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -30,15 +30,49 @@ using ASC.Api.DocumentConverter;
namespace OnlineEditorsExample
{
internal static class FileType
{
// the spreadsheet extension list
public static readonly List<string> ExtsSpreadsheet = new List<string>
{
".xls", ".xlsx", ".xlsm", ".xlsb",
".xlt", ".xltx", ".xltm",
".ods", ".fods", ".ots", ".csv"
};
// the presentation extension list
public static readonly List<string> ExtsPresentation = new List<string>
{
".pps", ".ppsx", ".ppsm",
".ppt", ".pptx", ".pptm",
".pot", ".potx", ".potm",
".odp", ".fodp", ".otp"
};
// the document extension list
public static readonly List<string> ExtsDocument = new List<string>
{
".doc", ".docx", ".docm",
".dot", ".dotx", ".dotm",
".odt", ".fodt", ".ott", ".rtf", ".txt",
".html", ".htm", ".mht", ".xml",
".pdf", ".djvu", ".fb2", ".epub", ".xps", ".oxps", ".oform"
};
// get an internal file extension
public static string GetInternalExtension(string extension)
{
extension = Path.GetExtension(extension).ToLower(); // get file extension
if (ExtsDocument.Contains(extension)) return ".docx"; // .docx for text document extensions
if (ExtsSpreadsheet.Contains(extension)) return ".xlsx"; // .xlsx for spreadsheet extensions
if (ExtsPresentation.Contains(extension)) return ".pptx"; // .pptx for presentation extensions
return string.Empty;
}
}
public partial class _Default : Page
{
//get server version
public static string GetVersion()
{
return WebConfigurationManager.AppSettings["version"];
}
// get the virtual path
public static string VirtualPath
{
@ -81,24 +115,24 @@ namespace OnlineEditorsExample
// file extensions that can be viewed
private static List<string> ViewedExts
{
get { return FormatManager.ViewableExtensions(); }
get { return (WebConfigurationManager.AppSettings["files.docservice.viewed-docs"] ?? "").Split(new char[] { '|', ',' }, StringSplitOptions.RemoveEmptyEntries).ToList(); }
}
public static List<string> FillFormsExts
{
get { return FormatManager.FillableExtensions(); }
get { return (WebConfigurationManager.AppSettings["files.docservice.fillform-docs"] ?? "").Split(new char[] { '|', ',' }, StringSplitOptions.RemoveEmptyEntries).ToList(); }
}
// file extensions that can be edited
public static List<string> EditedExts
{
get { return FormatManager.EditableExtensions(); }
get { return (WebConfigurationManager.AppSettings["files.docservice.edited-docs"] ?? "").Split(new char[] { '|', ',' }, StringSplitOptions.RemoveEmptyEntries).ToList(); }
}
// file extensions that can be converted
public static List<string> ConvertExts
{
get { return FormatManager.ConvertibleExtensions(); }
get { return (WebConfigurationManager.AppSettings["files.docservice.convert-docs"] ?? "").Split(new char[] { '|', ',' }, StringSplitOptions.RemoveEmptyEntries).ToList(); }
}
private static string _fileName;
@ -250,9 +284,9 @@ namespace OnlineEditorsExample
{
var ext = Path.GetExtension(fileName).ToLower();
if (FormatManager.DocumentExtensions().Contains(ext)) return "word"; // word for text document extensions
if (FormatManager.SpreadsheetExtensions().Contains(ext)) return "cell"; // cell for spreadsheet extensions
if (FormatManager.PresentationExtensions().Contains(ext)) return "slide"; // slide for presentation extensions
if (FileType.ExtsDocument.Contains(ext)) return "word"; // word for text document extensions
if (FileType.ExtsSpreadsheet.Contains(ext)) return "cell"; // cell for spreadsheet extensions
if (FileType.ExtsPresentation.Contains(ext)) return "slide"; // slide for presentation extensions
return "word"; // the default document type is word
}
@ -437,14 +471,7 @@ namespace OnlineEditorsExample
var lang = context.Request.Cookies.GetOrDefault("ulang", null);
var extension = (Path.GetExtension(_fileName).ToLower() ?? "").Trim('.');
string conversionExtension = "ooxml"; // set the default conversion extension as ooxml
object fileExt;
// change the conversion extension if it was provided in the request body
if (body.TryGetValue("fileExt", out fileExt) && !String.IsNullOrEmpty(fileExt.ToString()))
{
conversionExtension = fileExt.ToString();
}
var internalExtension = "ooxml";
// check if the file with such an extension can be converted
if (ConvertExts.Contains("." + extension))
@ -461,7 +488,7 @@ namespace OnlineEditorsExample
// get the url and file type of the converted file
Dictionary<string, string> newFileData;
var result = ServiceConverter.GetConvertedData(fileUrl.ToString() , extension, conversionExtension, key, true, out newFileData, filePass, lang);
var result = ServiceConverter.GetConvertedData(fileUrl.ToString() , extension, internalExtension, key, true, out newFileData, filePass, lang);
if (result != 100)
{
return "{ \"step\" : \"" + result + "\", \"filename\" : \"" + _fileName + "\"}";
@ -511,12 +538,7 @@ namespace OnlineEditorsExample
// get the correct file name if such a name already exists
public static string GetCorrectName(string fileName, string userAddress = null)
{
int maxName;
int.TryParse(WebConfigurationManager.AppSettings["filename-max"], out maxName);
var baseName = Path.GetFileNameWithoutExtension(fileName); // get file name without extension
if (baseName.Length > maxName){
baseName = baseName.Substring(0, maxName) + "[...]";
}
var ext = Path.GetExtension(fileName).ToLower(); // get file extension
var name = baseName + ext; // get full file name
@ -611,12 +633,5 @@ namespace OnlineEditorsExample
string isEnabledDirectUrl = HttpUtility.ParseQueryString(HttpContext.Current.Request.Url.Query).Get("directUrl");
return "&directUrl=" + (isEnabledDirectUrl != null ? isEnabledDirectUrl : "false");
}
// get direct url flag
public static bool IsEnabledDirectUrl()
{
string isEnabledDirectUrl = HttpUtility.ParseQueryString(HttpContext.Current.Request.Url.Query).Get("directUrl");
return isEnabledDirectUrl != null ? Convert.ToBoolean(isEnabledDirectUrl) : false;
}
}
}

View File

@ -15,7 +15,7 @@
<title>ONLYOFFICE</title>
<!--
*
* (c) Copyright Ascensio System SIA 2024
* (c) Copyright Ascensio System SIA 2023
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -145,17 +145,13 @@
};
// the user is trying to select document for comparing by clicking the Document from Storage button
var onRequestSelectDocument = function (event) {
var data = <%= DocumentData %>;
data.c = event.data.c;
docEditor.setRequestedDocument(data); // select a document for comparing
var onRequestCompareFile = function () {
docEditor.setRevisedFile(<%= CompareFileData %>); // select a document for comparing
};
// the user is trying to select recipients data by clicking the Mail merge button
var onRequestSelectSpreadsheet = function (event) {
var data = <%= DataSpreadsheet %>;
data.c = event.data.c;
docEditor.setRequestedSpreadsheet(data); // insert recipient data for spreadsheet into the file
var onRequestMailMergeRecipients = function (event) {
docEditor.setMailMergeRecipients(<%= DataMailMergeRecipients %>); // insert recipient data for mail merge into the file
};
var onRequestSaveAs = function (event) { // the user is trying to save file by clicking Save Copy as... button
@ -194,80 +190,19 @@
}
};
var onRequestOpen = function (event) { // user open external data source
innerAlert("onRequestOpen");
var windowName = event.data.windowName;
requestReference(event.data, function (data) {
if (data.error) {
var winEditor = window.open("", windowName);
winEditor.close();
innerAlert(data.error, true);
return;
}
var link = data.link;
window.open(link, windowName);
});
};
var onRequestReferenceData = function (event) { // user refresh external data source
innerAlert("onRequestReferenceData");
requestReference(event.data, function (data) {
docEditor.setReferenceData(data);
});
};
var requestReference = function (data, callback) {
innerAlert(data);
data.directUrl = !!config.document.directUrl;
event.data.directUrl = !!config.document.directUrl;
let xhr = new XMLHttpRequest();
xhr.open("POST", "webeditor.ashx?type=reference");
xhr.setRequestHeader("Content-Type", "application/json");
xhr.send(JSON.stringify(data));
xhr.send(JSON.stringify(event.data));
xhr.onload = function () {
console.log(xhr.responseText);
callback(JSON.parse(xhr.responseText));
docEditor.setReferenceData(JSON.parse(xhr.responseText));
}
};
var onRequestUsers = function (event) {
if (event && event.data){
var c = event.data.c;
}
switch (c) {
case "info":
users = [];
var allUsers = <%= UsersInfo %>;
for (var i = 0; i < event.data.id.length; i++) {
for (var j = 0; j < allUsers.length; j++) {
if (allUsers[j].id == event.data.id[i]) {
users.push(allUsers[j]);
break;
}
}
}
break;
case "protect":
var users = <%= UsersForProtect %>;
break;
default:
users = <%= UsersForMentions %>;
}
docEditor.setUsers({
"c": c,
"users": users,
});
};
var onRequestSendNotify = function (event) {
event.data.actionLink = replaceActionLink(location.href, JSON.stringify(event.data.actionLink));
var data = JSON.stringify(event.data);
innerAlert("onRequestSendNotify: " + data);
};
config = <%= DocConfig %>;
config.width = "100%";
@ -281,75 +216,60 @@
'onMakeActionLink': onMakeActionLink,
'onMetaChange': onMetaChange,
'onRequestInsertImage': onRequestInsertImage,
'onRequestSelectDocument': onRequestSelectDocument,
"onRequestSelectSpreadsheet": onRequestSelectSpreadsheet,
'onRequestCompareFile': onRequestCompareFile,
"onRequestMailMergeRecipients": onRequestMailMergeRecipients,
};
if (config.editorConfig.user.id) {
config.events['onRequestHistory'] = function (event) { // the user is trying to show the document version history
let xhr = new XMLHttpRequest();
xhr.open("GET", "webeditor.ashx?type=gethistory&filename=<%= FileName %>");
xhr.setRequestHeader("Content-Type", "application/json");
xhr.send();
xhr.onload = function () {
console.log(xhr.responseText);
docEditor.refreshHistory(JSON.parse(xhr.responseText));
}
};
config.events['onRequestHistoryData'] = function (event) { // the user is trying to click the specific document version in the document version history
var ver = event.data;
let xhr = new XMLHttpRequest();
xhr.open("GET", "webeditor.ashx?type=getversiondata&filename=<%= FileName %>&version=" + ver + "&directUrl=" + !!config.document.directUrl);
xhr.setRequestHeader("Content-Type", "application/json");
xhr.send();
xhr.onload = function () {
console.log(xhr.responseText);
docEditor.setHistoryData(JSON.parse(xhr.responseText)); // send the link to the document for viewing the version history
}
};
if (config.editorConfig.user.id !== "uid-3") {
<% if (!string.IsNullOrEmpty(History) && !string.IsNullOrEmpty(HistoryData))
{ %>
config.events['onRequestHistory'] = function () { // the user is trying to show the document version history
docEditor.refreshHistory(<%= History %>); // show the document version history
};
config.events['onRequestHistoryData'] = function (event) { // the user is trying to click the specific document version in the document version history
var ver = event.data;
var histData = <%= HistoryData %>;
docEditor.setHistoryData(histData[ver - 1]); // send the link to the document for viewing the version history
};
config.events['onRequestHistoryClose'] = function () { // the user is trying to go back to the document from viewing the document version history
document.location.reload();
};
config.events['onRequestRestore'] = function (event) {
var fileName = "<%= FileName %>";
var version = event.data.version;
var data = {
fileName: fileName,
version: version
};
let xhr = new XMLHttpRequest();
xhr.open("POST", "webeditor.ashx?type=restore&directUrl=" + !!config.document.directUrl);
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.send(JSON.stringify(data));
xhr.onload = function () {
docEditor.refreshHistory(JSON.parse(xhr.responseText));
}
};
}
<% } %>
// add mentions for not anonymous users
<% if (!string.IsNullOrEmpty(UsersForMentions))
{ %>
config.events['onRequestUsers'] = onRequestUsers;
config.events['onRequestUsers'] = function () {
docEditor.setUsers({ // set a list of users to mention in the comments
"users": <%= UsersForMentions %>
});
};
<% } %>
config.events['onRequestSaveAs'] = onRequestSaveAs;
// the user is mentioned in a comment
config.events['onRequestSendNotify'] = onRequestSendNotify;
config.events['onRequestSendNotify'] = function (event) {
event.data.actionLink = replaceActionLink(location.href, JSON.stringify(event.data.actionLink));
var data = JSON.stringify(event.data);
innerAlert("onRequestSendNotify: " + data);
};
// prevent file renaming for anonymous users
config.events['onRequestRename'] = onRequestRename;
config.events['onRequestReferenceData'] = onRequestReferenceData;
// prevent switch the document from the viewing into the editing mode for anonymous users
config.events['onRequestEditRights'] = onRequestEditRights;
config.events['onRequestOpen'] = onRequestOpen;
}
if (config.editorConfig.createUrl) {
config.events.onRequestSaveAs = onRequestSaveAs;
};
var сonnectEditor = function () {
if ((config.document.fileType === "docxf" || config.document.fileType === "oform")
&& DocsAPI.DocEditor.version().split(".")[0] < 7) {
innerAlert("Please update ONLYOFFICE Docs to version 7.0 to work on fillable forms online.");
return;
}
docEditor = new DocsAPI.DocEditor("iframeEditor", config);
};

View File

@ -1,6 +1,6 @@
/**
*
* (c) Copyright Ascensio System SIA 2024
* (c) Copyright Ascensio System SIA 2023
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -17,6 +17,7 @@
*/
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Web;
@ -60,12 +61,12 @@ namespace OnlineEditorsExample
}
protected string DocConfig { get; private set; }
protected string History { get; private set; }
protected string HistoryData { get; private set; }
protected string InsertImageConfig { get; private set; }
protected string DocumentData { get; private set; }
protected string DataSpreadsheet { get; private set; }
protected string CompareFileData { get; private set; }
protected string DataMailMergeRecipients { get; private set; }
protected string UsersForMentions { get; private set; }
protected string UsersInfo { get; private set; }
protected string UsersForProtect { get; private set; }
protected string DocumentType { get { return _Default.DocumentType(FileName); } }
// get callback url
@ -154,7 +155,7 @@ namespace OnlineEditorsExample
editorsMode = "fillForms";
canEdit = true;
}
var submitForm = editorsMode.Equals("fillForms") && id.Equals("uid-1"); // check if the Submit form button is displayed or hidden
var submitForm = editorsMode.Equals("fillForms") && id.Equals("uid-1") && false; // check if the Submit form button is displayed or hidden
var mode = canEdit && editorsMode != "view" ? "edit" : "view"; // get the editor opening mode (edit or view)
var jss = new JavaScriptSerializer();
@ -194,7 +195,7 @@ namespace OnlineEditorsExample
{
{ "title", FileName },
{ "url", getDownloadUrl(FileName) },
{ "directUrl", _Default.IsEnabledDirectUrl() ? directUrl : "" },
{ "directUrl", IsEnabledDirectUrl() ? directUrl : "" },
{ "fileType", ext.Trim('.') },
{ "key", Key },
{
@ -225,7 +226,7 @@ namespace OnlineEditorsExample
{ "download", !user.deniedPermissions.Contains("download") },
{ "edit", canEdit && (editorsMode == "edit" || editorsMode =="view" || editorsMode == "filter" || editorsMode == "blockcontent") },
{ "print", !user.deniedPermissions.Contains("print") },
{ "fillForms", editorsMode != "view" && editorsMode != "comment" && editorsMode != "blockcontent" },
{ "fillForms", editorsMode != "view" && editorsMode != "comment" && editorsMode != "embedded" && editorsMode != "blockcontent" },
{ "modifyFilter", editorsMode != "filter" },
{ "modifyContentControl", editorsMode != "blockcontent" },
{ "review", canEdit && (editorsMode == "edit" || editorsMode == "review") },
@ -258,8 +259,7 @@ namespace OnlineEditorsExample
{
{ "id", !user.id.Equals("uid-0") ? user.id : null },
{ "name", user.name },
{ "group", user.group },
{ "image", user.avatar ? _Default.GetServerUrl(false) + "/App_Themes/images/"+ user.id + ".png" : null }
{ "group", user.group }
}
},
{
@ -282,12 +282,10 @@ namespace OnlineEditorsExample
{ "forcesave", false }, // adds the request for the forced file saving to the callback handler
{ "submitForm", submitForm }, // if the Submit form button is displayed or not
{
"goback", user.goback != null ? new Dictionary<string, object> // settings for the Open file location menu button and upper right corner button
"goback", new Dictionary<string, object> // settings for the Open file location menu button and upper right corner button
{
{ "url", _Default.GetServerUrl(false) + "default.aspx" }, // the absolute URL to the website address which will be opened when clicking the Open file location menu button
{ "text", user.goback.text },
{ "blank", user.goback.blank }
} : new Dictionary<string, object>{}
{ "url", _Default.GetServerUrl(false) + "default.aspx" } // the absolute URL to the website address which will be opened when clicking the Open file location menu button
}
}
}
}
@ -313,26 +311,143 @@ namespace OnlineEditorsExample
// a document which will be compared with the current document
Dictionary<string, object> compareFile = GetCompareFile();
DocumentData = jss.Serialize(compareFile);
CompareFileData = jss.Serialize(compareFile);
// recipient data for spreadsheet
Dictionary<string, object> spreadsheetConfig = GetSpreadsheetConfig();
DataSpreadsheet = jss.Serialize(spreadsheetConfig);
// recipient data for mail merging
Dictionary<string, object> mailMergeConfig = GetMailMergeConfig();
DataMailMergeRecipients = jss.Serialize(mailMergeConfig);
// get users for mentions
List<Dictionary<string, object>> usersData = Users.getUsersForMentions(user.id);
UsersForMentions = !user.id.Equals("uid-0") ? jss.Serialize(usersData) : null;
List<Dictionary<string, object>> usersInfo = Users.getUsersInfo(user.id);
UsersInfo = jss.Serialize(usersData);
// get users for protect
List<Dictionary<string, object>> usersProtectData = Users.getUsersForProtect(user.id);
UsersForProtect = !user.id.Equals("uid-0") ? jss.Serialize(usersProtectData) : null;
Dictionary<string, object> hist;
Dictionary<string, object> histData;
// get the document history
GetHistory(out hist, out histData);
if (hist != null && histData != null)
{
History = jss.Serialize(hist);
HistoryData = jss.Serialize(histData);
}
}
catch { }
}
// get the document history
private void GetHistory(out Dictionary<string, object> history, out Dictionary<string, object> historyData)
{
var storagePath = WebConfigurationManager.AppSettings["storage-path"];
var jss = new JavaScriptSerializer();
var histDir = _Default.HistoryDir(_Default.StoragePath(FileName, null));
history = null;
historyData = null;
if (_Default.GetFileVersion(histDir) > 0) // if the file was modified (the file version is greater than 0)
{
var currentVersion = _Default.GetFileVersion(histDir);
var hist = new List<Dictionary<string, object>>();
var histData = new Dictionary<string, object>();
for (var i = 1; i <= currentVersion; i++) // run through all the file versions
{
var obj = new Dictionary<string, object>();
var dataObj = new Dictionary<string, object>();
var verDir = _Default.VersionDir(histDir, i); // get the path to the given file version
var key = i == currentVersion ? Key : File.ReadAllText(Path.Combine(verDir, "key.txt")); // get document key
obj.Add("key", key);
obj.Add("version", i);
if (i == 1) // check if the version number is equal to 1
{
var infoPath = Path.Combine(histDir, "createdInfo.json"); // get meta data of this file
if (File.Exists(infoPath)) {
var info = jss.Deserialize<Dictionary<string, object>>(File.ReadAllText(infoPath));
obj.Add("created", info["created"]); // write meta information to the object (user information and creation date)
obj.Add("user", new Dictionary<string, object>() {
{ "id", info["id"] },
{ "name", info["name"] },
});
}
}
var ext = Path.GetExtension(FileName).ToLower();
dataObj.Add("fileType", ext.Replace(".", ""));
dataObj.Add("key", key);
// write file url to the data object
var directPrevFileUrl = i == currentVersion ? _Default.FileUri(FileName, false) : MakePublicHistoryUrl(FileName, i.ToString(), "prev" + ext, false);
var prevFileUrl = i == currentVersion ? FileUri : MakePublicHistoryUrl(FileName, i.ToString(), "prev" + ext);
if (Path.IsPathRooted(storagePath))
{
prevFileUrl = i == currentVersion ? getDownloadUrl(FileName) : getDownloadUrl(Directory.GetFiles(verDir, "prev.*")[0].Replace(storagePath + "\\", ""));
directPrevFileUrl = i == currentVersion ? getDownloadUrl(FileName, false) : getDownloadUrl(Directory.GetFiles(verDir, "prev.*")[0].Replace(storagePath + "\\", ""), false);
}
dataObj.Add("url", prevFileUrl); // write file 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)
{
// get the path to the changes.json file
var changes = jss.Deserialize<Dictionary<string, object>>(File.ReadAllText(Path.Combine(_Default.VersionDir(histDir, i - 1), "changes.json")));
var changesArray = (ArrayList)changes["changes"];
var change = changesArray.Count > 0
? (Dictionary<string, object>)changesArray[0]
: new Dictionary<string, object>();
// write information about changes to the object
obj.Add("changes", change.Count > 0 ? changes["changes"] : null);
obj.Add("serverVersion", changes["serverVersion"]);
obj.Add("created", change.Count > 0 ? change["created"] : null);
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
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"] }
};
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);
}
if (JwtManager.Enabled)
{
var token = JwtManager.Encode(dataObj);
dataObj.Add("token", token);
}
hist.Add(obj); // add object dictionary to the hist list
histData.Add((i - 1).ToString(), dataObj); // write data object information to the history data
}
// write history information about the current file version to the history object
history = new Dictionary<string, object>()
{
{ "currentVersion", currentVersion },
{ "history", hist }
};
historyData = histData;
}
}
// get a logo config
private Dictionary<string, object> GetLogoConfig()
{
@ -340,21 +455,21 @@ namespace OnlineEditorsExample
var InsertImageUrl = new UriBuilder(_Default.GetServerUrl(true));
InsertImageUrl.Path = HttpRuntime.AppDomainAppVirtualPath
+ (HttpRuntime.AppDomainAppVirtualPath.EndsWith("/") ? "" : "/")
+ "App_Themes\\images\\logo.svg";
+ "App_Themes\\images\\logo.png";
var DirectImageUrl = new UriBuilder(_Default.GetServerUrl(false));
DirectImageUrl.Path = HttpRuntime.AppDomainAppVirtualPath
+ (HttpRuntime.AppDomainAppVirtualPath.EndsWith("/") ? "" : "/")
+ "App_Themes\\images\\logo.svg";
+ "App_Themes\\images\\logo.png";
// create a logo config
Dictionary<string, object> logoConfig = new Dictionary<string, object>
{
{ "fileType", "svg"},
{ "fileType", "png"},
{ "url", InsertImageUrl.ToString()}
};
if (_Default.IsEnabledDirectUrl())
if (IsEnabledDirectUrl())
{
logoConfig.Add("directUrl", DirectImageUrl.ToString());
}
@ -391,7 +506,7 @@ namespace OnlineEditorsExample
{ "url", compareFileUrl.ToString() }
};
if (_Default.IsEnabledDirectUrl())
if (IsEnabledDirectUrl())
{
dataCompareFile.Add("directUrl", DirectFileUrl.ToString());
}
@ -405,43 +520,43 @@ namespace OnlineEditorsExample
return dataCompareFile;
}
// get a spreadsheet config
private Dictionary<string, object> GetSpreadsheetConfig()
// get a mail merge config
private Dictionary<string, object> GetMailMergeConfig()
{
// get the path to the recipients data for spreadsheet
var spreadsheetUrl = new UriBuilder(_Default.GetServerUrl(true));
spreadsheetUrl.Path =
// get the path to the recipients data for mail merging
var mailmergeUrl = new UriBuilder(_Default.GetServerUrl(true));
mailmergeUrl.Path =
HttpRuntime.AppDomainAppVirtualPath
+ (HttpRuntime.AppDomainAppVirtualPath.EndsWith("/") ? "" : "/")
+ "webeditor.ashx";
spreadsheetUrl.Query = "type=csv";
mailmergeUrl.Query = "type=csv";
var DirectSpreadsheetUrl = new UriBuilder(_Default.GetServerUrl(false));
DirectSpreadsheetUrl.Path =
var DirectMailMergeUrl = new UriBuilder(_Default.GetServerUrl(false));
DirectMailMergeUrl.Path =
HttpRuntime.AppDomainAppVirtualPath
+ (HttpRuntime.AppDomainAppVirtualPath.EndsWith("/") ? "" : "/")
+ "webeditor.ashx";
DirectSpreadsheetUrl.Query = "type=csv";
DirectMailMergeUrl.Query = "type=csv";
// create a spreadsheet config
Dictionary<string, object> spreadsheetConfig = new Dictionary<string, object>
// create a mail merge config
Dictionary<string, object> mailMergeConfig = new Dictionary<string, object>
{
{ "fileType", "csv" },
{ "url", spreadsheetUrl.ToString() }
{ "url", mailmergeUrl.ToString() }
};
if (_Default.IsEnabledDirectUrl())
if (IsEnabledDirectUrl())
{
spreadsheetConfig.Add("directUrl", DirectSpreadsheetUrl.ToString());
mailMergeConfig.Add("directUrl", DirectMailMergeUrl.ToString());
}
if (JwtManager.Enabled) // if the secret key to generate token exists
{
var spreadsheetToken = JwtManager.Encode(spreadsheetConfig); // encode spreadsheetConfig into the token
spreadsheetConfig.Add("token", spreadsheetToken); // and add it to the spreadsheet config
var mailmergeToken = JwtManager.Encode(mailMergeConfig); // encode mailMergeConfig into the token
mailMergeConfig.Add("token", mailmergeToken); // and add it to the mail merge config
}
return spreadsheetConfig;
return mailMergeConfig;
}
// get image url for templates
@ -474,6 +589,21 @@ namespace OnlineEditorsExample
return _Default.GetServerUrl(true) + fullPath.Substring(root.Length).Replace(Path.DirectorySeparatorChar, '/');
}
// create the public history url
private string MakePublicHistoryUrl(string filename, string version, string file, Boolean isServer = true)
{
var userAddress = isServer ? "&userAddress=" + HttpUtility.UrlEncode(_Default.CurUserHostAddress(HttpContext.Current.Request.UserHostAddress)) : "";
var fileUrl = new UriBuilder(_Default.GetServerUrl(isServer));
fileUrl.Path = HttpRuntime.AppDomainAppVirtualPath
+ (HttpRuntime.AppDomainAppVirtualPath.EndsWith("/") ? "" : "/")
+ "webeditor.ashx";
fileUrl.Query = "type=downloadhistory&fileName=" + HttpUtility.UrlEncode(filename)
+ "&ver=" + version + "&file=" + file
+ userAddress;
return fileUrl.ToString();
}
// create demo document
private static void Try(string type, string sample, HttpRequest request)
{
@ -496,7 +626,7 @@ namespace OnlineEditorsExample
return;
}
var demoName = (string.IsNullOrEmpty(sample) ? "new" : "sample") + ext; // create demo document name with the necessary extension
var demoPath = "assets\\document-templates\\" + (string.IsNullOrEmpty(sample) ? "new\\" : "sample\\"); // and put this file into the assets directory
var demoPath = "assets\\" + (string.IsNullOrEmpty(sample) ? "new\\" : "sample\\"); // and put this file into the assets directory
FileName = _Default.GetCorrectName(demoName); // get file name with an index if such a file name already exists
@ -522,5 +652,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

@ -1,6 +1,6 @@
/**
*
* (c) Copyright Ascensio System SIA 2024
* (c) Copyright Ascensio System SIA 2023
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -231,10 +231,6 @@ namespace ASC.Api.DocumentConverter
switch (errorCode)
{
case -9:
// public const int c_nErrorConversionOutputFormatError = -9;
errorMessage = String.Format(errorMessageTemplate, "Error conversion output format");
break;
case -8:
// public const int c_nErrorFileVKey = -8;
errorMessage = String.Format(errorMessageTemplate, "Error document VKey");

View File

@ -1,192 +0,0 @@
/**
*
* (c) Copyright Ascensio System SIA 2024
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using Newtonsoft.Json;
namespace OnlineEditorsExample
{
public class Format
{
public string Name { get; }
public string Type { get; }
public List<string> Actions { get; }
public List<string> Convert { get; }
public List<string> Mime { get; }
public Format(string name, string type, List<string> actions, List<string> convert, List<string> mime)
{
Name = name;
Type = type;
Actions = actions;
Convert = convert;
Mime = mime;
}
public string Extension()
{
return "." + Name;
}
}
public class FormatManager
{
private static List<Format> cachedFormats;
public static List<string> FillableExtensions()
{
return Fillable()
.Select(format => format.Extension())
.ToList();
}
public static List<Format> Fillable()
{
return All()
.Where(format => format.Actions.Contains("fill"))
.ToList();
}
public static List<string> ViewableExtensions()
{
return Viewable()
.Select(format => format.Extension())
.ToList();
}
public static List<Format> Viewable()
{
return All()
.Where(format => format.Actions.Contains("view"))
.ToList();
}
public static List<string> EditableExtensions()
{
return Editable()
.Select(format => format.Extension())
.ToList();
}
public static List<Format> Editable()
{
return All()
.Where(format => format.Actions.Contains("edit") || format.Actions.Contains("lossy-edit"))
.ToList();
}
public static List<string> ConvertibleExtensions()
{
return Convertible()
.Select(format => format.Extension())
.ToList();
}
public static List<Format> Convertible()
{
return All()
.Where(format => format.Actions.Contains("auto-convert"))
.ToList();
}
public static List<string> SpreadsheetExtensions()
{
return Spreadsheets()
.Select(format => format.Extension())
.ToList();
}
public static List<Format> Spreadsheets()
{
return All()
.Where(format => format.Type == "cell")
.ToList();
}
public static List<string> PresentationExtensions()
{
return Presentations()
.Select(format => format.Extension())
.ToList();
}
public static List<Format> Presentations()
{
return All()
.Where(format => format.Type == "slide")
.ToList();
}
public static List<string> DocumentExtensions()
{
return Documents()
.Select(format => format.Extension())
.ToList();
}
public static List<Format> Documents()
{
return All()
.Where(format => format.Type == "word")
.ToList();
}
public static List<string> AllExtensions()
{
return All()
.Select(format => format.Extension())
.ToList();
}
public static List<Format> All()
{
if (cachedFormats == null) {
var path = GetPath();
var lines = File.ReadLines(path, Encoding.UTF8);
var contents = string.Join(Environment.NewLine, lines);
var formats = JsonConvert.DeserializeObject<Format[]>(contents);
cachedFormats = formats.ToList();
}
return cachedFormats;
}
private static string GetPath()
{
string path = Path.Combine(GetDirectory(), "onlyoffice-docs-formats.json");
if (File.Exists(path))
{
return path;
}
else
{
throw new FileNotFoundException("The JSON file does not exist.");
}
}
private static string GetDirectory()
{
string directory = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "assets", "document-formats");
return Path.GetFullPath(directory);
}
}
}

View File

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

View File

@ -119,7 +119,6 @@
<DependentUpon>DocEditor.aspx</DependentUpon>
</Compile>
<Compile Include="DocumentConverter.cs" />
<Compile Include="FormatManager.cs" />
<Compile Include="JwtManager.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Default.aspx.cs">
@ -145,9 +144,11 @@
</ItemGroup>
<ItemGroup>
<Content Include="App_Themes\images\loader16.gif" />
<Content Include="App_Themes\images\logo.png" />
<Content Include="App_Themes\jquery-ui.css" />
<Content Include="App_Themes\stylesheet.css" />
<Content Include="DocEditor.aspx" />
<Content Include="script\jquery-1.9.0.min.js" />
<Content Include="script\jquery-ui.min.js" />
<Content Include="script\jquery.blockUI.js" />
<Content Include="script\jquery.dropdownToggle.js" />
@ -157,23 +158,17 @@
<Content Include="WebEditor.ashx" />
</ItemGroup>
<ItemGroup>
<Content Include="assets\document-formats\AUTHORS.md" />
<Content Include="assets\document-formats\CHANGELOG.md" />
<Content Include="assets\document-formats\LICENSE" />
<Content Include="assets\document-formats\onlyoffice-docs-formats.json" />
<Content Include="assets\document-formats\README.md" />
<Content Include="assets\document-templates\AUTHORS.md" />
<Content Include="assets\document-templates\LICENSE" />
<Content Include="assets\document-templates\new\new.docx" />
<Content Include="assets\document-templates\new\new.docxf" />
<Content Include="assets\document-templates\new\new.pptx" />
<Content Include="assets\document-templates\new\new.xlsx" />
<Content Include="assets\document-templates\README.md" />
<Content Include="assets\document-templates\sample\csv.csv" />
<Content Include="assets\document-templates\sample\sample.docx" />
<Content Include="assets\document-templates\sample\sample.docxf" />
<Content Include="assets\document-templates\sample\sample.pptx" />
<Content Include="assets\document-templates\sample\sample.xlsx" />
<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" />
</ItemGroup>
<PropertyGroup>

View File

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

View File

@ -1,6 +1,6 @@
/**
*
* (c) Copyright Ascensio System SIA 2024
* (c) Copyright Ascensio System SIA 2023
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -258,22 +258,6 @@ namespace OnlineEditorsExample
var action = jss.Deserialize<Dictionary<string, object>>(jss.Serialize(actions[0]));
var user = action["userid"].ToString(); // get the user id
DocEditor.CreateMeta(fileName, user, "Filling Form", userAddress); // create meta data for the forcesaved file
string formsDataUrl = fileData["formsdataurl"].ToString();
if (!string.IsNullOrEmpty(formsDataUrl))
{
string formsName = _Default.GetCorrectName(Path.GetFileNameWithoutExtension(fileName) + ".txt", userAddress);
string formsPath = _Default.StoragePath(formsName, userAddress);
var bytesForms = DownloadFile(formsDataUrl);
SaveFile(bytesForms, formsPath);
}
else
{
throw new Exception("Document editing service did not return formsDataUrl");
}
}
}
catch (Exception)

View File

@ -1,6 +1,6 @@
/**
*
* (c) Copyright Ascensio System SIA 2024
* (c) Copyright Ascensio System SIA 2023
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -30,9 +30,7 @@ namespace OnlineEditorsExample
"Can perform all actions with comments",
"The file favorite state is undefined",
"Can create files from templates using data from the editor",
"Can see the information about all users",
"Has an avatar",
"Can submit forms"
"Can see the information about all users"
};
static List<string> descr_user_2 = new List<string>()
@ -42,9 +40,7 @@ namespace OnlineEditorsExample
"Can view comments, edit his own comments and comments left by users with no group. Can remove his own comments only",
"This file is marked as favorite",
"Can create new files from the editor",
"Can see the information about users from Group2 and users who dont belong to any group",
"Has an avatar",
"Cant submit forms"
"Can see the information about users from Group2 and users who dont belong to any group"
};
static List<string> descr_user_3 = new List<string>()
@ -57,10 +53,7 @@ namespace OnlineEditorsExample
"Cant download the file",
"Cant print the file",
"Can create new files from the editor",
"Can see the information about Group2 users",
"Cant submit forms",
"Can't close history",
"Can't restore the file version"
"Can see the information about Group2 users"
};
static List<string> descr_user_0 = new List<string>()
@ -77,7 +70,6 @@ namespace OnlineEditorsExample
"Can't view chat",
"Can't protect file",
"View file without collaboration",
"Cant submit forms"
};
private static List<User> users = new List<User>() {
@ -92,9 +84,7 @@ namespace OnlineEditorsExample
null,
new List<string>(),
descr_user_1,
true,
true,
new Goback(null, false)
true
),
new User(
"uid-2",
@ -112,14 +102,12 @@ namespace OnlineEditorsExample
true,
new List<string>(),
descr_user_2,
false,
true,
new Goback("Go to Documents",null)
false
),
new User(
"uid-3",
"Hamish Mitchell",
null,
"mitchell@example.com",
"group-3",
new List<string>() { "group-2" },
new Dictionary<string,object>()
@ -132,9 +120,7 @@ namespace OnlineEditorsExample
false,
new List<string>() { "copy", "download", "print" },
descr_user_3,
false,
false,
null
false
),
new User(
"uid-0",
@ -147,9 +133,7 @@ namespace OnlineEditorsExample
null,
new List<string>() { "protect" },
descr_user_0,
false,
false,
null
false
)
};
@ -187,44 +171,6 @@ namespace OnlineEditorsExample
}
return usersData;
}
public static List<Dictionary<string, object>> getUsersInfo(string id)
{
List<Dictionary<string, object>> usersData = new List<Dictionary<string, object>>();
if(id != "uid-0"){
foreach (User user in users)
{
usersData.Add(new Dictionary<string, object>()
{
{"id", user.id},
{"name", user.name },
{"email", user.email },
{"image", user.avatar ? _Default.GetServerUrl(false) + "/App_Themes/images/"+ user.id + ".png" : null }
});
}
}
return usersData;
}
// get a list of users with their names and emails for protect
public static List<Dictionary<string, object>> getUsersForProtect(string id)
{
List<Dictionary<string, object>> usersData = new List<Dictionary<string, object>>();
foreach (User user in users)
{
if (!user.id.Equals(id) && user.name != null)
{
usersData.Add(new Dictionary<string, object>()
{
{"name", user.name },
{"email", user.email },
{"id", user.id}
});
}
}
return usersData;
}
}
public class User
@ -240,10 +186,8 @@ namespace OnlineEditorsExample
public List<string> descriptions;
public bool templates;
public List<string> userInfoGroups;
public bool avatar;
public Goback goback;
public User(string id, string name, string email, string group, List<string> reviewGroups, Dictionary<string, object> commentGroups, List<string> userInfoGroups, bool? favorite, List<string> deniedPermissions, List<string> descriptions, bool templates, bool avatar, Goback goback)
public User(string id, string name, string email, string group, List<string> reviewGroups, Dictionary<string, object> commentGroups, List<string> userInfoGroups, bool? favorite, List<string> deniedPermissions, List<string> descriptions, bool templates)
{
this.id = id;
this.name = name;
@ -256,22 +200,6 @@ namespace OnlineEditorsExample
this.descriptions = descriptions;
this.templates = templates;
this.userInfoGroups = userInfoGroups;
this.avatar = avatar;
this.goback = goback;
}
}
public class Goback
{
public string text;
public bool? blank;
public Goback(){}
public Goback(string text, bool? blank)
{
this.text = text;
this.blank = blank;
}
}
}

View File

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

View File

@ -1,6 +1,6 @@
/**
*
* (c) Copyright Ascensio System SIA 2024
* (c) Copyright Ascensio System SIA 2023
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -26,10 +26,7 @@ using System.Diagnostics;
using System.Web.Configuration;
using System.Linq;
using System.Net;
using System.Collections;
using System.Net.Sockets;
using ASC.Api.DocumentConverter;
using Newtonsoft.Json;
namespace OnlineEditorsExample
{
@ -51,15 +48,6 @@ namespace OnlineEditorsExample
case "downloadhistory":
DownloadHistory(context);
break;
case "gethistory":
GetHistory(context);
break;
case "getversiondata":
GetVersionData(context);
break;
case "restore":
Restore(context);
break;
case "convert":
Convert(context);
break;
@ -87,9 +75,6 @@ namespace OnlineEditorsExample
case "reference":
Reference(context);
break;
case "formats":
Formats(context);
break;
}
}
@ -225,22 +210,12 @@ namespace OnlineEditorsExample
context.Response.ContentType = "text/plain";
try
{
string fileName = context.Request["fileName"];
string userAddress = HttpUtility.UrlEncode(_Default.CurUserHostAddress(HttpContext.Current.Request.UserHostAddress));
var fileName = Path.GetFileName(context.Request["fileName"]);
var path = _Default.StoragePath(fileName, HttpUtility.UrlEncode(_Default.CurUserHostAddress(HttpContext.Current.Request.UserHostAddress)));
var histDir = _Default.HistoryDir(path);
if (!String.IsNullOrEmpty(fileName))
{
fileName = Path.GetFileName(fileName);
var path = _Default.StoragePath(fileName, userAddress);
var histDir = _Default.HistoryDir(path);
if (File.Exists(path)) File.Delete(path); // delete file
if (Directory.Exists(histDir)) Directory.Delete(histDir, true); // delete file history
} else
{
string userDir = _Default.StoragePath("", userAddress);
if (Directory.Exists(userDir)) Directory.Delete(userDir, true); // delete the user's directory
}
if (File.Exists(path)) File.Delete(path); // delete file
if (Directory.Exists(histDir)) Directory.Delete(histDir, true); // delete file history
context.Response.Write("{ \"success\": true }");
}
@ -289,7 +264,7 @@ namespace OnlineEditorsExample
private static void Assets(HttpContext context)
{
var fileName = Path.GetFileName(context.Request["filename"]);
var filePath = HttpRuntime.AppDomainAppPath + "assets/document-templates/sample/" + fileName;
var filePath = HttpRuntime.AppDomainAppPath + "assets/sample/" + fileName;
download(filePath, context);
}
@ -297,7 +272,7 @@ namespace OnlineEditorsExample
private static void GetCsv(HttpContext context)
{
var fileName = "csv.csv";
var filePath = HttpRuntime.AppDomainAppPath + "assets/document-templates/sample/" + fileName;
var filePath = HttpRuntime.AppDomainAppPath + "assets/sample/" + fileName;
download(filePath, context);
}
@ -358,164 +333,6 @@ namespace OnlineEditorsExample
get { return false; }
}
private static void GetHistory(HttpContext context)
{
var jss = new JavaScriptSerializer();
var fileName = context.Request["filename"];
var history = GetHistory(fileName);
context.Response.Write(jss.Serialize(history));
}
private static void GetVersionData(HttpContext context)
{
var storagePath = WebConfigurationManager.AppSettings["storage-path"];
var jss = new JavaScriptSerializer();
var fileName = context.Request["filename"];
int version;
if (!int.TryParse(context.Request["version"], out version))
{
context.Response.Write("{ \"error\": \"Version number invalid!\"}");
return;
}
var versionData = new Dictionary<string, object>();
var histDir = _Default.HistoryDir(_Default.StoragePath(fileName, null));
var lastVersion = _Default.GetFileVersion(histDir);
var verDir = _Default.VersionDir(histDir, version);
var lastVersionUri = _Default.FileUri(fileName, true);
var key = version == lastVersion
? ServiceConverter.GenerateRevisionId(_Default.CurUserHostAddress(null)
+ "/" + Path.GetFileName(lastVersionUri)
+ "/" + File.GetLastWriteTime(_Default.StoragePath(fileName, null)).GetHashCode())
: File.ReadAllText(Path.Combine(verDir, "key.txt"));
var ext = Path.GetExtension(fileName).ToLower();
versionData.Add("fileType", ext.Replace(".", ""));
versionData.Add("key", key);
var directPrevFileUrl = version == lastVersion ? _Default.FileUri(fileName, false) : MakePublicHistoryUrl(fileName, version.ToString(), "prev" + ext, false);
var prevFileUrl = version == lastVersion ? lastVersionUri : MakePublicHistoryUrl(fileName, version.ToString(), "prev" + ext);
if (Path.IsPathRooted(storagePath))
{
prevFileUrl = version == lastVersion ? DocEditor.getDownloadUrl(fileName) : DocEditor.getDownloadUrl(Directory.GetFiles(verDir, "prev.*")[0].Replace(storagePath + "\\", ""));
directPrevFileUrl = version == lastVersion ? DocEditor.getDownloadUrl(fileName, false) : DocEditor.getDownloadUrl(Directory.GetFiles(verDir, "prev.*")[0].Replace(storagePath + "\\", ""), false);
}
versionData.Add("url", prevFileUrl);
if (_Default.IsEnabledDirectUrl())
{
versionData.Add("directUrl", directPrevFileUrl); // write direct url to the data object
}
versionData.Add("version", version);
if (version > 1)
{
var prevVerDir = _Default.VersionDir(histDir, version - 1);
var prevUrl = MakePublicHistoryUrl(fileName, (version - 1).ToString(), "prev" + ext);
if (Path.IsPathRooted(storagePath))
prevUrl = DocEditor.getDownloadUrl(Directory.GetFiles(prevVerDir, "prev.*")[0].Replace(storagePath + "\\", ""));
var prevKey = File.ReadAllText(Path.Combine(prevVerDir, "key.txt"));
Dictionary<string, object> dataPrev = new Dictionary<string, object>() { // write information about previous file version to the data object
{ "fileType", ext.Replace(".", "") },
{ "key", prevKey }, // write key and url information about previous file version
{ "url", prevUrl }
};
string directPrevUrl;
if (_Default.IsEnabledDirectUrl())
{
directPrevUrl = Path.IsPathRooted(storagePath)
? DocEditor.getDownloadUrl(Directory.GetFiles(prevVerDir, "prev.*")[0].Replace(storagePath + "\\", ""), false)
: MakePublicHistoryUrl(fileName, (version - 1).ToString(), "prev" + ext, false);
dataPrev.Add("directUrl", directPrevUrl); // write direct url to the data object
}
versionData.Add("previous", dataPrev);
if (File.Exists(Path.Combine(prevVerDir, "diff.zip")))
{
var changesUrl = MakePublicHistoryUrl(fileName, (version - 1).ToString(), "diff.zip");
versionData.Add("changesUrl", changesUrl);
}
}
if (JwtManager.Enabled)
{
var token = JwtManager.Encode(versionData);
versionData.Add("token", token);
}
context.Response.Write(jss.Serialize(versionData));
}
private void Restore(HttpContext context)
{
string fileData;
try
{
using (var receiveStream = context.Request.InputStream)
using (var readStream = new StreamReader(receiveStream))
{
fileData = readStream.ReadToEnd();
if (string.IsNullOrEmpty(fileData)) return;
}
}
catch (Exception e)
{
throw new HttpException((int)HttpStatusCode.BadRequest, e.Message);
}
var jss = new JavaScriptSerializer();
var body = jss.Deserialize<Dictionary<string, object>>(fileData);
var fileName = (string)body["fileName"];
var version = (int)body["version"];
var lastVersionUri = _Default.FileUri(fileName, true);
var key = ServiceConverter.GenerateRevisionId(_Default.CurUserHostAddress(null)
+ "/" + Path.GetFileName(lastVersionUri)
+ "/" + File.GetLastWriteTime(_Default.StoragePath(fileName, null)).GetHashCode());
var histDir = _Default.HistoryDir(_Default.StoragePath(fileName, null));
var currentVersionDir = _Default.VersionDir(histDir, _Default.GetFileVersion(histDir));
var verDir = _Default.VersionDir(histDir, version);
if (!Directory.Exists(currentVersionDir)) Directory.CreateDirectory(currentVersionDir);
var ext = Path.GetExtension(fileName).ToLower();
File.Copy(_Default.StoragePath(fileName, null), Path.Combine(currentVersionDir, "prev" + ext));
File.WriteAllText(Path.Combine(currentVersionDir, "key.txt"), key);
var changesPath = Path.Combine(_Default.VersionDir(histDir, version - 1), "changes.json");
if (File.Exists(changesPath))
{
File.Copy(changesPath, Path.Combine(currentVersionDir, "changes.json"));
}
File.Copy(Path.Combine(verDir, "prev" + ext), _Default.StoragePath(fileName, null), true);
var fileInfo = new FileInfo(_Default.StoragePath(fileName, null));
fileInfo.LastWriteTimeUtc = DateTime.UtcNow;
var history = GetHistory(fileName);
context.Response.Write(jss.Serialize(history));
}
private static void DownloadHistory(HttpContext context)
{
try
@ -636,27 +453,6 @@ namespace OnlineEditorsExample
}
}
if (fileName == "" && body.ContainsKey("link"))
{
string link = body["link"].ToString();
if (!link.Contains(_Default.GetServerUrl(false)))
{
context.Response.Write(jss.Serialize(new Dictionary<string, string>() {
{ "url", link },
{ "directUrl", link }
}));
return;
}
Uri linkUri = new Uri(link);
fileName = HttpUtility.ParseQueryString(linkUri.Query).Get("fileID");
if (string.IsNullOrEmpty(fileName) || !File.Exists(_Default.StoragePath(fileName, null)))
{
context.Response.Write("{ \"error\": \"File is not exist\"}");
return;
}
}
if (fileName == "")
{
try
@ -685,9 +481,6 @@ namespace OnlineEditorsExample
var data = new Dictionary<string, object>() {
{ "fileType", (Path.GetExtension(fileName) ?? "").ToLower().Trim('.') },
{ "key", ServiceConverter.GenerateRevisionId(_Default.CurUserHostAddress(null)
+ "/" + Path.GetFileName(_Default.FileUri(fileName, true))
+ "/" + File.GetLastWriteTime(_Default.StoragePath(fileName, null)).GetHashCode()) },
{ "url", DocEditor.getDownloadUrl(fileName)},
{ "directUrl", directUrl ? DocEditor.getDownloadUrl(fileName, false) : null},
{ "referenceData", new Dictionary<string, string>()
@ -700,8 +493,7 @@ namespace OnlineEditorsExample
{"instanceId", _Default.GetServerUrl(false) }
}
},
{ "path", fileName },
{ "link", _Default.GetServerUrl(false) + "doceditor.aspx?fileID=" + fileName }
{ "path", fileName }
};
if (JwtManager.Enabled)
@ -712,104 +504,5 @@ namespace OnlineEditorsExample
context.Response.Write(jss.Serialize(data));
}
// get the document history
private static Dictionary<string, object> GetHistory(string fileName)
{
var jss = new JavaScriptSerializer();
var histDir = _Default.HistoryDir(_Default.StoragePath(fileName, null));
var history = new Dictionary<string, object>();
var currentVersion = _Default.GetFileVersion(histDir);
var currentFileUri = _Default.FileUri(fileName, true);
var currentKey = ServiceConverter.GenerateRevisionId(_Default.CurUserHostAddress(null)
+ "/" + Path.GetFileName(currentFileUri)
+ "/" + File.GetLastWriteTime(_Default.StoragePath(fileName, null)).GetHashCode());
var versionList = new List<Dictionary<string, object>>();
for (var versionNum = 1; versionNum <= currentVersion; versionNum++)
{
var versionObj = new Dictionary<string, object>();
var verDir = _Default.VersionDir(histDir, versionNum); // get the path to the given file version
var key = versionNum == currentVersion ? currentKey : File.ReadAllText(Path.Combine(verDir, "key.txt")); // get document key
versionObj.Add("key", key);
versionObj.Add("version", versionNum);
var changesPath = Path.Combine(_Default.VersionDir(histDir, versionNum - 1), "changes.json");
if (versionNum == 1 || !File.Exists(changesPath)) // check if the version number is equal to 1
{
var infoPath = Path.Combine(histDir, "createdInfo.json"); // get meta data of this file
if (File.Exists(infoPath))
{
var info = jss.Deserialize<Dictionary<string, object>>(File.ReadAllText(infoPath));
versionObj.Add("created", info["created"]); // write meta information to the object (user information and creation date)
versionObj.Add("user", new Dictionary<string, object>()
{
{ "id", info["id"] },
{ "name", info["name"] },
});
}
}
else if (versionNum > 1) // check if the version number is greater than 1 (the file was modified)
{
// get the path to the changes.json file
var changes = jss.Deserialize<Dictionary<string, object>>(File.ReadAllText(changesPath));
var changesArray = (ArrayList)changes["changes"];
var change = changesArray.Count > 0
? (Dictionary<string, object>)changesArray[0]
: new Dictionary<string, object>();
// write information about changes to the object
versionObj.Add("changes", change.Count > 0 ? changes["changes"] : null);
versionObj.Add("serverVersion", changes["serverVersion"]);
versionObj.Add("created", change.Count > 0 ? change["created"] : null);
versionObj.Add("user", change.Count > 0 ? change["user"] : null);
}
versionList.Add(versionObj);
}
history.Add("currentVersion", currentVersion);
history.Add("history", versionList);
return history;
}
// create the public history url
private static string MakePublicHistoryUrl(string filename, string version, string file, Boolean isServer = true)
{
var userAddress = isServer ? "&userAddress=" + HttpUtility.UrlEncode(_Default.CurUserHostAddress(HttpContext.Current.Request.UserHostAddress)) : "";
var fileUrl = new UriBuilder(_Default.GetServerUrl(isServer));
fileUrl.Path = HttpRuntime.AppDomainAppVirtualPath
+ (HttpRuntime.AppDomainAppVirtualPath.EndsWith("/") ? "" : "/")
+ "webeditor.ashx";
fileUrl.Query = "type=downloadhistory&fileName=" + HttpUtility.UrlEncode(filename)
+ "&ver=" + version + "&file=" + file
+ userAddress;
return fileUrl.ToString();
}
// return all the supported formats
private static void Formats(HttpContext context)
{
try
{
Dictionary<string, object> data = new Dictionary<string, object>
{
{ "formats", FormatManager.All() }
};
context.Response.ContentType = "application/json";
var jss = new JavaScriptSerializer();
context.Response.Write(jss.Serialize(data));
}
catch (Exception e)
{
context.Response.Write("{ \"error\": \"" + e.Message + "\"}");
}
}
}
}

View File

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

View File

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

View File

@ -1,6 +1,6 @@
/**
*
* (c) Copyright Ascensio System SIA 2024
* (c) Copyright Ascensio System SIA 2023
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -17,27 +17,6 @@
*/
var directUrl;
var formatManager;
window.onload = function () {
fetch("webeditor.ashx?type=formats")
.then((response) => response.json())
.then((data) => {
if (data.formats) {
let formats = [];
data.formats.forEach(format => {
formats.push(new Format(
format.Name,
format.Type,
format.Actions,
format.Convert,
format.Mime
));
});
formatManager = new FormatManager(formats);
}
})
}
if (typeof jQuery != "undefined") {
jq = jQuery.noConflict();
@ -108,7 +87,7 @@ if (typeof jQuery != "undefined") {
});
var timer = null;
var checkConvert = function (filePass, fileType) {
var checkConvert = function (filePass) {
filePass = filePass ? filePass : null;
if (timer != null) {
clearTimeout(timer);
@ -124,7 +103,7 @@ if (typeof jQuery != "undefined") {
var posExt = fileName.lastIndexOf('.');
posExt = 0 <= posExt ? fileName.substring(posExt).trim().toLowerCase() : '';
if (!formatManager.isAutoConvertible(posExt)) {
if (ConverExtList.indexOf(posExt) == -1) {
jq("#step2").addClass("done").removeClass("current");
loadScripts();
return;
@ -137,7 +116,7 @@ if (typeof jQuery != "undefined") {
contentType: "text/xml",
type: "post",
dataType: "json",
data: JSON.stringify({ filename: fileName, filePass: filePass, fileExt: fileType }),
data: JSON.stringify({ filename: fileName, filePass: filePass }),
url: requestAddress,
complete: function (data) {
var responseText = data.responseText;
@ -153,12 +132,6 @@ if (typeof jQuery != "undefined") {
}
return;
} else {
if (response.error.includes("Error conversion output format")) {
jq("#select-file-type").removeClass("invisible");
jq("#step2").removeClass("current");
jq("#hiddenFileName").attr("placeholder", filePass);
return;
}
jq(".current").removeClass("current");
jq(".step:not(.done)").addClass("error");
jq("#mainProgress .error-message").show().find("span").text(response.error);
@ -170,7 +143,7 @@ if (typeof jQuery != "undefined") {
jq("#hiddenFileName").val(response.filename);
if (response.step && response.step < 100) {
checkConvert(filePass, fileType);
checkConvert(filePass);
} else {
jq("#step2").addClass("done").removeClass("current");
loadScripts();
@ -205,10 +178,10 @@ if (typeof jQuery != "undefined") {
jq("#beginView, #beginEmbedded").removeClass("disable");
var fileName = jq("#hiddenFileName").val();
var posExt = fileName.lastIndexOf('.') + 1;
var posExt = fileName.lastIndexOf('.');
posExt = 0 <= posExt ? fileName.substring(posExt).trim().toLowerCase() : '';
if (formatManager.isEditable(posExt) || formatManager.isFillable(posExt)) {
if (EditedExtList.indexOf(posExt) != -1 || FillFormExtList.indexOf(posExt) != -1) {
jq("#beginEdit").removeClass("disable");
}
};
@ -240,15 +213,6 @@ if (typeof jQuery != "undefined") {
});
};
jq(document).on("click", ".file-type:not(.disable)", function () {
const currentElement = jq(this);
var fileType = currentElement.attr("data");
var filePass = jq("#hiddenFileName").attr("placeholder");
jq('.file-type').addClass(["disable", "pale"]);
currentElement.removeClass("pale");
checkConvert(filePass, fileType);
});
jq(document).on("click", "#enterPass", function () {
var filePass = jq("#filePass").val();
if (filePass) {
@ -329,24 +293,6 @@ if (typeof jQuery != "undefined") {
});
});
jq(document).on("click", ".clear-all", function () {
if (confirm("Delete all the files?")) {
var requestAddress = "webeditor.ashx"
+ "?type=remove";
jq.ajax({
async: true,
contentType: "text/xml",
url: requestAddress,
complete: function (data) {
if (JSON.parse(data.responseText).success) {
window.location.reload(true);
}
}
});
}
});
function showUserTooltip (isMobile) {
if ( jq("div#portal-info").is(":hidden") ) {
jq("div#portal-info").show();

View File

@ -1,12 +1,15 @@
<?xml version="1.0" encoding="utf-8" ?>
<appSettings>
<clear />
<add key="version" value="1.8.0"/>
<add key="version" value="1.6.0"/>
<add key="filesize-max" value="52428800"/>
<add key="storage-path" value=""/>
<add key="filename-max" value="50"/>
<add key="files.docservice.fillform-docs" value=".docx|.oform"/>
<add key="files.docservice.viewed-docs" value=".djvu|.oxps|.pdf|.xps"/>
<add key="files.docservice.edited-docs" value=".csv|.docm|.docx|.docxf|.dotm|.dotx|.epub|.fb2|.html|.odp|.ods|.odt|.otp|.ots|.ott|.potm|.potx|.ppsm|.ppsx|.pptm|.pptx|.rtf|.txt|.xlsm|.xlsx|.xltm|.xltx"/>
<add key="files.docservice.convert-docs" value=".doc|.dot|.dps|.dpt|.epub|.et|.ett|.fb2|.fodp|.fods|.fodt|.htm|.html|.mht|.mhtml|.odp|.ods|.odt|.otp|.ots|.ott|.pot|.pps|.ppt|.rtf|.stw|.sxc|.sxi|.sxw|.wps|.wpt|.xls|.xlsb|.xlt|.xml"/>
<add key="files.docservice.timeout" value="120000" />
<add key="files.docservice.secret" value="" />
<add key="files.docservice.header" value="Authorization" />
@ -14,7 +17,7 @@
<add key="files.docservice.token.useforrequest" value="true" />
<add key="files.docservice.languages" value="en:English|ar:Arabic|hy:Armenian|az:Azerbaijani|eu:Basque|be:Belarusian|bg:Bulgarian|ca:Catalan|zh:Chinese (Simplified)|zh-TW:Chinese (Traditional)|cs:Czech|da:Danish|nl:Dutch|en-GB:English (United Kingdom)|fi:Finnish|fr:French|gl:Galego|de:German|el:Greek|hu:Hungarian|id:Indonesian|it:Italian|ja:Japanese|ko:Korean|lo:Lao|lv:Latvian|ms:Malay (Malaysia)|no:Norwegian|pl:Polish|pt:Portuguese (Brazil)|pt-PT:Portuguese (Portugal)|ro:Romanian|ru:Russian|sr-Latn-RS:Serbian|si:Sinhala (Sri Lanka)|sk:Slovak|sl:Slovenian|es:Spanish|sv:Swedish|tr:Turkish|uk:Ukrainian|vi:Vietnamese|aa-AA: Test Language"/>
<add key="files.docservice.languages" value="en:English|hy:Armenian|az:Azerbaijani|eu:Basque|be:Belarusian|bg:Bulgarian|ca:Catalan|zh:Chinese (Simplified)|zh-TW:Chinese (Traditional)|cs:Czech|da:Danish|nl:Dutch|fi:Finnish|fr:French|gl:Galego|de:German|el:Greek|hu:Hungarian|id:Indonesian|it:Italian|ja:Japanese|ko:Korean|lo:Lao|lv:Latvian|ms:Malay (Malaysia)|no:Norwegian|pl:Polish|pt:Portuguese (Brazil)|pt-PT:Portuguese (Portugal)|ro:Romanian|ru:Russian|si:Sinhala (Sri Lanka)|sk:Slovak|sl:Slovenian|es:Spanish|sv:Swedish|tr:Turkish|uk:Ukrainian|vi:Vietnamese|aa-AA: Test Language"/>
<add key="files.docservice.url.site" value="http://documentserver/"/>

View File

@ -49,6 +49,10 @@ ModelMapper - ModelMapper is an intelligent object mapping library that automa
License: Apache 2.0
License File modelmapper.license
Prime JWT - is intended to be fast and easy to use. Prime JWT has a single external dependency on Jackson. (https://github.com/ws-apps/prime-jwt/blob/master/LICENSE)
License: Apache 2.0
License File: prime-jwt.license
Spring Boot - Helps create Spring-powered, production-grade applications and services. Has external dependencies on Spring Framework. (https://github.com/spring-projects/spring-boot/blob/main/LICENSE.txt)
License: Apache 2.0
License File: spring-boot.license

View File

@ -20,7 +20,7 @@ See the detailed guide to learn how to install Document Server [for Windows](htt
Download the [Java-Spring example](https://api.onlyoffice.com/editors/demopreview) from our site.
To connect the editors to your website, specify the path to the editors installation, server port and the path to the storage folder in the *src/main/resources/application.properties* file:
To connect the editors to your website, specify the path to the editors installation, server port and the path to the storage folder in the *\src\main\resources\application.properties* file:
```
files.storage=
@ -128,18 +128,22 @@ See the detailed guide to learn how to install Document Server [for Linux](https
### Step 2. Install the prerequisites and run the website with the editors
1. Install **Java** following the instructions [here](https://docs.oracle.com/en/java/javase/20/install/installation-jdk-linux-platforms.html#GUID-737A84E4-2EFF-4D38-8E60-3E29D1B884B8).
1. Install **Java**:
```
sudo add-apt-repository ppa:webupd8team/java sudo apt-get update sudo apt-get install oracle-java11-installer
```
2. Download the archive with the Java-Spring example and unpack the archive or clone git repository:
a) archive with Java-Spring:
```
wget https://api.onlyoffice.com/app_data/editor/Java.Spring.Example.zip
wget https://api.onlyoffice.com/app_data/editor/Java%20Spring%20Example.zip
```
```
unzip Java.Spring.Example.zip
unzip Java\ Spring\ Example.zip
```
b) git repository:
```
@ -158,7 +162,7 @@ See the detailed guide to learn how to install Document Server [for Linux](https
```
cd document-server-integration/web/documentserver-example/java-spring
```
4. Edit the *src/main/resources/application.properties* configuration file. Specify the name of your local server with the ONLYOFFICE Document Server installed.
4. Edit the *application.properties* configuration file. Specify the name of your local server with the ONLYOFFICE Document Server installed.
```
nano src/main/resources/application.properties
@ -206,51 +210,13 @@ Make sure that the Document Server has access to the server with the example ins
## For Docker
### Step 1. Install ONLYOFFICE Docs
Download and install ONLYOFFICE Docs (packaged as Document Server).
See the detailed guide to learn how to install Document Server [for Docker](https://helpcenter.onlyoffice.com/installation/docs-developer-install-docker.aspx).
### Step 2. Install the prerequisites and run the website with the editors
1. Install **Java** following the instructions [here](https://docs.oracle.com/en/java/javase/20/install/installation-jdk-linux-platforms.html#GUID-737A84E4-2EFF-4D38-8E60-3E29D1B884B8).
2. Download the archive with the Java-Spring example and unpack the archive or clone git repository:
a) archive with Java-Spring:
```
wget https://api.onlyoffice.com/app_data/editor/Java.Spring.Example.zip
```
```
unzip Java.Spring.Example.zip
```
b) git repository:
```
git clone https://github.com/ONLYOFFICE/document-server-integration.git
```
3. Change the current directory for the project directory:
a) from archive
```
cd Java\ Spring\ Example/
```
b) from git repository
```
cd document-server-integration/web/documentserver-example/java-spring
```
4. Edit the *src/main/resources/application.properties* configuration file. Specify the name of your local server with the ONLYOFFICE Document Server installed:
1. Edit the *application.properties* configuration file. Specify the name of your local server with the ONLYOFFICE Document Server installed ([installation instructions](https://helpcenter.onlyoffice.com/installation/docs-developer-install-docker.aspx)).
```
nano src/main/resources/application.properties
```
5. Edit the following lines:
2. Edit the following lines:
```
files.storage=
@ -260,23 +226,17 @@ See the detailed guide to learn how to install Document Server [for Docker](http
where the **documentserver** is the name of the server with the ONLYOFFICE Docs installed, **port** is any available port and **files.storage** is the path where files will be created and stored (in the project folder by default). You can set an absolute path.
6. Run the next command in the java example directory:
3. Run the next command in the java example directory:
```
docker-compose up
```
7. Open your browser using **server.address** and **server.port**:
4. Open your browser using **server.address** and **server.port**:
```
http://server.address:server.port/
```
### Step 3. Check accessibility
In case the example and Document Server are installed on different computers, make sure that your server with the example installed has access to the Document Server with the address which you specify instead of **documentserver** in the configuration files.
Make sure that the Document Server has access to the server with the example installed with the address which you specify instead of **example.com** in the configuration files.
## Important security info
Please keep in mind the following security aspects when you are using test examples:

View File

@ -49,6 +49,10 @@ ModelMapper - ModelMapper is an intelligent object mapping library that automa
License: Apache 2.0
License File modelmapper.license
Prime JWT - is intended to be fast and easy to use. Prime JWT has a single external dependency on Jackson. (https://github.com/ws-apps/prime-jwt/blob/master/LICENSE)
License: Apache 2.0
License File: prime-jwt.license
Spring Boot - Helps create Spring-powered, production-grade applications and services. Has external dependencies on Spring Framework. (https://github.com/spring-projects/spring-boot/blob/main/LICENSE.txt)
License: Apache 2.0
License File: spring-boot.license

View File

@ -0,0 +1,201 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "{}"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright {yyyy} {name of copyright owner}
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
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.

View File

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

View File

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

View File

@ -1,6 +1,6 @@
/**
*
* (c) Copyright Ascensio System SIA 2024
* (c) Copyright Ascensio System SIA 2023
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -19,7 +19,6 @@
package com.onlyoffice.integration;
import com.onlyoffice.integration.documentserver.serializers.FilterState;
import com.onlyoffice.integration.entities.Goback;
import com.onlyoffice.integration.services.UserServices;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@ -47,8 +46,7 @@ public class ExampleData {
"Can't rename files from the editor",
"Can't view chat",
"Can't protect file",
"View file without collaboration",
"Cant submit forms"
"View file without collaboration"
);
// the description for user 1
@ -60,9 +58,7 @@ public class ExampleData {
"The file favorite state is undefined",
"Can create a file from a template with data from the editor",
"Can see the information about all users",
"Can view chat",
"Has an avatar",
"Can submit forms"
"Can view chat"
);
// the description for user 2
@ -75,9 +71,7 @@ public class ExampleData {
"This file is favorite",
"Can create a file from an editor",
"Can see the information about users from Group2 and users who dont belong to any group",
"Can view chat",
"Has an avatar",
"Cant submit forms"
"Can view chat"
);
// the description for user 3
@ -92,33 +86,30 @@ public class ExampleData {
"He cant print the file",
"Can create a file from an editor",
"Can see the information about Group2 users",
"Can view chat",
"Cant submit forms",
"Can't close history",
"Can't restore the file version"
"Can view chat"
);
// create user 1 with the specified parameters
userService.createUser("John Smith", "smith@example.com", descriptionUserFirst,
"", List.of(FilterState.NULL.toString()), List.of(FilterState.NULL.toString()),
List.of(FilterState.NULL.toString()), List.of(FilterState.NULL.toString()),
List.of(FilterState.NULL.toString()), null, true, true, true, new Goback(null, false));
List.of(FilterState.NULL.toString()), null, true, true);
// create user 2 with the specified parameters
userService.createUser("Mark Pottato", "pottato@example.com", descriptionUserSecond,
"group-2", List.of("", "group-2"), List.of(FilterState.NULL.toString()),
List.of("group-2", ""), List.of("group-2"), List.of("group-2", ""), true, true,
true, true, new Goback("Go to Documents", null));
true);
// create user 3 with the specified parameters
userService.createUser("Hamish Mitchell", null, descriptionUserThird,
userService.createUser("Hamish Mitchell", "mitchell@example.com", descriptionUserThird,
"group-3", List.of("group-2"), List.of("group-2", "group-3"), List.of("group-2"),
new ArrayList<>(), List.of("group-2"), false, true, true, false, null);
new ArrayList<>(), List.of("group-2"), false, true, true);
// create user 0 with the specified parameters
userService.createUser("Anonymous", null, descriptionUserZero, "",
List.of(FilterState.NULL.toString()), List.of(FilterState.NULL.toString()),
List.of(FilterState.NULL.toString()), List.of(FilterState.NULL.toString()),
new ArrayList<>(), null, false, false, false, null);
new ArrayList<>(), null, false, false);
}
}

View File

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

View File

@ -1,6 +1,6 @@
/**
*
* (c) Copyright Ascensio System SIA 2024
* (c) Copyright Ascensio System SIA 2023
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -20,17 +20,6 @@ package com.onlyoffice.integration;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.onlyoffice.integration.documentserver.storage.FileStoragePathBuilder;
import com.onlyoffice.manager.document.DocumentManager;
import com.onlyoffice.manager.request.DefaultRequestManager;
import com.onlyoffice.manager.request.RequestManager;
import com.onlyoffice.manager.security.DefaultJwtManager;
import com.onlyoffice.manager.security.JwtManager;
import com.onlyoffice.manager.settings.SettingsManager;
import com.onlyoffice.manager.url.UrlManager;
import com.onlyoffice.service.command.CommandService;
import com.onlyoffice.service.command.DefaultCommandService;
import com.onlyoffice.service.convert.ConvertService;
import com.onlyoffice.service.convert.DefaultConvertService;
import org.json.simple.parser.JSONParser;
import org.modelmapper.ModelMapper;
import org.modelmapper.convention.MatchingStrategies;
@ -41,15 +30,23 @@ import org.springframework.context.annotation.Configuration;
import javax.annotation.PostConstruct;
import com.onlyoffice.integration.documentserver.util.SSLUtils;
@Configuration
public class IntegrationConfiguration {
@Value("${files.storage}")
private String storageAddress;
@Value("${files.docservice.verify-peer-off}")
private String verifyPerrOff;
@Autowired
private FileStoragePathBuilder storagePathBuilder;
@Autowired
private SSLUtils ssl;
@Bean
public ModelMapper mapper() { // create the model mapper
ModelMapper mapper = new ModelMapper();
@ -70,34 +67,21 @@ public class IntegrationConfiguration {
@PostConstruct
public void init() { // initialize the storage path builder
storagePathBuilder.configure(storageAddress.isBlank() ? null : storageAddress);
if (!verifyPerrOff.isEmpty()) {
try {
if (verifyPerrOff.equals("true")) {
ssl.turnOffSslChecking(); //the certificate will be ignored
} else {
ssl.turnOnSslChecking(); //the certificate will be verified
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
@Bean
public ObjectMapper objectMapper() { // create the object mapper
return new ObjectMapper();
}
@Bean
public JwtManager jwtManager(final SettingsManager settingsManager) {
return new DefaultJwtManager(settingsManager);
}
@Bean
public RequestManager requestManager(final UrlManager urlManager, final JwtManager jwtManager,
final SettingsManager settingsManager) {
return new DefaultRequestManager(urlManager, jwtManager, settingsManager);
}
@Bean
public ConvertService convertService(final DocumentManager documentManager, final UrlManager urlManager,
final RequestManager requestManager,
final SettingsManager settingsManager) {
return new DefaultConvertService(documentManager, urlManager, requestManager, settingsManager);
}
@Bean
public CommandService commandService(final RequestManager requestManager) {
return new DefaultCommandService(requestManager);
}
}

View File

@ -1,6 +1,6 @@
/**
*
* (c) Copyright Ascensio System SIA 2024
* (c) Copyright Ascensio System SIA 2023
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -20,22 +20,18 @@ package com.onlyoffice.integration.controllers;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.onlyoffice.integration.documentserver.managers.history.HistoryManager;
import com.onlyoffice.integration.documentserver.managers.jwt.JwtManager;
import com.onlyoffice.integration.documentserver.models.enums.Action;
import com.onlyoffice.integration.documentserver.storage.FileStoragePathBuilder;
import com.onlyoffice.integration.dto.Mentions;
import com.onlyoffice.integration.dto.Protect;
import com.onlyoffice.integration.dto.UserInfo;
import com.onlyoffice.integration.entities.User;
import com.onlyoffice.integration.sdk.manager.UrlManager;
import com.onlyoffice.integration.sdk.service.ConfigService;
import com.onlyoffice.integration.dto.Mentions;
import com.onlyoffice.integration.documentserver.models.enums.Type;
import com.onlyoffice.integration.documentserver.models.filemodel.FileModel;
import com.onlyoffice.integration.services.UserServices;
import com.onlyoffice.manager.security.JwtManager;
import com.onlyoffice.manager.settings.SettingsManager;
import com.onlyoffice.model.documenteditor.Config;
import com.onlyoffice.model.documenteditor.config.document.Type;
import com.onlyoffice.model.settings.SettingsConstants;
import com.onlyoffice.integration.services.configurers.FileConfigurer;
import com.onlyoffice.integration.services.configurers.wrappers.DefaultFileWrapper;
import lombok.SneakyThrows;
import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
@ -59,6 +55,12 @@ import static com.onlyoffice.integration.documentserver.util.Constants.ANONYMOUS
@Controller
public class EditorController {
@Value("${files.docservice.url.site}")
private String docserviceSite;
@Value("${files.docservice.url.api}")
private String docserviceApiUrl;
@Value("${files.docservice.languages}")
private String langs;
@ -71,17 +73,14 @@ public class EditorController {
@Autowired
private UserServices userService;
@Autowired
private HistoryManager historyManager;
@Autowired
private ObjectMapper objectMapper;
@Autowired
private SettingsManager settingsManager;
@Autowired
private ConfigService configService;
@Autowired
private UrlManager urlManager;
private FileConfigurer<DefaultFileWrapper> fileConfigurer;
@GetMapping(path = "${url.editor}")
// process request to open the editor page
@ -95,18 +94,16 @@ public class EditorController {
@CookieValue(value = "ulang") final String lang,
final Model model) throws JsonProcessingException {
Action action = Action.edit;
Type type = Type.DESKTOP;
Type type = Type.desktop;
Locale locale = new Locale("en");
if (actionParam != null) {
action = Action.valueOf(actionParam);
}
if (typeParam != null) {
type = Type.valueOf(typeParam.toUpperCase());
type = Type.valueOf(typeParam);
}
settingsManager.setSetting(SettingsConstants.DIRECT_URL, String.valueOf(directUrl));
List<String> langsAndKeys = Arrays.asList(langs.split("\\|"));
for (String langAndKey : langsAndKeys) {
String[] couple = langAndKey.split(":");
@ -123,43 +120,43 @@ public class EditorController {
return "index.html";
}
Config config = configService.createConfig(
fileName,
action,
type
User user = optionalUser.get();
// get file model with the default file parameters
FileModel fileModel = fileConfigurer.getFileModel(
DefaultFileWrapper
.builder()
.fileName(fileName)
.type(type)
.lang(locale.toLanguageTag())
.action(action)
.user(user)
.actionData(actionLink)
.isEnableDirectUrl(directUrl)
.build()
);
JSONObject actionData = null;
// add attributes to the specified model
// add file model with the default parameters to the original model
model.addAttribute("model", fileModel);
if (actionLink != null && !actionLink.isEmpty()) {
actionData = new JSONObject(actionLink);
}
config.getEditorConfig().setActionLink(actionData);
config.getEditorConfig().setLang(locale.toLanguageTag());
model.addAttribute("model", config);
// get file history and add it to the model
model.addAttribute("fileHistory", historyManager.getHistory(fileModel.getDocument()));
// create the document service api URL and add it to the model
model.addAttribute("docserviceApiUrl", urlManager.getDocumentServerApiUrl());
model.addAttribute("docserviceApiUrl", docserviceSite + docserviceApiUrl);
// get an image and add it to the model
model.addAttribute("dataInsertImage", getInsertImage(directUrl));
// get a document for comparison and add it to the model
model.addAttribute("dataDocument", getCompareFile(directUrl));
model.addAttribute("dataCompareFile", getCompareFile(directUrl));
// get recipients data for mail merging and add it to the model
model.addAttribute("dataSpreadsheet", getSpreadsheet(directUrl));
model.addAttribute("dataMailMergeRecipients", getMailMerge(directUrl));
// get user data for mentions and add it to the model
model.addAttribute("usersForMentions", getUserMentions(uid));
model.addAttribute("usersInfo", getUsersInfo(uid));
// get user data for protect and add it to the model
model.addAttribute("usersForProtect", getUserProtect(uid));
return "editor.html";
}
@ -179,48 +176,18 @@ public class EditorController {
return usersForMentions;
}
private List<UserInfo> getUsersInfo(final String uid) { // get user data for mentions
List<UserInfo> usersInfo = new ArrayList<>();
if (uid != null && !uid.equals("4")) {
List<User> list = userService.findAll();
for (User u : list) {
String image = u.getAvatar() ? storagePathBuilder.getServerUrl(true) + "/css/img/uid-"
+ u.getId() + ".png" : null;
usersInfo.add(new UserInfo(u.getId(), u.getName(), u.getEmail(), image));
}
}
return usersInfo;
}
private List<Protect> getUserProtect(final String uid) { // get user data for protect
List<Protect> usersForProtect = new ArrayList<>();
if (uid != null && !uid.equals("4")) {
List<User> list = userService.findAll();
for (User u : list) {
if (u.getId() != Integer.parseInt(uid) && u.getId() != ANONYMOUS_USER_ID) {
// user data includes user names, IDs and emails
usersForProtect.add(new Protect(u.getId(), u.getName(), u.getEmail()));
}
}
}
return usersForProtect;
}
@SneakyThrows
private String getInsertImage(final Boolean directUrl) { // get an image that will be inserted into the document
Map<String, Object> dataInsertImage = new HashMap<>();
dataInsertImage.put("fileType", "svg");
dataInsertImage.put("url", storagePathBuilder.getServerUrl(true) + "/css/img/logo.svg");
dataInsertImage.put("fileType", "png");
dataInsertImage.put("url", storagePathBuilder.getServerUrl(true) + "/css/img/logo.png");
if (directUrl) {
dataInsertImage.put("directUrl", storagePathBuilder
.getServerUrl(false) + "/css/img/logo.svg");
.getServerUrl(false) + "/css/img/logo.png");
}
// check if the document token is enabled
if (settingsManager.isSecurityEnabled()) {
if (jwtManager.tokenEnabled()) {
// create token from the dataInsertImage object
dataInsertImage.put("token", jwtManager.createToken(dataInsertImage));
@ -233,40 +200,40 @@ public class EditorController {
// get a document that will be compared with the current document
@SneakyThrows
private String getCompareFile(final Boolean directUrl) {
Map<String, Object> dataDocument = new HashMap<>();
dataDocument.put("fileType", "docx");
dataDocument.put("url", storagePathBuilder.getServerUrl(true) + "/assets?name=sample.docx");
Map<String, Object> dataCompareFile = new HashMap<>();
dataCompareFile.put("fileType", "docx");
dataCompareFile.put("url", storagePathBuilder.getServerUrl(true) + "/assets?name=sample.docx");
if (directUrl) {
dataDocument.put("directUrl", storagePathBuilder
dataCompareFile.put("directUrl", storagePathBuilder
.getServerUrl(false) + "/assets?name=sample.docx");
}
// check if the document token is enabled
if (settingsManager.isSecurityEnabled()) {
if (jwtManager.tokenEnabled()) {
// create token from the dataDocument object
dataDocument.put("token", jwtManager.createToken(dataDocument));
// create token from the dataCompareFile object
dataCompareFile.put("token", jwtManager.createToken(dataCompareFile));
}
return objectMapper.writeValueAsString(dataDocument);
return objectMapper.writeValueAsString(dataCompareFile);
}
@SneakyThrows
private String getSpreadsheet(final Boolean directUrl) {
Map<String, Object> dataSpreadsheet = new HashMap<>(); // get recipients data for mail merging
dataSpreadsheet.put("fileType", "csv");
dataSpreadsheet.put("url", storagePathBuilder.getServerUrl(true) + "/csv");
private String getMailMerge(final 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");
if (directUrl) {
dataSpreadsheet.put("directUrl", storagePathBuilder.getServerUrl(false) + "/csv");
dataMailMergeRecipients.put("directUrl", storagePathBuilder.getServerUrl(false) + "/csv");
}
// check if the document token is enabled
if (settingsManager.isSecurityEnabled()) {
if (jwtManager.tokenEnabled()) {
// create token from the dataSpreadsheet object
dataSpreadsheet.put("token", jwtManager.createToken(dataSpreadsheet));
// create token from the dataMailMergeRecipients object
dataMailMergeRecipients.put("token", jwtManager.createToken(dataMailMergeRecipients));
}
return objectMapper.writeValueAsString(dataSpreadsheet);
return objectMapper.writeValueAsString(dataMailMergeRecipients);
}
}

View File

@ -1,6 +1,6 @@
/**
*
* (c) Copyright Ascensio System SIA 2024
* (c) Copyright Ascensio System SIA 2023
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -21,40 +21,25 @@ package com.onlyoffice.integration.controllers;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.onlyoffice.integration.documentserver.managers.history.HistoryManager;
import com.onlyoffice.integration.documentserver.callbacks.CallbackHandler;
import com.onlyoffice.integration.documentserver.managers.jwt.JwtManager;
import com.onlyoffice.integration.documentserver.storage.FileStorageMutator;
import com.onlyoffice.integration.documentserver.storage.FileStoragePathBuilder;
import com.onlyoffice.integration.dto.Converter;
import com.onlyoffice.integration.dto.Reference;
import com.onlyoffice.integration.dto.Rename;
import com.onlyoffice.integration.dto.Restore;
import com.onlyoffice.integration.dto.SaveAs;
import com.onlyoffice.integration.dto.ConvertedData;
import com.onlyoffice.integration.dto.Track;
import com.onlyoffice.integration.entities.User;
import com.onlyoffice.integration.sdk.manager.DocumentManager;
import com.onlyoffice.integration.documentserver.models.enums.DocumentType;
import com.onlyoffice.integration.services.UserServices;
import com.onlyoffice.manager.request.RequestManager;
import com.onlyoffice.manager.security.JwtManager;
import com.onlyoffice.manager.settings.SettingsManager;
import com.onlyoffice.manager.url.UrlManager;
import com.onlyoffice.model.commandservice.CommandRequest;
import com.onlyoffice.model.commandservice.CommandResponse;
import com.onlyoffice.model.commandservice.commandrequest.Command;
import com.onlyoffice.model.commandservice.commandrequest.Meta;
import com.onlyoffice.model.convertservice.ConvertRequest;
import com.onlyoffice.model.convertservice.ConvertResponse;
import com.onlyoffice.model.documenteditor.Callback;
import com.onlyoffice.model.documenteditor.config.document.ReferenceData;
import com.onlyoffice.service.command.CommandService;
import com.onlyoffice.service.convert.ConvertService;
import com.onlyoffice.service.documenteditor.callback.CallbackService;
import org.apache.http.HttpEntity;
import org.json.simple.JSONArray;
import com.onlyoffice.integration.documentserver.util.file.FileUtility;
import com.onlyoffice.integration.documentserver.util.service.ServiceConverter;
import com.onlyoffice.integration.documentserver.managers.document.DocumentManager;
import com.onlyoffice.integration.documentserver.managers.callback.CallbackManager;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.Resource;
import org.springframework.core.io.UrlResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
@ -64,31 +49,23 @@ import org.springframework.web.bind.annotation.CookieValue;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.util.UriComponents;
import org.springframework.web.util.UriComponentsBuilder;
import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.net.InetAddress;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Optional;
@ -96,6 +73,22 @@ import java.util.Optional;
@Controller
public class FileController {
@Value("${files.docservice.header}")
private String documentJwtHeader;
@Value("${filesize-max}")
private String filesizeMax;
@Value("${files.docservice.url.site}")
private String docserviceUrlSite;
@Value("${files.docservice.url.command}")
private String docserviceUrlCommand;
@Autowired
private FileUtility fileUtility;
@Autowired
private DocumentManager documentManager;
@Autowired
private JwtManager jwtManager;
@Autowired
@ -105,29 +98,18 @@ public class FileController {
@Autowired
private UserServices userService;
@Autowired
private CallbackHandler callbackHandler;
@Autowired
private ObjectMapper objectMapper;
@Autowired
private HistoryManager historyManager;
private ServiceConverter serviceConverter;
@Autowired
private DocumentManager documentManager;
@Autowired
private ConvertService convertService;
@Autowired
private RequestManager requestManager;
@Autowired
private SettingsManager settingsManager;
@Autowired
private CallbackService callbackService;
@Autowired
private CommandService commandService;
@Autowired
private UrlManager urlManager;
private CallbackManager callbackManager;
// create user metadata
private String createUserMetadata(final String uid, final String fullFileName) {
Optional<User> optionalUser = userService.findUserById(Integer.parseInt(uid)); // find a user by their ID
// get document type
String documentType = documentManager.getDocumentType(fullFileName).toString().toLowerCase();
String documentType = fileUtility.getDocumentType(fullFileName).toString().toLowerCase(); // get document type
if (optionalUser.isPresent()) {
User user = optionalUser.get();
storageMutator.createMeta(fullFileName, // create meta information with the user ID and name specified
@ -149,28 +131,6 @@ public class FileController {
.body(resource);
}
private ResponseEntity<Resource> downloadSample(final String fileName) {
String serverPath = System.getProperty("user.dir");
String contentType = "application/octet-stream";
String[] fileLocation = new String[] {serverPath, "src", "main", "resources", "assets", "document-templates",
"sample", fileName};
Path filePath = Paths.get(String.join(File.separator, fileLocation));
Resource resource;
try {
resource = new UrlResource(filePath.toUri());
if (resource.exists()) {
return ResponseEntity.ok()
.contentType(MediaType.parseMediaType(contentType))
.header(HttpHeaders.CONTENT_DISPOSITION,
"attachment; filename=\"" + resource.getFilename() + "\"")
.body(resource);
}
} catch (MalformedURLException e) {
e.printStackTrace();
}
return null;
}
// download data from the specified history file
private ResponseEntity<Resource> downloadFileHistory(final String fileName,
final String version,
@ -194,17 +154,17 @@ public class FileController {
@CookieValue("uid") final String uid) {
try {
String fullFileName = file.getOriginalFilename(); // get file name
String fileExtension = documentManager.getExtension(fullFileName); // get file extension
String fileExtension = fileUtility.getFileExtension(fullFileName); // get file extension
long fileSize = file.getSize(); // get file size
byte[] bytes = file.getBytes(); // get file in bytes
// check if the file size exceeds the maximum file size or is less than 0
if (documentManager.getMaxFileSize() < fileSize || fileSize <= 0) {
if (fileUtility.getMaxFileSize() < fileSize || fileSize <= 0) {
return "{ \"error\": \"File size is incorrect\"}"; // if so, write an error message to the response
}
// check if file extension is supported by the editor
if (documentManager.getDocumentType(fullFileName) == null) {
if (!fileUtility.getFileExts().contains(fileExtension)) {
// if not, write an error message to the response
return "{ \"error\": \"File type is not supported\"}";
@ -215,8 +175,7 @@ public class FileController {
throw new IOException("Could not update a file"); // if the file cannot be updated, an error occurs
}
fullFileName = documentManager.getBaseName(fileNamePath)
+ "." + fileExtension; // get full file name
fullFileName = fileUtility.getFileNameWithoutExtension(fileNamePath) + fileExtension; // get full file name
return createUserMetadata(uid, fullFileName); // create user metadata and return it
} catch (Exception e) {
@ -233,87 +192,80 @@ public class FileController {
@CookieValue("uid") final String uid, @CookieValue("ulang") final String lang) {
// get file name
String fileName = body.getFileName();
// get URL for downloading a file with the specified name
String fileUri = documentManager.getDownloadUrl(fileName, true);
// get file password if it exists
String filePass = body.getFilePass() != null ? body.getFilePass() : null;
// get an auto-conversion extension from the request body or set it to the ooxml extension
String conversionExtension = body.getFileExt() != null ? body.getFileExt() : "ooxml";
// get file extension
String fileExt = fileUtility.getFileExtension(fileName);
// get document type (word, cell or slide)
DocumentType type = fileUtility.getDocumentType(fileName);
// convert to .ooxml
String internalFileExt = "ooxml";
try {
// check if the file with such an extension can be converted
if (documentManager.getDefaultConvertExtension(fileName) != null) {
ConvertRequest convertRequest = ConvertRequest.builder()
.password(filePass)
.outputtype(conversionExtension)
.region(lang)
.async(true)
.build();
if (fileUtility.getConvertExts().contains(fileExt)) {
String key = serviceConverter.generateRevisionId(fileUri); // generate document key
ConvertedData response = serviceConverter // get the URL to the converted file
.getConvertedData(fileUri, fileExt, internalFileExt, key, filePass, true, lang);
ConvertResponse convertResponse = convertService.processConvert(convertRequest, fileName);
String newFileUri = response.getUri();
String newFileType = "." + response.getFileType();
if (convertResponse.getError() != null || convertResponse.getFileUrl() == null) {
return objectMapper.writeValueAsString(convertResponse);
if (newFileUri.isEmpty()) {
return "{ \"step\" : \"0\", \"filename\" : \"" + fileName + "\"}";
}
String newFileUri = convertResponse.getFileUrl();
String newFileType = convertResponse.getFileType();
/* get a file name of an internal file extension with an index if the file
with such a name already exists */
final String oldFileName = fileName;
String nameWithInternalExt = documentManager.getBaseName(fileName) + "." + newFileType;
String nameWithInternalExt = fileUtility.getFileNameWithoutExtension(fileName) + newFileType;
String correctedName = documentManager.getCorrectName(nameWithInternalExt);
fileName = requestManager.executeGetRequest(newFileUri, new RequestManager.Callback<String>() {
public String doWork(final Object response) throws IOException {
InputStream stream = ((HttpEntity) response).getContent(); // get input stream of the converted
// file
URL url = new URL(newFileUri);
java.net.HttpURLConnection connection = (java.net.HttpURLConnection) url.openConnection();
InputStream stream = connection.getInputStream(); // get input stream of the converted file
if (stream == null) {
throw new RuntimeException("Input stream is null");
}
if (stream == null) {
connection.disconnect();
throw new RuntimeException("Input stream is null");
}
// remove source file
storageMutator.deleteFile(fileName);
// remove source file
storageMutator.deleteFile(oldFileName);
// create the converted file with input stream
storageMutator.createFile(Path.of(storagePathBuilder.getFileLocation(correctedName)), stream);
return correctedName;
}
});
// create the converted file with input stream
storageMutator.createFile(Path.of(storagePathBuilder.getFileLocation(correctedName)), stream);
fileName = correctedName;
}
// create meta information about the converted file with the user ID and name specified
return createUserMetadata(uid, fileName);
} catch (Exception e) {
e.printStackTrace();
// if the operation of file converting is unsuccessful, an error occurs
return "{ \"error\": \"" + e.getMessage() + "\"}";
}
// if the operation of file converting is unsuccessful, an error occurs
return "{ \"error\": \"" + "The file can't be converted.\"}";
}
@PostMapping("/delete")
@ResponseBody
public String delete(@RequestBody final Converter body) { // delete a file
try {
String filename = body.getFileName();
boolean success = false;
String fullFileName = fileUtility.getFileName(body.getFileName()); // get full file name
if (filename != null) {
String fullFileName = documentManager.getDocumentName(filename); // get full file name
// delete a file from the storage and return the status of this operation (true or false)
boolean fileSuccess = storageMutator.deleteFile(fullFileName);
// delete a file from the storage and return the status of this operation (true or false)
boolean fileSuccess = storageMutator.deleteFile(fullFileName);
// delete file history and return the status of this operation (true or false)
boolean historySuccess = storageMutator.deleteFileHistory(fullFileName);
// delete file history and return the status of this operation (true or false)
boolean historySuccess = storageMutator.deleteFileHistory(fullFileName);
success = fileSuccess && historySuccess;
} else {
// delete the user's folder and return the boolean status
success = storageMutator.deleteUserFolder();
}
return "{ \"success\": \"" + (success) + "\"}";
return "{ \"success\": \"" + (fileSuccess && historySuccess) + "\"}";
} catch (Exception e) {
// if the operation of file deleting is unsuccessful, an error occurs
return "{ \"error\": \"" + e.getMessage() + "\"}";
@ -327,12 +279,13 @@ public class FileController {
@RequestParam("file") final String file) { // history file
try {
// check if a token is enabled or not
if (settingsManager.isSecurityEnabled()) {
String header = request.getHeader(settingsManager.getSecurityHeader());
if (jwtManager.tokenEnabled() && jwtManager.tokenUseForRequest()) {
String header = request.getHeader(documentJwtHeader == null // get the document JWT header
|| documentJwtHeader.isEmpty() ? "Authorization" : documentJwtHeader);
if (header != null && !header.isEmpty()) {
String token = header
.replace("Bearer ", ""); // token is the header without the Bearer prefix
jwtManager.verify(token); // read the token
jwtManager.readToken(token); // read the token
} else {
return null;
}
@ -350,12 +303,13 @@ public class FileController {
final String userAddress) {
try {
// check if a token is enabled or not
if (settingsManager.isSecurityEnabled() && userAddress != null) {
String header = request.getHeader(settingsManager.getSecurityHeader());
if (jwtManager.tokenEnabled() && userAddress != null && jwtManager.tokenUseForRequest()) {
String header = request.getHeader(documentJwtHeader == null // get the document JWT header
|| documentJwtHeader.isEmpty() ? "Authorization" : documentJwtHeader);
if (header != null && !header.isEmpty()) {
String token = header
.replace("Bearer ", ""); // token is the header without the Bearer prefix
jwtManager.verify(token); // read the token
jwtManager.readToken(token); // read the token
} else {
return null;
}
@ -401,12 +355,14 @@ public class FileController {
@GetMapping("/assets")
public ResponseEntity<Resource> assets(@RequestParam("name")
final String name) { // get sample files from the assests
return downloadSample(name);
String fileName = Path.of("assets", "sample", fileUtility.getFileName(name)).toString();
return downloadFile(fileName);
}
@GetMapping("/csv")
public ResponseEntity<Resource> csv() { // download a csv file
return downloadSample("csv.csv");
String fileName = Path.of("assets", "sample", "csv.csv").toString();
return downloadFile(fileName);
}
@GetMapping("/files")
@ -421,57 +377,56 @@ public class FileController {
public String track(final HttpServletRequest request, // track file changes
@RequestParam("fileName") final String fileName,
@RequestParam("userAddress") final String userAddress,
@RequestBody final Callback body) {
Callback callback;
@RequestBody final Track body) {
Track track;
try {
String bodyString = objectMapper
.writeValueAsString(body); // write the request body to the object mapper as a string
String header = request.getHeader(documentJwtHeader == null // get the request header
|| documentJwtHeader.isEmpty() ? "Authorization" : documentJwtHeader);
if (bodyString.isEmpty()) { // if the request body is empty, an error occurs
throw new RuntimeException("{\"error\":1,\"message\":\"Request payload is empty\"}");
}
String authorizationHeader = request.getHeader(settingsManager.getSecurityHeader());
callback = callbackService.verifyCallback(body, authorizationHeader);
callbackService.processCallback(callback, fileName);
JSONObject bodyCheck = jwtManager.parseBody(bodyString, header); // parse the request body
track = objectMapper.readValue(bodyCheck.toJSONString(), Track.class); // read the request body
} catch (Exception e) {
e.printStackTrace();
return e.getMessage();
}
return "{\"error\":\"0\"}";
int error = callbackHandler.handle(track, fileName);
return "{\"error\":" + error + "}";
}
@PostMapping("/saveas")
@ResponseBody
public String saveAs(@RequestBody final SaveAs body, @CookieValue("uid") final String uid) {
try {
String fileName = documentManager.getCorrectName(body.getTitle());
public String saveAs(@RequestBody final JSONObject body, @CookieValue("uid") final String uid) {
String title = (String) body.get("title");
String saveAsFileUrl = (String) body.get("url");
if (documentManager.getDocumentType(fileName) == null) {
try {
String fileName = documentManager.getCorrectName(title);
String curExt = fileUtility.getFileExtension(fileName);
if (!fileUtility.getFileExts().contains(curExt)) {
return "{\"error\":\"File type is not supported\"}";
}
String url = body.getUrl();
URL url = new URL(saveAsFileUrl);
java.net.HttpURLConnection connection = (java.net.HttpURLConnection) url.openConnection();
InputStream stream = connection.getInputStream();
url = urlManager.replaceToInnerDocumentServerUrl(url);
if (Integer.parseInt(filesizeMax) < stream.available() || stream.available() <= 0) {
return "{\"error\":\"File size is incorrect\"}";
}
storageMutator.createFile(Path.of(storagePathBuilder.getFileLocation(fileName)), stream);
createUserMetadata(uid, fileName);
return requestManager.executeGetRequest(url, new RequestManager.Callback<String>() {
@Override
public String doWork(final Object response) throws Exception {
InputStream stream = ((HttpEntity) response).getContent();
if (documentManager.getMaxFileSize() < stream.available() || stream.available() <= 0) {
return "{\"error\":\"File size is incorrect\"}";
}
storageMutator.createFile(Path.of(storagePathBuilder.getFileLocation(fileName)), stream);
createUserMetadata(uid, fileName);
return "{\"file\": \"" + fileName + "\"}";
}
});
} catch (Exception e) {
return "{\"file\": \"" + fileName + "\"}";
} catch (IOException e) {
e.printStackTrace();
return "{ \"error\" : 1, \"message\" : \"" + e.getMessage() + "\"}";
}
@ -479,19 +434,26 @@ public class FileController {
@PostMapping("/rename")
@ResponseBody
public String rename(@RequestBody final Rename body) {
CommandRequest commandRequest = CommandRequest.builder()
.key(body.getFileKey())
.c(Command.META)
.meta(Meta.builder()
.title(body.getFileName() + "." + body.getFileType())
.build())
.build();
public String rename(@RequestBody final JSONObject body) {
String newfilename = (String) body.get("newfilename");
String dockey = (String) body.get("dockey");
String origExt = "." + (String) body.get("ext");
String curExt = newfilename;
if (newfilename.indexOf(".") != -1) {
curExt = (String) fileUtility.getFileExtension(newfilename);
}
if (origExt.compareTo(curExt) != 0) {
newfilename += origExt;
}
HashMap<String, String> meta = new HashMap<>();
meta.put("title", newfilename);
try {
CommandResponse commandResponse = commandService.processCommand(commandRequest, body.getFileName());
return commandResponse.getError().getDescription();
callbackManager.commandRequest("meta", dockey, meta);
return "result ok";
} catch (Exception e) {
e.printStackTrace();
return e.getMessage();
@ -500,7 +462,7 @@ public class FileController {
@PostMapping("/reference")
@ResponseBody
public String reference(@RequestBody final Reference body) {
public String reference(@RequestBody final JSONObject body) {
try {
JSONParser parser = new JSONParser();
Gson gson = new GsonBuilder().disableHtmlEscaping().create();
@ -508,11 +470,12 @@ public class FileController {
String userAddress = "";
String fileName = "";
if (body.getReferenceData() != null) {
ReferenceData referenceData = body.getReferenceData();
if (body.containsKey("referenceData")) {
LinkedHashMap referenceDataObj = (LinkedHashMap) body.get("referenceData");
String instanceId = (String) referenceDataObj.get("instanceId");
if (referenceData.getInstanceId().equals(storagePathBuilder.getServerUrl(false))) {
JSONObject fileKey = (JSONObject) parser.parse(referenceData.getFileKey());
if (instanceId.equals(storagePathBuilder.getServerUrl(false))) {
JSONObject fileKey = (JSONObject) parser.parse((String) referenceDataObj.get("fileKey"));
userAddress = (String) fileKey.get("userAddress");
if (userAddress.equals(InetAddress.getLocalHost().getHostAddress())) {
fileName = (String) fileKey.get("fileName");
@ -520,28 +483,11 @@ public class FileController {
}
}
String link = body.getLink();
if (fileName.equals("") && link != null) {
if (!link.contains(storagePathBuilder.getServerUrl(true))) {
HashMap<String, String> data = new HashMap<>();
data.put("url", link);
data.put("directUrl", link);
return gson.toJson(data);
}
UriComponents uriComponents = UriComponentsBuilder.fromUriString(body.getLink()).build();
fileName = uriComponents.getQueryParams().getFirst("fileName");
boolean fileExists = new File(storagePathBuilder.getFileLocation(fileName)).exists();
if (!fileExists) {
return "{ \"error\": \"File is not exist\"}";
}
}
if (fileName.equals("")) {
try {
String path = (String) body.getPath();
path = path.substring(path.lastIndexOf('/') + 1);
path = path.split("\\?")[0];
String path = (String) body.get("path");
path = fileUtility.getFileName(path);
File f = new File(storagePathBuilder.getFileLocation(path));
if (f.exists()) {
fileName = path;
@ -555,6 +501,8 @@ public class FileController {
return "{ \"error\": \"File not found\"}";
}
boolean directUrl = (boolean) body.get("directUrl");
HashMap<String, Object> fileKey = new HashMap<>();
fileKey.put("fileName", fileName);
fileKey.put("userAddress", InetAddress.getLocalHost().getHostAddress());
@ -564,19 +512,13 @@ public class FileController {
referenceData.put("fileKey", gson.toJson(fileKey));
HashMap<String, Object> data = new HashMap<>();
data.put("fileType", documentManager.getDocumentName(fileName));
data.put("key", documentManager.generateRevisionId(
storagePathBuilder.getStorageLocation()
+ "/" + fileName + "/"
+ new File(storagePathBuilder.getFileLocation(fileName)).lastModified()
));
data.put("url", urlManager.getFileUrl(fileName));
data.put("directUrl", body.getDirectUrl() ? urlManager.getDirectFileUrl(fileName) : null);
data.put("fileType", fileUtility.getFileExtension(fileName).replace(".", ""));
data.put("url", documentManager.getDownloadUrl(fileName, true));
data.put("directUrl", directUrl ? documentManager.getDownloadUrl(fileName, false) : null);
data.put("referenceData", referenceData);
data.put("path", fileName);
data.put("link", storagePathBuilder.getServerUrl(true) + "/editor?fileName=" + fileName);
if (settingsManager.isSecurityEnabled()) {
if (jwtManager.tokenEnabled()) {
String token = jwtManager.createToken(data);
data.put("token", token);
}
@ -586,101 +528,4 @@ public class FileController {
return "{ \"error\" : 1, \"message\" : \"" + e.getMessage() + "\"}";
}
}
@GetMapping("/history")
@ResponseBody
public String history(@RequestParam("fileName") final String fileName) {
return historyManager.getHistory(fileName);
}
@GetMapping("/historydata")
@ResponseBody
public String history(@RequestParam("fileName") final String fileName,
@RequestParam("version") final String version,
@RequestParam(value = "directUrl", defaultValue = "false") final Boolean directUrl) {
return historyManager.getHistoryData(fileName, version, directUrl);
}
@PutMapping("/restore")
@ResponseBody
public String restore(@RequestBody final Restore body, @CookieValue("uid") final Integer uid) {
try {
String sourceStringFile = storagePathBuilder.getFileLocation(body.getFileName());
File sourceFile = new File(sourceStringFile);
Path sourcePathFile = sourceFile.toPath();
String historyDirectory = storagePathBuilder.getHistoryDir(sourcePathFile.toString());
Integer bumpedVersion = storagePathBuilder.getFileVersion(historyDirectory, false);
String bumpedVersionStringDirectory = historyManager.versionDir(historyDirectory, bumpedVersion, true);
File bumpedVersionDirectory = new File(bumpedVersionStringDirectory);
if (!bumpedVersionDirectory.exists()) {
bumpedVersionDirectory.mkdir();
}
Path bumpedKeyPathFile = Paths.get(bumpedVersionStringDirectory, "key.txt");
String bumpedKeyStringFile = bumpedKeyPathFile.toString();
File bumpedKeyFile = new File(bumpedKeyStringFile);
String bumpedKey = documentManager.generateRevisionId(
storagePathBuilder.getStorageLocation()
+ "/"
+ body.getFileName()
+ "/"
+ Long.toString(sourceFile.lastModified())
);
FileWriter bumpedKeyFileWriter = new FileWriter(bumpedKeyFile);
bumpedKeyFileWriter.write(bumpedKey);
bumpedKeyFileWriter.close();
User user = userService.findUserById(uid).get();
Path bumpedChangesPathFile = Paths.get(bumpedVersionStringDirectory, "changes.json");
String bumpedChangesStringFile = bumpedChangesPathFile.toString();
File bumpedChangesFile = new File(bumpedChangesStringFile);
JSONObject bumpedChangesUser = new JSONObject();
// Don't add the `uid-` prefix.
// https://github.com/ONLYOFFICE/document-server-integration/issues/437#issuecomment-1663526562
bumpedChangesUser.put("id", user.getId());
bumpedChangesUser.put("name", user.getName());
JSONObject bumpedChangesChangesItem = new JSONObject();
bumpedChangesChangesItem.put("created", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
bumpedChangesChangesItem.put("user", bumpedChangesUser);
JSONArray bumpedChangesChanges = new JSONArray();
bumpedChangesChanges.add(bumpedChangesChangesItem);
JSONObject bumpedChanges = new JSONObject();
bumpedChanges.put("serverVersion", null);
bumpedChanges.put("changes", bumpedChangesChanges);
String bumpedChangesContent = bumpedChanges.toJSONString();
FileWriter bumpedChangesFileWriter = new FileWriter(bumpedChangesFile);
bumpedChangesFileWriter.write(bumpedChangesContent);
bumpedChangesFileWriter.close();
String sourceExtension = documentManager.getExtension(body.getFileName());
String previousBasename = "prev." + sourceExtension;
Path bumpedFile = Paths.get(bumpedVersionStringDirectory, previousBasename);
Files.move(sourcePathFile, bumpedFile);
String recoveryVersionStringDirectory = historyManager.versionDir(
historyDirectory,
body.getVersion(),
true
);
Path recoveryPathFile = Paths.get(recoveryVersionStringDirectory, previousBasename);
String recoveryStringFile = recoveryPathFile.toString();
FileInputStream recoveryStream = new FileInputStream(recoveryStringFile);
storageMutator.createFile(sourcePathFile, recoveryStream);
recoveryStream.close();
JSONObject responseBody = new JSONObject();
responseBody.put("error", null);
responseBody.put("success", true);
return responseBody.toJSONString();
} catch (Exception error) {
error.printStackTrace();
JSONObject responseBody = new JSONObject();
responseBody.put("error", error.getMessage());
responseBody.put("success", false);
return responseBody.toJSONString();
}
}
}

View File

@ -1,6 +1,6 @@
/**
*
* (c) Copyright Ascensio System SIA 2024
* (c) Copyright Ascensio System SIA 2023
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -21,11 +21,9 @@ package com.onlyoffice.integration.controllers;
import com.onlyoffice.integration.documentserver.storage.FileStorageMutator;
import com.onlyoffice.integration.documentserver.storage.FileStoragePathBuilder;
import com.onlyoffice.integration.documentserver.util.Misc;
import com.onlyoffice.integration.documentserver.util.file.FileUtility;
import com.onlyoffice.integration.entities.User;
import com.onlyoffice.integration.sdk.manager.DocumentManager;
import com.onlyoffice.integration.sdk.manager.UrlManager;
import com.onlyoffice.integration.services.UserServices;
import com.onlyoffice.integration.dto.FormatsList;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
@ -35,7 +33,6 @@ import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.http.ResponseEntity;
import java.util.ArrayList;
import java.util.Arrays;
@ -55,17 +52,20 @@ public class IndexController {
@Autowired
private FileStoragePathBuilder storagePathBuilder;
@Autowired
private FileUtility fileUtility;
@Autowired
private Misc mistUtility;
@Autowired
private UserServices userService;
@Autowired
private DocumentManager documentManager;
@Value("${files.docservice.url.site}")
private String docserviceSite;
@Autowired
private UrlManager urlManager;
@Value("${files.docservice.url.preloader}")
private String docservicePreloader;
@Value("${url.converter}")
private String urlConverter;
@ -76,9 +76,6 @@ public class IndexController {
@Value("${files.docservice.languages}")
private String langs;
@Value("${server.version}")
private String serverVersion;
@GetMapping("${url.index}")
public String index(@RequestParam(value = "directUrl", required = false) final Boolean directUrl,
final Model model) {
@ -105,14 +102,15 @@ public class IndexController {
for (java.io.File file:files) { // run through all the files
String fileName = file.getName(); // get file name
docTypes.add(documentManager
docTypes.add(fileUtility
.getDocumentType(fileName)
.toString()
.toLowerCase()); // add a document type of each file to the list
filesEditable.add(documentManager.isEditable(fileName)); // specify if a file is editable or not
filesEditable.add(fileUtility.getEditedExts()
.contains(fileUtility.getFileExtension(fileName))); // specify if a file is editable or not
versions.add(" [" + storagePathBuilder.
getFileVersion(fileName, true) + "]"); // add a file version to the list
isFillFormDoc.add(documentManager.isFillable(fileName));
isFillFormDoc.add(fileUtility.getFillExts().contains(fileUtility.getFileExtension(fileName)));
}
// add all the parameters to the model
@ -121,12 +119,11 @@ public class IndexController {
model.addAttribute("files", files);
model.addAttribute("docTypes", docTypes);
model.addAttribute("filesEditable", filesEditable);
model.addAttribute("datadocs", urlManager.getDocumentServerPreloaderApiUrl());
model.addAttribute("datadocs", docserviceSite + docservicePreloader);
model.addAttribute("tooltip", tooltip);
model.addAttribute("users", users);
model.addAttribute("languages", languages);
model.addAttribute("directUrl", directUrl);
model.addAttribute("serverVersion", serverVersion);
return "index.html";
}
@ -135,16 +132,16 @@ public class IndexController {
@ResponseBody
public HashMap<String, String> configParameters() { // get configuration parameters
HashMap<String, String> configuration = new HashMap<>();
configuration.put("FillExtList", String.join(",", fileUtility
.getFillExts())); // put a list of the extensions that can be filled to config
configuration.put("ConverExtList", String.join(",", fileUtility
.getConvertExts())); // put a list of the extensions that can be converted to config
configuration.put("EditedExtList", String.join(",", fileUtility
.getEditedExts())); // put a list of the extensions that can be edited to config
configuration.put("UrlConverter", urlConverter);
configuration.put("UrlEditor", urlEditor);
return configuration;
}
@GetMapping("/formats")
@ResponseBody
public ResponseEntity<FormatsList> formats() { // return all the supported formats
FormatsList list = new FormatsList(documentManager.getFormats());
return ResponseEntity.ok(list);
}
}

View File

@ -1,6 +1,6 @@
/**
*
* (c) Copyright Ascensio System SIA 2024
* (c) Copyright Ascensio System SIA 2023
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -16,24 +16,17 @@
*
*/
package entities;
package com.onlyoffice.integration.documentserver.callbacks;
public class Goback {
private String text;
private Boolean blank;
import com.onlyoffice.integration.dto.Track;
import org.springframework.beans.factory.annotation.Autowired;
public Goback() { }
public Goback(final String textParam, final Boolean blankParam) {
this.text = textParam;
this.blank = blankParam;
}
public String getText() {
return text;
}
public Boolean getBlank() {
return blank;
// specify the callback handler functions
public interface Callback {
int handle(Track body, String fileName); // handle the callback
int getStatus(); // get document status
@Autowired
default void selfRegistration(CallbackHandler callbackHandler) { // register a callback handler
callbackHandler.register(getStatus(), this);
}
}

View File

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

View File

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

View File

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

View File

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

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