mirror of
https://github.com/ONLYOFFICE/document-server-integration.git
synced 2026-04-07 14:06:11 +08:00
Compare commits
113 Commits
v99.99.99.
...
feature/py
| Author | SHA1 | Date | |
|---|---|---|---|
| c9baa474be | |||
| 48185674d4 | |||
| dbca11e85c | |||
| d21a732859 | |||
| b96a6fac53 | |||
| b01af348a7 | |||
| c2443d3106 | |||
| 5fa3f4c57f | |||
| efd7e1b6e7 | |||
| 259ee63eea | |||
| 453b9835b7 | |||
| 89e6544b79 | |||
| 32a60c09aa | |||
| 5a03024cd3 | |||
| cb6416c481 | |||
| 55e4247687 | |||
| a0620905b2 | |||
| 3fcef4096a | |||
| 4e5349c1c4 | |||
| 538eec1ff3 | |||
| df7cfda2fb | |||
| 9ebef04f3d | |||
| a6ed970bca | |||
| 7f659bc95e | |||
| 3c4a1c1c31 | |||
| 2bae0567ad | |||
| c06f2a5a29 | |||
| 8aed04753c | |||
| 15ed02e556 | |||
| fb66dc8423 | |||
| 541ace8132 | |||
| 8b5cebeb3f | |||
| 419fbf90f9 | |||
| 2d637b88df | |||
| 13e2d5b33c | |||
| f208fe1939 | |||
| b3cc35cb5e | |||
| 8b316b0786 | |||
| c57fcbfd90 | |||
| 1939b85c8c | |||
| ee0ac33820 | |||
| c93579d98f | |||
| 61a9e122cd | |||
| e88a9f5bed | |||
| f1ce0fb415 | |||
| 3b142d92fc | |||
| 1898da660e | |||
| 0629cf0797 | |||
| 7737670a6d | |||
| 5bdcac42e3 | |||
| 4b8ffa26cc | |||
| a4b6fcb512 | |||
| 523b10c979 | |||
| 1d4bc95c29 | |||
| e94a4863aa | |||
| edda981ab7 | |||
| 65ebf9a5b1 | |||
| a081cd1f06 | |||
| 04c5ee8cd7 | |||
| 3ebf3fabee | |||
| 403efc1325 | |||
| 7deedcaa5e | |||
| 161e26dd8a | |||
| 09804349fa | |||
| 83a83f4f5d | |||
| 79ee987003 | |||
| 434484cac3 | |||
| a0bafb0e4b | |||
| 184aded727 | |||
| 7db708e559 | |||
| 3b3116f56e | |||
| 15c70f43d7 | |||
| 39af4be045 | |||
| c9dc4862ed | |||
| 122d41e307 | |||
| 2880db7383 | |||
| c0f23a4fc2 | |||
| 1a49d8dd03 | |||
| 180f287c07 | |||
| 37c33965c8 | |||
| 0861732dbe | |||
| d3220c7a91 | |||
| 450cafdae3 | |||
| 62abe3e569 | |||
| 8b2fbff3b7 | |||
| acf243ee3e | |||
| 66c38ded4a | |||
| 58a73190d4 | |||
| ae7a208831 | |||
| 2d83f3f39c | |||
| 2aed1e3a83 | |||
| 001a99b502 | |||
| a7a9f997d5 | |||
| 4c3dc96e30 | |||
| 7fe1ae27b4 | |||
| dce840c627 | |||
| 4f832ac2f7 | |||
| e7623e29d7 | |||
| 16dd8a55e5 | |||
| dca68bf0d1 | |||
| f028f1ba2f | |||
| 5c8867dd20 | |||
| 27eea60fc3 | |||
| c285b49d3b | |||
| 70c86f3054 | |||
| 00e5466a0c | |||
| 12a366a28a | |||
| b4918cf493 | |||
| b2b21980d1 | |||
| 09a97c0f66 | |||
| 5db65ef062 | |||
| 5164380336 | |||
| 26c5cd0a83 |
6
.github/workflows/lint-php.yml
vendored
6
.github/workflows/lint-php.yml
vendored
@ -25,7 +25,5 @@ jobs:
|
||||
php-version: '8.2'
|
||||
tools: cs2pr, phpcs
|
||||
|
||||
- name: Run phpcs
|
||||
run: |
|
||||
phpcs --version
|
||||
phpcs -q --extensions=php,module,inc,install,test,profile,theme,info --ignore=node_modules,bower_components,vendor,css,js,lib --standard=./ruleset.xml ./
|
||||
- name: Lint
|
||||
run: phpcs .
|
||||
12
.gitmodules
vendored
12
.gitmodules
vendored
@ -2,10 +2,6 @@
|
||||
path = web/documentserver-example/java/src/main/resources/assets
|
||||
url = https://github.com/ONLYOFFICE/document-templates
|
||||
branch = main/en
|
||||
[submodule "web/documentserver-example/python/assets"]
|
||||
path = web/documentserver-example/python/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
|
||||
@ -38,3 +34,11 @@
|
||||
path = web/documentserver-example/php/assets/document-formats
|
||||
url = https://github.com/ONLYOFFICE/document-formats
|
||||
branch = master
|
||||
[submodule "web/documentserver-example/python/assets/document-templates"]
|
||||
path = web/documentserver-example/python/assets/document-templates
|
||||
url = https://github.com/ONLYOFFICE/document-templates
|
||||
branch = main/en
|
||||
[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
|
||||
|
||||
@ -303,6 +303,10 @@ PHP_CodeSniffer - PHP_CodeSniffer is a set of two PHP scripts; the main phpcs sc
|
||||
License: BSD-3-Clause
|
||||
License File: PHP_CodeSniffer.license
|
||||
|
||||
PHPUnit - The PHP Unit Testing framework. (https://github.com/sebastianbergmann/phpunit/blob/main/LICENSE)
|
||||
License: BSD 3-Clause
|
||||
License File: phpunit.license
|
||||
|
||||
|
||||
web/documentserver-example/python
|
||||
|
||||
|
||||
@ -6,6 +6,9 @@
|
||||
- nodejs: delete file without reloading the page
|
||||
- nodejs: getting history by a separate request
|
||||
- nodejs: restore from history
|
||||
- python: restore from history
|
||||
- ruby: restore from history
|
||||
- php: restore from history
|
||||
|
||||
## 1.6.0
|
||||
- nodejs: setUsers for region protection
|
||||
|
||||
@ -163,6 +163,8 @@ public class DefaultCallbackManager implements CallbackManager {
|
||||
|
||||
storageMutator.createDirectory(ver); // create the file version directory
|
||||
|
||||
lastVersion.toFile().renameTo(new File(versionDir + File.separator + "prev" + curExt));
|
||||
|
||||
saveFile(byteArrayFile, toSave); // save document file
|
||||
|
||||
byte[] byteArrayChanges = getDownloadFile(changesUri); // download file changes
|
||||
|
||||
@ -239,7 +239,8 @@
|
||||
let fileList = JSON.parse(xhr.responseText);
|
||||
let firstXlsxName;
|
||||
let file;
|
||||
for (file of fileList) {
|
||||
for (var i = 0; i < fileList.length; i++) {
|
||||
file = fileList[i];
|
||||
if (file["title"]) {
|
||||
if (getFileExt(file["title"]) === "xlsx")
|
||||
{
|
||||
|
||||
2
web/documentserver-example/php/.gitignore
vendored
Normal file
2
web/documentserver-example/php/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
logs
|
||||
vendor
|
||||
1
web/documentserver-example/php/.php-version
Normal file
1
web/documentserver-example/php/.php-version
Normal file
@ -0,0 +1 @@
|
||||
8.1.21
|
||||
@ -31,3 +31,7 @@ License File: jwt.license
|
||||
PHP_CodeSniffer - PHP_CodeSniffer is a set of two PHP scripts; the main phpcs script that tokenizes PHP, JavaScript and CSS files to detect violations of a defined coding standard, and a second phpcbf script to automatically correct coding standard violations. PHP_CodeSniffer is an essential development tool that ensures your code remains clean and consistent. (https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt)
|
||||
License: BSD-3-Clause
|
||||
License File: PHP_CodeSniffer.license
|
||||
|
||||
PHPUnit - The PHP Unit Testing framework. (https://github.com/sebastianbergmann/phpunit/blob/main/LICENSE)
|
||||
License: BSD 3-Clause
|
||||
License File: phpunit.license
|
||||
|
||||
80
web/documentserver-example/php/Makefile
Normal file
80
web/documentserver-example/php/Makefile
Normal file
@ -0,0 +1,80 @@
|
||||
.DEFAULT_GOAL := help
|
||||
|
||||
ADDRESS := $(ADDRESS)
|
||||
PORT := $(PORT)
|
||||
|
||||
.PHONY: help
|
||||
help: # Show help message for each of the Makefile recipes.
|
||||
@grep -E "^[a-z-]+: #" $(MAKEFILE_LIST) | \
|
||||
awk 'BEGIN {FS = ": # "}; {printf "%s: %s\n", $$1, $$2}'
|
||||
|
||||
.PHONY: dev
|
||||
dev: # Install development dependencies.
|
||||
@composer install
|
||||
|
||||
.PHONY: prod
|
||||
prod: # Install production dependencies.
|
||||
@composer install --no-dev
|
||||
|
||||
ifeq ($(ADDRESS),)
|
||||
server-dev: \
|
||||
export ADDRESS := localhost
|
||||
else
|
||||
server-dev: \
|
||||
export ADDRESS := $(ADDRESS)
|
||||
endif
|
||||
|
||||
ifeq ($(PORT),)
|
||||
server-dev: \
|
||||
export PORT := 9000
|
||||
else
|
||||
server-dev: \
|
||||
export PORT := $(PORT)
|
||||
endif
|
||||
|
||||
.PHONY: server-dev
|
||||
server-dev: # Start the development server on localhost at $PORT (default: 9000).
|
||||
@php --server $(ADDRESS):$(PORT)
|
||||
|
||||
ifeq ($(ADDRESS),)
|
||||
server-prod: \
|
||||
export ADDRESS := 0.0.0.0
|
||||
else
|
||||
server-prod: \
|
||||
export ADDRESS := $(ADDRESS)
|
||||
endif
|
||||
|
||||
ifeq ($(PORT),)
|
||||
server-prod: \
|
||||
export PORT := 9000
|
||||
else
|
||||
server-prod: \
|
||||
export PORT := $(PORT)
|
||||
endif
|
||||
|
||||
.PHONY: server-prod
|
||||
server-prod: # Start the production server on 0.0.0.0 at $PORT (default: 9000).
|
||||
@php-fpm --fpm-config php-fpm.conf
|
||||
|
||||
.PHONY: lint
|
||||
lint: # Lint the source code for the style.
|
||||
@./vendor/bin/phpcs .
|
||||
|
||||
.PHONY: test
|
||||
test: # Run tests recursively.
|
||||
@./vendor/bin/phpunit \
|
||||
--test-suffix "Tests.php" \
|
||||
--display-incomplete \
|
||||
--display-deprecations \
|
||||
--display-errors \
|
||||
--display-notices \
|
||||
--display-warnings \
|
||||
common
|
||||
@./vendor/bin/phpunit \
|
||||
--test-suffix "Tests.php" \
|
||||
--display-incomplete \
|
||||
--display-deprecations \
|
||||
--display-errors \
|
||||
--display-notices \
|
||||
--display-warnings \
|
||||
configuration
|
||||
@ -18,6 +18,8 @@
|
||||
namespace OnlineEditorsExamplePhp;
|
||||
|
||||
use Exception;
|
||||
use OnlineEditorsExamplePhp\Common\Path;
|
||||
use OnlineEditorsExamplePhp\Configuration\ConfigurationManager;
|
||||
use OnlineEditorsExamplePhp\Helpers\ConfigManager;
|
||||
use OnlineEditorsExamplePhp\Helpers\ExampleUsers;
|
||||
use OnlineEditorsExamplePhp\Helpers\JwtManager;
|
||||
@ -47,41 +49,6 @@ function getHttpOrigin()
|
||||
return $origin;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set headers that prevent caching in all the browsers
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function nocacheHeaders()
|
||||
{
|
||||
$headers = [
|
||||
'Expires' => 'Wed, 11 Jan 1984 05:00:00 GMT',
|
||||
'Cache-Control' => 'no-cache, must-revalidate, max-age=0',
|
||||
'Pragma' => 'no-cache',
|
||||
];
|
||||
$headers['Last-Modified'] = false;
|
||||
|
||||
unset($headers['Last-Modified']);
|
||||
|
||||
// In PHP 5.3+, make sure we are not sending a Last-Modified header.
|
||||
if (function_exists('header_remove')) {
|
||||
@header_remove('Last-Modified');
|
||||
} else {
|
||||
// In PHP 5.2, send an empty Last-Modified header, but only as a
|
||||
// last resort to override a header already sent. #WP23021
|
||||
foreach (headers_list() as $header) {
|
||||
if (0 === mb_stripos($header, 'Last-Modified')) {
|
||||
$headers['Last-Modified'] = '';
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($headers as $name => $field_value) {
|
||||
@header("{$name}: {$field_value}");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Save copy as...
|
||||
*
|
||||
@ -90,6 +57,8 @@ function nocacheHeaders()
|
||||
function saveas()
|
||||
{
|
||||
try {
|
||||
$config_manager = new ConfigurationManager();
|
||||
|
||||
$post = json_decode(file_get_contents('php://input'), true);
|
||||
$fileurl = $post["url"];
|
||||
$title = $post["title"];
|
||||
@ -106,8 +75,7 @@ function saveas()
|
||||
$content_length = $headers["Content-Length"];
|
||||
$data = file_get_contents(str_replace(" ", "%20", $fileurl));
|
||||
|
||||
if ($data === false || $content_length <= 0 || $content_length >
|
||||
$configManager->getConfig("fileSizeMax")) {
|
||||
if ($data === false || $content_length <= 0 || $content_length > $config_manager->maximum_file_size()) {
|
||||
$result["error"] = "File size is incorrect";
|
||||
return $result;
|
||||
}
|
||||
@ -133,6 +101,8 @@ function saveas()
|
||||
*/
|
||||
function upload()
|
||||
{
|
||||
$config_manager = new ConfigurationManager();
|
||||
|
||||
$configManager = new ConfigManager();
|
||||
if ($_FILES['files']['error'] > 0) {
|
||||
$result["error"] = 'Error ' . json_encode($_FILES['files']['error']);
|
||||
@ -154,7 +124,7 @@ function upload()
|
||||
$ext = mb_strtolower(pathinfo($_FILES['files']['name'], PATHINFO_EXTENSION)); // get file extension
|
||||
|
||||
// check if the file size is correct (it should be less than the max file size, but greater than 0)
|
||||
if ($filesize <= 0 || $filesize > $configManager->getConfig("fileSizeMax")) {
|
||||
if ($filesize <= 0 || $filesize > $config_manager->maximum_file_size()) {
|
||||
$result["error"] = 'File size is incorrect'; // if not, then an error occurs
|
||||
return $result;
|
||||
}
|
||||
@ -203,7 +173,15 @@ function track()
|
||||
return $data;
|
||||
}
|
||||
|
||||
global $_trackerStatus;
|
||||
$_trackerStatus = [
|
||||
0 => 'NotFound',
|
||||
1 => 'Editing',
|
||||
2 => 'MustSave',
|
||||
3 => 'Corrupted',
|
||||
4 => 'Closed',
|
||||
6 => 'MustForceSave',
|
||||
7 => 'CorruptedForceSave',
|
||||
];
|
||||
$status = $_trackerStatus[$data->status]; // get status from the request body
|
||||
|
||||
$userAddress = $_GET["userAddress"];
|
||||
@ -256,9 +234,8 @@ function convert()
|
||||
$fileUri = $post["fileUri"];
|
||||
if ($fileUri == null || $fileUri == "") {
|
||||
$fileUri = serverPath(true) . '/'
|
||||
. "webeditor-ajax.php"
|
||||
. "?type=download"
|
||||
. "&fileName=" . urlencode($fileName)
|
||||
. "download"
|
||||
. "?fileName=" . urlencode($fileName)
|
||||
. "&userAddress=" . getClientIp();
|
||||
}
|
||||
$key = getDocEditorKey($fileName);
|
||||
@ -391,6 +368,8 @@ function csv()
|
||||
function historyDownload()
|
||||
{
|
||||
try {
|
||||
$config_manager = new ConfigurationManager();
|
||||
|
||||
$fileName = basename($_GET["fileName"]); // get the file name
|
||||
$userAddress = $_GET["userAddress"];
|
||||
|
||||
@ -400,8 +379,7 @@ function historyDownload()
|
||||
$jwtManager = new JwtManager();
|
||||
if ($jwtManager->isJwtEnabled()) {
|
||||
$configManager = new ConfigManager();
|
||||
$jwtHeader = $configManager->getConfig("docServJwtHeader") == "" ?
|
||||
"Authorization" : $configManager->getConfig("docServJwtHeader");
|
||||
$jwtHeader = $config_manager->jwt_header();
|
||||
if (!empty(apache_request_headers()[$jwtHeader])) {
|
||||
$token = $jwtManager->jwtDecode(mb_substr(
|
||||
apache_request_headers()[$jwtHeader],
|
||||
@ -438,17 +416,15 @@ function historyDownload()
|
||||
function download()
|
||||
{
|
||||
try {
|
||||
$configManager = new ConfigManager();
|
||||
$fileName = realpath($configManager->getConfig("storagePath"))
|
||||
=== $configManager->getConfig("storagePath") ?
|
||||
$_GET["fileName"] : basename($_GET["fileName"]); // get the file name
|
||||
$config_manager = new ConfigurationManager();
|
||||
|
||||
$fileName = $_GET["fileName"];
|
||||
$userAddress = $_GET["userAddress"] ?? null;
|
||||
$isEmbedded = $_GET["&dmode"] ?? null;
|
||||
$jwtManager = new JwtManager();
|
||||
|
||||
if ($jwtManager->isJwtEnabled() && $isEmbedded == null && $userAddress) {
|
||||
$jwtHeader = $configManager->getConfig("docServJwtHeader") == "" ?
|
||||
"Authorization" : $configManager->getConfig("docServJwtHeader");
|
||||
$jwtHeader = $config_manager->jwt_header();
|
||||
if (!empty(apache_request_headers()[$jwtHeader])) {
|
||||
$token = $jwtManager->jwtDecode(mb_substr(
|
||||
apache_request_headers()[$jwtHeader],
|
||||
@ -605,3 +581,74 @@ function reference()
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
function restore()
|
||||
{
|
||||
try {
|
||||
$input = file_get_contents('php://input');
|
||||
$body = json_decode($input);
|
||||
|
||||
$source_basename = $body->fileName;
|
||||
$version = $body->version;
|
||||
$user_id = $body->userId;
|
||||
|
||||
$source_file = getStoragePath($source_basename);
|
||||
$history_directory = getHistoryDir($source_file);
|
||||
|
||||
$bumped_version = getFileVersion($history_directory);
|
||||
$bumped_version_string_directory = getVersionDir($history_directory, $bumped_version);
|
||||
if (!file_exists($bumped_version_string_directory)) {
|
||||
mkdir($bumped_version_string_directory);
|
||||
}
|
||||
$bumped_version_directory = new Path($bumped_version_string_directory);
|
||||
|
||||
$bumped_key_file = $bumped_version_directory->join_path('key.txt');
|
||||
$bumped_key_string_file = $bumped_key_file->string();
|
||||
$bumped_key = getDocEditorKey($source_basename);
|
||||
file_put_contents($bumped_key_string_file, $bumped_key, LOCK_EX);
|
||||
|
||||
$users = new ExampleUsers();
|
||||
$user = $users->getUser($user_id);
|
||||
|
||||
$bumped_changes_file = $bumped_version_directory->join_path('changes.json');
|
||||
$bumped_changes_string_file = $bumped_changes_file->string();
|
||||
$bumped_changes = [
|
||||
'serverVersion' => null,
|
||||
'changes' => array(
|
||||
[
|
||||
'created' => date('Y-m-d H:i:s'),
|
||||
'user' => [
|
||||
'id' => $user->id,
|
||||
'name' => $user->name
|
||||
]
|
||||
]
|
||||
)
|
||||
];
|
||||
$bumped_changes_content = json_encode($bumped_changes, JSON_PRETTY_PRINT);
|
||||
file_put_contents($bumped_changes_string_file, $bumped_changes_content, LOCK_EX);
|
||||
|
||||
$source_extension = pathinfo($source_basename, PATHINFO_EXTENSION);
|
||||
$previous_basename = "prev.{$source_extension}";
|
||||
|
||||
$bumped_file = $bumped_version_directory->join_path($previous_basename);
|
||||
$bumped_string_file = $bumped_file->string();
|
||||
copy($source_file, $bumped_string_file);
|
||||
|
||||
$recovery_version_string_directory = getVersionDir($history_directory, $version);
|
||||
$recovery_version_directory = new Path($recovery_version_string_directory);
|
||||
$recovery_file = $recovery_version_directory->join_path($previous_basename);
|
||||
$recovery_string_file = $recovery_file->string();
|
||||
copy($recovery_string_file, $source_file);
|
||||
|
||||
return [
|
||||
'error' => null,
|
||||
'success' => true
|
||||
];
|
||||
} catch (Exception $error) {
|
||||
$message = $error->getMessage();
|
||||
return [
|
||||
'error' => $message,
|
||||
'success' => false
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
22
web/documentserver-example/php/common/HTTPStatus.php
Normal file
22
web/documentserver-example/php/common/HTTPStatus.php
Normal file
@ -0,0 +1,22 @@
|
||||
<?php
|
||||
//
|
||||
// (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.
|
||||
//
|
||||
|
||||
namespace OnlineEditorsExamplePhp\Common;
|
||||
|
||||
enum HTTPStatus: int {
|
||||
case not_found = 404;
|
||||
}
|
||||
127
web/documentserver-example/php/common/Path.php
Normal file
127
web/documentserver-example/php/common/Path.php
Normal file
@ -0,0 +1,127 @@
|
||||
<?php
|
||||
//
|
||||
// (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.
|
||||
//
|
||||
|
||||
namespace OnlineEditorsExamplePhp\Common;
|
||||
|
||||
final class Path {
|
||||
private string $separator = DIRECTORY_SEPARATOR;
|
||||
private string $string;
|
||||
|
||||
public function __construct(string $path) {
|
||||
$this->string = $path;
|
||||
}
|
||||
|
||||
public function string(): string {
|
||||
return $this->string;
|
||||
}
|
||||
|
||||
public function dirname(): ?string {
|
||||
$string = $this->string();
|
||||
$parsed = pathinfo($string, PATHINFO_DIRNAME);
|
||||
return $parsed ?: null;
|
||||
}
|
||||
|
||||
public function basename(): ?string {
|
||||
$string = $this->string();
|
||||
$parsed = pathinfo($string, PATHINFO_BASENAME);
|
||||
return $parsed ?: null;
|
||||
}
|
||||
|
||||
public function extension(): ?string {
|
||||
$string = $this->string();
|
||||
$parsed = pathinfo($string, PATHINFO_EXTENSION);
|
||||
return $parsed ?: null;
|
||||
}
|
||||
|
||||
public function filename(): ?string {
|
||||
$string = $this->string();
|
||||
$parsed = pathinfo($string, PATHINFO_FILENAME);
|
||||
return $parsed ?: null;
|
||||
}
|
||||
|
||||
public function normalize(): self {
|
||||
$string = $this->string();
|
||||
$filtered = array();
|
||||
$slugs = explode($this->separator, $string);
|
||||
foreach ($slugs as $slug) {
|
||||
if ($slug === '.') {
|
||||
continue;
|
||||
}
|
||||
if ($slug === '..') {
|
||||
array_pop($filtered);
|
||||
continue;
|
||||
}
|
||||
$filtered[] = $slug;
|
||||
}
|
||||
$joined = implode($this->separator, $filtered);
|
||||
$escaped_separator = preg_quote($this->separator, $this->separator);
|
||||
$separator_regex = "/{$escaped_separator}{2,}/";
|
||||
$separated = preg_replace($separator_regex, $this->separator, $joined);
|
||||
return new Path($separated);
|
||||
}
|
||||
|
||||
public function join_path(string $path): self {
|
||||
$string = $this->string();
|
||||
$separator =
|
||||
str_ends_with($string, $this->separator) ||
|
||||
str_starts_with($path, $this->separator)
|
||||
? ''
|
||||
: $this->separator;
|
||||
return new Path("{$string}{$separator}{$path}");
|
||||
}
|
||||
|
||||
public function absolute(): bool {
|
||||
$string = $this->string();
|
||||
|
||||
$nt_regex = '/^[A-Za-z]:\\\\/';
|
||||
if (preg_match($nt_regex, $string)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$nt_separator = '\\';
|
||||
if (str_starts_with($string, $nt_separator)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$posix_separator = '/';
|
||||
if (str_starts_with($string, $posix_separator)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function exists(): bool {
|
||||
$string = $this->string();
|
||||
return file_exists($string);
|
||||
}
|
||||
|
||||
public function contents(): string {
|
||||
$string = $this->string();
|
||||
return file_get_contents($string);
|
||||
}
|
||||
|
||||
public function directory(): bool {
|
||||
$string = $this->string();
|
||||
return is_dir($string);
|
||||
}
|
||||
|
||||
public function make_directory(): bool {
|
||||
$string = $this->string();
|
||||
return mkdir($string);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,39 @@
|
||||
<?php
|
||||
//
|
||||
// (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.
|
||||
//
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use OnlineEditorsExamplePhp\Common\Path;
|
||||
|
||||
final class PathAbsolutePOSIXTests extends TestCase {
|
||||
public function test_recognizes_an_empty_as_a_non_absolute() {
|
||||
$path = new Path('');
|
||||
$absolute = $path->absolute();
|
||||
$this->assertFalse($absolute);
|
||||
}
|
||||
|
||||
public function test_recognizes_a_relative_as_a_non_absolute() {
|
||||
$path = new Path('.');
|
||||
$absolute = $path->absolute();
|
||||
$this->assertFalse($absolute);
|
||||
}
|
||||
|
||||
public function test_recognizes_an_absolute_as_an_absolute() {
|
||||
$path = new Path('/');
|
||||
$absolute = $path->absolute();
|
||||
$this->assertTrue($absolute);
|
||||
}
|
||||
}
|
||||
84
web/documentserver-example/php/common/PathJoinPOSIXTests.php
Normal file
84
web/documentserver-example/php/common/PathJoinPOSIXTests.php
Normal file
@ -0,0 +1,84 @@
|
||||
<?php
|
||||
//
|
||||
// (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.
|
||||
//
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use OnlineEditorsExamplePhp\Common\Path;
|
||||
|
||||
final class PathJoinPOSIXTests extends TestCase {
|
||||
public function test_joins_a_relative_to_an_empty_one() {
|
||||
$path = new Path('');
|
||||
$joined = $path->join_path('srv');
|
||||
$this->assertEquals($joined->dirname(), '/');
|
||||
$this->assertEquals($joined->basename(), 'srv');
|
||||
$this->assertEquals($joined->extension(), null);
|
||||
$this->assertEquals($joined->filename(), 'srv');
|
||||
}
|
||||
|
||||
public function test_joins_a_relative_to_a_relative_one() {
|
||||
$path = new Path('.');
|
||||
$joined = $path->join_path('srv');
|
||||
$this->assertEquals($joined->dirname(), '.');
|
||||
$this->assertEquals($joined->basename(), 'srv');
|
||||
$this->assertEquals($joined->extension(), null);
|
||||
$this->assertEquals($joined->filename(), 'srv');
|
||||
}
|
||||
|
||||
public function test_joins_a_relative_to_an_absolute_one() {
|
||||
$path = new Path('/');
|
||||
$joined = $path->join_path('srv');
|
||||
$this->assertEquals($joined->dirname(), '/');
|
||||
$this->assertEquals($joined->basename(), 'srv');
|
||||
$this->assertEquals($joined->extension(), null);
|
||||
$this->assertEquals($joined->filename(), 'srv');
|
||||
}
|
||||
|
||||
public function test_joins_an_absolute_to_an_empty_one() {
|
||||
$path = new Path('');
|
||||
$joined = $path->join_path('/srv');
|
||||
$this->assertEquals($joined->dirname(), '/');
|
||||
$this->assertEquals($joined->basename(), 'srv');
|
||||
$this->assertEquals($joined->extension(), null);
|
||||
$this->assertEquals($joined->filename(), 'srv');
|
||||
}
|
||||
|
||||
public function test_joins_an_absolute_to_a_relative_one() {
|
||||
$path = new Path('.');
|
||||
$joined = $path->join_path('/srv');
|
||||
$this->assertEquals($joined->dirname(), '.');
|
||||
$this->assertEquals($joined->basename(), 'srv');
|
||||
$this->assertEquals($joined->extension(), null);
|
||||
$this->assertEquals($joined->filename(), 'srv');
|
||||
}
|
||||
|
||||
public function test_joins_an_absolute_to_an_absolute_one() {
|
||||
$path = new Path('/');
|
||||
$joined = $path->join_path('/srv');
|
||||
$this->assertEquals($joined->dirname(), '/');
|
||||
$this->assertEquals($joined->basename(), 'srv');
|
||||
$this->assertEquals($joined->extension(), null);
|
||||
$this->assertEquals($joined->filename(), 'srv');
|
||||
}
|
||||
|
||||
public function test_joins_an_unnormalized() {
|
||||
$path = new Path('');
|
||||
$joined = $path->join_path('../srv');
|
||||
$this->assertEquals($joined->dirname(), '/..');
|
||||
$this->assertEquals($joined->basename(), 'srv');
|
||||
$this->assertEquals($joined->extension(), null);
|
||||
$this->assertEquals($joined->filename(), 'srv');
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,30 @@
|
||||
<?php
|
||||
//
|
||||
// (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.
|
||||
//
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use OnlineEditorsExamplePhp\Common\Path;
|
||||
|
||||
final class PathNormalizePOSIXTests extends TestCase {
|
||||
public function test_normalizes() {
|
||||
$path = new Path('./srv///sub/.././sub/file.docx');
|
||||
$normalized = $path->normalize();
|
||||
$this->assertEquals($normalized->dirname(), 'srv/sub');
|
||||
$this->assertEquals($normalized->basename(), 'file.docx');
|
||||
$this->assertEquals($normalized->extension(), 'docx');
|
||||
$this->assertEquals($normalized->filename(), 'file');
|
||||
}
|
||||
}
|
||||
150
web/documentserver-example/php/common/PathStringPOSIXTests.php
Normal file
150
web/documentserver-example/php/common/PathStringPOSIXTests.php
Normal file
@ -0,0 +1,150 @@
|
||||
<?php
|
||||
//
|
||||
// (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.
|
||||
//
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use OnlineEditorsExamplePhp\Common\Path;
|
||||
|
||||
final class PathStringPOSIXTests extends TestCase {
|
||||
public function test_generates_with_an_empty() {
|
||||
$path = new Path('');
|
||||
$string = $path->string();
|
||||
$this->assertEquals($string, '');
|
||||
}
|
||||
|
||||
public function test_generates_with_an_empty_relative() {
|
||||
$path = new Path('.');
|
||||
$string = $path->string();
|
||||
$this->assertEquals($string, '.');
|
||||
}
|
||||
|
||||
public function test_generates_with_an_empty_absolute() {
|
||||
$path = new Path('/');
|
||||
$string = $path->string();
|
||||
$this->assertEquals($string, '/');
|
||||
}
|
||||
|
||||
public function test_generates_with_a_relative() {
|
||||
$path = new Path('srv');
|
||||
$string = $path->string();
|
||||
$this->assertEquals($string, 'srv');
|
||||
}
|
||||
|
||||
public function test_generates_with_a_relative_containing_a_directory() {
|
||||
$path = new Path('srv/sub');
|
||||
$string = $path->string();
|
||||
$this->assertEquals($string, 'srv/sub');
|
||||
}
|
||||
|
||||
public function test_generates_with_a_relative_containing_a_file() {
|
||||
$path = new Path('srv/file.json');
|
||||
$string = $path->string();
|
||||
$this->assertEquals($string, 'srv/file.json');
|
||||
}
|
||||
|
||||
public function test_generates_with_a_relative_containing_a_directory_with_a_file() {
|
||||
$path = new Path('srv/sub/file.json');
|
||||
$string = $path->string();
|
||||
$this->assertEquals($string, 'srv/sub/file.json');
|
||||
}
|
||||
|
||||
public function test_generates_with_an_unnormalized_relative() {
|
||||
$path = new Path('srv////sub///file.json');
|
||||
$string = $path->string();
|
||||
$this->assertEquals($string, 'srv////sub///file.json');
|
||||
}
|
||||
|
||||
public function test_generates_with_an_normalized_relative() {
|
||||
$path = new Path('srv////sub///file.json');
|
||||
$normalized = $path->normalize();
|
||||
$string = $normalized->string();
|
||||
$this->assertEquals($string, 'srv/sub/file.json');
|
||||
}
|
||||
|
||||
public function test_generates_with_an_explicit_relative() {
|
||||
$path = new Path('./srv');
|
||||
$string = $path->string();
|
||||
$this->assertEquals($string, './srv');
|
||||
}
|
||||
|
||||
public function test_generates_with_an_explicit_relative_containing_a_directory() {
|
||||
$path = new Path('./srv/sub');
|
||||
$string = $path->string();
|
||||
$this->assertEquals($string, './srv/sub');
|
||||
}
|
||||
|
||||
public function test_generates_with_an_explicit_relative_containing_a_file() {
|
||||
$path = new Path('./srv/file.json');
|
||||
$string = $path->string();
|
||||
$this->assertEquals($string, './srv/file.json');
|
||||
}
|
||||
|
||||
public function test_generates_with_an_explicit_relative_containing_a_directory_with_a_file() {
|
||||
$path = new Path('./srv/sub/file.json');
|
||||
$string = $path->string();
|
||||
$this->assertEquals($string, './srv/sub/file.json');
|
||||
}
|
||||
|
||||
public function test_generates_with_an_explicit_unnormalized_relative() {
|
||||
$path = new Path('./srv////sub///file.json');
|
||||
$string = $path->string();
|
||||
$this->assertEquals($string, './srv////sub///file.json');
|
||||
}
|
||||
|
||||
public function test_generates_with_an_explicit_normalized_relative() {
|
||||
$path = new Path('./srv////sub///file.json');
|
||||
$normalized = $path->normalize();
|
||||
$string = $normalized->string();
|
||||
$this->assertEquals($string, 'srv/sub/file.json');
|
||||
}
|
||||
|
||||
public function test_generates_with_an_absolute() {
|
||||
$path = new Path('/srv');
|
||||
$string = $path->string();
|
||||
$this->assertEquals($string, '/srv');
|
||||
}
|
||||
|
||||
public function test_generates_with_an_absolute_containing_a_directory() {
|
||||
$path = new Path('/srv/sub');
|
||||
$string = $path->string();
|
||||
$this->assertEquals($string, '/srv/sub');
|
||||
}
|
||||
|
||||
public function test_generates_with_an_absolute_containing_a_file() {
|
||||
$path = new Path('/srv/file.json');
|
||||
$string = $path->string();
|
||||
$this->assertEquals($string, '/srv/file.json');
|
||||
}
|
||||
|
||||
public function test_generates_with_an_absolute_containing_a_directory_with_a_file() {
|
||||
$path = new Path('/srv/sub/file.json');
|
||||
$string = $path->string();
|
||||
$this->assertEquals($string, '/srv/sub/file.json');
|
||||
}
|
||||
|
||||
public function test_generates_with_an_unnormalized_absolute() {
|
||||
$path = new Path('/srv////sub///file.json');
|
||||
$string = $path->string();
|
||||
$this->assertEquals($string, '/srv////sub///file.json');
|
||||
}
|
||||
|
||||
public function test_generates_with_an_normalized_absolute() {
|
||||
$path = new Path('/srv////sub///file.json');
|
||||
$normalized = $path->normalize();
|
||||
$string = $normalized->string();
|
||||
$this->assertEquals($string, '/srv/sub/file.json');
|
||||
}
|
||||
}
|
||||
132
web/documentserver-example/php/common/URL.php
Normal file
132
web/documentserver-example/php/common/URL.php
Normal file
@ -0,0 +1,132 @@
|
||||
<?php
|
||||
//
|
||||
// (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.
|
||||
//
|
||||
|
||||
namespace OnlineEditorsExamplePhp\Common;
|
||||
|
||||
final class URL {
|
||||
private string $string;
|
||||
|
||||
public function __construct(string $url) {
|
||||
$this->string = $url;
|
||||
}
|
||||
|
||||
public function string(): string {
|
||||
return $this->string;
|
||||
}
|
||||
|
||||
public function scheme(): ?string {
|
||||
$string = $this->string();
|
||||
return parse_url($string, PHP_URL_SCHEME) ?: null;
|
||||
}
|
||||
|
||||
public function host(): ?string {
|
||||
$string = $this->string();
|
||||
return parse_url($string, PHP_URL_HOST) ?: null;
|
||||
}
|
||||
|
||||
public function port(): ?int {
|
||||
$string = $this->string();
|
||||
return parse_url($string, PHP_URL_PORT) ?: null;
|
||||
}
|
||||
|
||||
public function user(): ?string {
|
||||
$string = $this->string();
|
||||
return parse_url($string, PHP_URL_USER) ?: null;
|
||||
}
|
||||
|
||||
public function pass(): ?string {
|
||||
$string = $this->string();
|
||||
return parse_url($string, PHP_URL_PASS) ?: null;
|
||||
}
|
||||
|
||||
public function path(): ?string {
|
||||
$string = $this->string();
|
||||
return parse_url($string, PHP_URL_PATH) ?: null;
|
||||
}
|
||||
|
||||
public function query(): ?string {
|
||||
$string = $this->string();
|
||||
return parse_url($string, PHP_URL_QUERY) ?: null;
|
||||
}
|
||||
|
||||
public function fragment(): ?string {
|
||||
$string = $this->string();
|
||||
return parse_url($string, PHP_URL_FRAGMENT) ?: null;
|
||||
}
|
||||
|
||||
public static function from_components(
|
||||
?string $scheme,
|
||||
?string $host,
|
||||
?int $port,
|
||||
?string $user,
|
||||
?string $pass,
|
||||
?string $path,
|
||||
?string $query,
|
||||
?string $fragment
|
||||
): URL {
|
||||
$string = '';
|
||||
if ($scheme) {
|
||||
$string .= "{$scheme}://";
|
||||
}
|
||||
if ($user) {
|
||||
$string .= $user;
|
||||
}
|
||||
if ($pass) {
|
||||
$string .= ":{$pass}@";
|
||||
}
|
||||
if ($host) {
|
||||
$string .= $host;
|
||||
}
|
||||
if ($port) {
|
||||
$string .= ":{$port}";
|
||||
}
|
||||
if ($path) {
|
||||
$string .= $path;
|
||||
}
|
||||
if ($query) {
|
||||
$string .= "?{$query}";
|
||||
}
|
||||
if ($fragment) {
|
||||
$string .= "#{$fragment}";
|
||||
}
|
||||
return new URL($string);
|
||||
}
|
||||
|
||||
public function join_path(string $path): self {
|
||||
$current_path = $this->path();
|
||||
$separator =
|
||||
$current_path &&
|
||||
(
|
||||
str_ends_with($current_path, '/') ||
|
||||
str_starts_with($path, '/')
|
||||
) ||
|
||||
!$current_path && str_starts_with($path, '/')
|
||||
? ''
|
||||
: '/';
|
||||
$separated = "{$current_path}{$separator}{$path}";
|
||||
return URL::from_components(
|
||||
$this->scheme(),
|
||||
$this->host(),
|
||||
$this->port(),
|
||||
$this->user(),
|
||||
$this->pass(),
|
||||
$separated,
|
||||
$this->query(),
|
||||
$this->fragment()
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,42 @@
|
||||
<?php
|
||||
//
|
||||
// (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.
|
||||
//
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use OnlineEditorsExamplePhp\Common\URL;
|
||||
|
||||
final class URLFromComponentsTests extends TestCase {
|
||||
public function test_creates() {
|
||||
$url = URL::from_components(
|
||||
'http',
|
||||
'localhost',
|
||||
8080,
|
||||
'user',
|
||||
'password',
|
||||
'/path',
|
||||
'q=value',
|
||||
'fragment'
|
||||
);
|
||||
$this->assertEquals('http', $url->scheme());
|
||||
$this->assertEquals('localhost', $url->host());
|
||||
$this->assertEquals(8080, $url->port());
|
||||
$this->assertEquals('user', $url->user());
|
||||
$this->assertEquals('password', $url->pass());
|
||||
$this->assertEquals('/path', $url->path());
|
||||
$this->assertEquals('q=value', $url->query());
|
||||
$this->assertEquals('fragment', $url->fragment());
|
||||
}
|
||||
}
|
||||
73
web/documentserver-example/php/common/URLJoinPathTests.php
Normal file
73
web/documentserver-example/php/common/URLJoinPathTests.php
Normal file
@ -0,0 +1,73 @@
|
||||
<?php
|
||||
//
|
||||
// (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.
|
||||
//
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use OnlineEditorsExamplePhp\Common\URL;
|
||||
|
||||
final class URLJoinPathTests extends TestCase {
|
||||
public function test_joins_a_relative_to_an_empty_one() {
|
||||
$url = new URL('http://localhost');
|
||||
$joined = $url->join_path('first');
|
||||
$this->assertEquals('http', $joined->scheme());
|
||||
$this->assertEquals('localhost', $joined->host());
|
||||
$this->assertEquals(null, $joined->port());
|
||||
$this->assertEquals(null, $joined->user());
|
||||
$this->assertEquals(null, $joined->pass());
|
||||
$this->assertEquals('/first', $joined->path());
|
||||
$this->assertEquals(null, $joined->query());
|
||||
$this->assertEquals(null, $joined->fragment());
|
||||
}
|
||||
|
||||
public function test_joins_a_relative() {
|
||||
$url = new URL('http://localhost/first');
|
||||
$joined = $url->join_path('second');
|
||||
$this->assertEquals('http', $joined->scheme());
|
||||
$this->assertEquals('localhost', $joined->host());
|
||||
$this->assertEquals(null, $joined->port());
|
||||
$this->assertEquals(null, $joined->user());
|
||||
$this->assertEquals(null, $joined->pass());
|
||||
$this->assertEquals('/first/second', $joined->path());
|
||||
$this->assertEquals(null, $joined->query());
|
||||
$this->assertEquals(null, $joined->fragment());
|
||||
}
|
||||
|
||||
public function test_joins_an_absolute_to_an_empty_one() {
|
||||
$url = new URL('http://localhost');
|
||||
$joined = $url->join_path('/first');
|
||||
$this->assertEquals('http', $joined->scheme());
|
||||
$this->assertEquals('localhost', $joined->host());
|
||||
$this->assertEquals(null, $joined->port());
|
||||
$this->assertEquals(null, $joined->user());
|
||||
$this->assertEquals(null, $joined->pass());
|
||||
$this->assertEquals('/first', $joined->path());
|
||||
$this->assertEquals(null, $joined->query());
|
||||
$this->assertEquals(null, $joined->fragment());
|
||||
}
|
||||
|
||||
public function test_joins_an_absolute() {
|
||||
$url = new URL('http://localhost/first');
|
||||
$joined = $url->join_path('/second');
|
||||
$this->assertEquals('http', $joined->scheme());
|
||||
$this->assertEquals('localhost', $joined->host());
|
||||
$this->assertEquals(null, $joined->port());
|
||||
$this->assertEquals(null, $joined->user());
|
||||
$this->assertEquals(null, $joined->pass());
|
||||
$this->assertEquals('/first/second', $joined->path());
|
||||
$this->assertEquals(null, $joined->query());
|
||||
$this->assertEquals(null, $joined->fragment());
|
||||
}
|
||||
}
|
||||
30
web/documentserver-example/php/common/URLStringTests.php
Normal file
30
web/documentserver-example/php/common/URLStringTests.php
Normal file
@ -0,0 +1,30 @@
|
||||
<?php
|
||||
//
|
||||
// (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.
|
||||
//
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use OnlineEditorsExamplePhp\Common\URL;
|
||||
|
||||
final class URLStringTests extends TestCase {
|
||||
public function test_generates() {
|
||||
$url = new URL('http://user:password@localhost:8080/path?q=value#fragment');
|
||||
$string = $url->string();
|
||||
$this->assertEquals(
|
||||
'http://user:password@localhost:8080/path?q=value#fragment',
|
||||
$string
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -1,26 +1,19 @@
|
||||
{
|
||||
"require": {
|
||||
"ext-mbstring": "*",
|
||||
"firebase/php-jwt": "^6.8.1"
|
||||
},
|
||||
"require-dev": {
|
||||
"squizlabs/php_codesniffer": "*",
|
||||
"ext-mbstring": "*"
|
||||
"squizlabs/php_codesniffer": "^3.7.2",
|
||||
"phpunit/phpunit": "^10.2.6"
|
||||
},
|
||||
"scripts": {
|
||||
"code-sniffer": [
|
||||
"./vendor/bin/phpcs --config-set default_standard ruleset.xml",
|
||||
"./vendor/bin/phpcs --config-set colors 1"
|
||||
],
|
||||
"post-install-cmd": [
|
||||
"@code-sniffer"
|
||||
],
|
||||
"post-update-cmd": [
|
||||
"@code-sniffer"
|
||||
]
|
||||
},
|
||||
"autoload-dev": {
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"OnlineEditorsExamplePhp\\" : "",
|
||||
"OnlineEditorsExamplePhp\\Common\\": "common/",
|
||||
"OnlineEditorsExamplePhp\\Configuration\\" : "configuration/",
|
||||
"OnlineEditorsExamplePhp\\Helpers\\" : "helpers/",
|
||||
"OnlineEditorsExamplePhp\\Views\\" : "views/",
|
||||
"Firebase\\JWT\\" : "lib/jwt/"
|
||||
"OnlineEditorsExamplePhp\\Views\\" : "views/"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
1701
web/documentserver-example/php/composer.lock
generated
1701
web/documentserver-example/php/composer.lock
generated
File diff suppressed because it is too large
Load Diff
@ -1,66 +0,0 @@
|
||||
{
|
||||
"version": "1.6.0",
|
||||
|
||||
"fileSizeMax": 5242880,
|
||||
"storagePath": "",
|
||||
"alone": false,
|
||||
|
||||
"docServTimeout": "120000",
|
||||
"docServSiteUrl": "https://documentserver/",
|
||||
|
||||
"docServConverterUrl": "ConvertService.ashx",
|
||||
"docServApiUrl": "web-apps/apps/api/documents/api.js",
|
||||
"docServPreloaderUrl": "web-apps/apps/api/documents/cache-scripts.html",
|
||||
"docServCommandUrl": "coauthoring/CommandService.ashx",
|
||||
|
||||
"docServJwtSecret": "",
|
||||
"docServJwtHeader": "Authorization",
|
||||
"docServJwtUseForRequest": true,
|
||||
|
||||
"docServVerifyPeerOff": true,
|
||||
|
||||
"exampleUrl": "",
|
||||
"mobileRegex": "android|avantgo|playbook|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od|ad)|iris|kindle|lge |maemo|midp|mmp|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\\/|plucker|pocket|psp|symbian|treo|up\\.(browser|link)|vodafone|wap|windows (ce|phone)|xda|xiino",
|
||||
"languages": {
|
||||
"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"
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,177 @@
|
||||
<?php
|
||||
//
|
||||
// (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.
|
||||
//
|
||||
|
||||
namespace OnlineEditorsExamplePhp\Configuration;
|
||||
|
||||
use OnlineEditorsExamplePhp\Common\Path;
|
||||
use OnlineEditorsExamplePhp\Common\URL;
|
||||
|
||||
final class ConfigurationManager {
|
||||
public string $version = '1.6.0';
|
||||
|
||||
public function example_url(): ?URL {
|
||||
$url = getenv('EXAMPLE_URL');
|
||||
if (!$url) {
|
||||
return null;
|
||||
}
|
||||
return new URL($url);
|
||||
}
|
||||
|
||||
public function document_server_url(): URL {
|
||||
$url = getenv('DOCUMENT_SERVER_URL') ?: 'http://document-server';
|
||||
return new URL($url);
|
||||
}
|
||||
|
||||
public function document_server_api_url(): URL {
|
||||
$server_url = $this->document_server_url();
|
||||
$path = getenv('DOCUMENT_SERVER_API_PATH')
|
||||
?: 'web-apps/apps/api/documents/api.js';
|
||||
return $server_url->join_path($path);
|
||||
}
|
||||
|
||||
public function document_server_preloader_url(): URL {
|
||||
$server_url = $this->document_server_url();
|
||||
$path = getenv('DOCUMENT_SERVER_PRELOADER_PATH')
|
||||
?: 'web-apps/apps/api/documents/cache-scripts.html';
|
||||
return $server_url->join_path($path);
|
||||
}
|
||||
|
||||
public function document_server_command_url(): URL {
|
||||
$server_url = $this->document_server_url();
|
||||
$path = getenv('DOCUMENT_SERVER_COMMAND_PATH')
|
||||
?: 'coauthoring/CommandService.ashx';
|
||||
return $server_url->join_path($path);
|
||||
}
|
||||
|
||||
public function document_server_converter_url(): URL {
|
||||
$server_url = $this->document_server_url();
|
||||
$path = getenv('DOCUMENT_SERVER_CONVERTER_PATH')
|
||||
?: 'ConvertService.ashx';
|
||||
return $server_url->join_path($path);
|
||||
}
|
||||
|
||||
public function jwt_secret(): string {
|
||||
return getenv('JWT_SECRET') ?: '';
|
||||
}
|
||||
|
||||
public function jwt_header(): string {
|
||||
return getenv('JWT_HEADER') ?: 'Authorization';
|
||||
}
|
||||
|
||||
public function jwt_use_for_request(): bool {
|
||||
$use = getenv('JWT_USE_FOR_REQUEST');
|
||||
if (!$use) {
|
||||
return true;
|
||||
}
|
||||
return filter_var($use, FILTER_VALIDATE_BOOLEAN);
|
||||
}
|
||||
|
||||
public function ssl_verify_peer_mode_enabled(): bool {
|
||||
$enabled = getenv('SSL_VERIFY_PEER_MODE_ENABLED');
|
||||
if (!$enabled) {
|
||||
return false;
|
||||
}
|
||||
return filter_var($enabled, FILTER_VALIDATE_BOOLEAN);
|
||||
}
|
||||
|
||||
public function storage_path(): Path {
|
||||
$storage_path = getenv('STORAGE_PATH') ?: 'storage';
|
||||
$storage_directory = new Path($storage_path);
|
||||
if ($storage_directory->absolute()) {
|
||||
return $storage_directory;
|
||||
}
|
||||
|
||||
$storage_string_directory = $storage_directory->string();
|
||||
$current_directory = new Path(__DIR__);
|
||||
$directory = $current_directory
|
||||
->join_path('..')
|
||||
->join_path($storage_string_directory);
|
||||
return $directory->normalize();
|
||||
}
|
||||
|
||||
public function single_user(): bool {
|
||||
$single = getenv('SINGLE_USER');
|
||||
if (!$single) {
|
||||
return false;
|
||||
}
|
||||
return filter_var($single, FILTER_VALIDATE_BOOLEAN);
|
||||
}
|
||||
|
||||
public function maximum_file_size(): int {
|
||||
$size = getenv('MAXIMUM_FILE_SIZE');
|
||||
if (!$size) {
|
||||
return 5 * 1024 * 1024;
|
||||
}
|
||||
return intval($size);
|
||||
}
|
||||
|
||||
public function conversion_timeout(): int {
|
||||
$timeout = getenv('CONVERSION_TIMEOUT');
|
||||
if (!$timeout) {
|
||||
return 120 * 1000;
|
||||
}
|
||||
return intval($timeout);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string[]
|
||||
*/
|
||||
public function languages(): array {
|
||||
return [
|
||||
'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'
|
||||
];
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,47 @@
|
||||
<?php
|
||||
//
|
||||
// (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.
|
||||
//
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use OnlineEditorsExamplePhp\Configuration\ConfigurationManager;
|
||||
|
||||
final class ConfigurationManagerConversionTimeoutTests extends TestCase {
|
||||
public array $env;
|
||||
|
||||
public function __construct(string $name) {
|
||||
$this->env = getenv();
|
||||
parent::__construct($name);
|
||||
}
|
||||
|
||||
protected function setUp(): void {
|
||||
foreach ($this->env as $key => $value) {
|
||||
putenv("{$key}={$value}");
|
||||
}
|
||||
}
|
||||
|
||||
public function test_assigns_a_default_value() {
|
||||
$config_manager = new ConfigurationManager();
|
||||
$timeout = $config_manager->conversion_timeout();
|
||||
$this->assertEquals(120_000, $timeout);
|
||||
}
|
||||
|
||||
public function test_assigns_a_value_from_the_environment() {
|
||||
putenv('CONVERSION_TIMEOUT=10');
|
||||
$config_manager = new ConfigurationManager();
|
||||
$timeout = $config_manager->conversion_timeout();
|
||||
$this->assertEquals(10, $timeout);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,53 @@
|
||||
<?php
|
||||
//
|
||||
// (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.
|
||||
//
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use OnlineEditorsExamplePhp\Configuration\ConfigurationManager;
|
||||
|
||||
final class ConfigurationManagerDocumentServerAPIURLTests extends TestCase {
|
||||
public array $env;
|
||||
|
||||
public function __construct(string $name) {
|
||||
$this->env = getenv();
|
||||
parent::__construct($name);
|
||||
}
|
||||
|
||||
protected function setUp(): void {
|
||||
foreach ($this->env as $key => $value) {
|
||||
putenv("{$key}={$value}");
|
||||
}
|
||||
}
|
||||
|
||||
public function test_assigns_a_default_value() {
|
||||
$config_manager = new ConfigurationManager();
|
||||
$url = $config_manager->document_server_api_url();
|
||||
$this->assertEquals(
|
||||
'http://document-server/web-apps/apps/api/documents/api.js',
|
||||
$url->string()
|
||||
);
|
||||
}
|
||||
|
||||
public function test_assigns_a_value_from_the_environment() {
|
||||
putenv('DOCUMENT_SERVER_API_PATH=/api');
|
||||
$config_manager = new ConfigurationManager();
|
||||
$url = $config_manager->document_server_api_url();
|
||||
$this->assertEquals(
|
||||
'http://document-server/api',
|
||||
$url->string()
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,53 @@
|
||||
<?php
|
||||
//
|
||||
// (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.
|
||||
//
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use OnlineEditorsExamplePhp\Configuration\ConfigurationManager;
|
||||
|
||||
final class ConfigurationManagerDocumentServerCommandURLTests extends TestCase {
|
||||
public array $env;
|
||||
|
||||
public function __construct(string $name) {
|
||||
$this->env = getenv();
|
||||
parent::__construct($name);
|
||||
}
|
||||
|
||||
protected function setUp(): void {
|
||||
foreach ($this->env as $key => $value) {
|
||||
putenv("{$key}={$value}");
|
||||
}
|
||||
}
|
||||
|
||||
public function test_assigns_a_default_value() {
|
||||
$config_manager = new ConfigurationManager();
|
||||
$url = $config_manager->document_server_command_url();
|
||||
$this->assertEquals(
|
||||
'http://document-server/coauthoring/CommandService.ashx',
|
||||
$url->string()
|
||||
);
|
||||
}
|
||||
|
||||
public function test_assigns_a_value_from_the_environment() {
|
||||
putenv('DOCUMENT_SERVER_COMMAND_PATH=/command');
|
||||
$config_manager = new ConfigurationManager();
|
||||
$url = $config_manager->document_server_command_url();
|
||||
$this->assertEquals(
|
||||
'http://document-server/command',
|
||||
$url->string()
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,53 @@
|
||||
<?php
|
||||
//
|
||||
// (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.
|
||||
//
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use OnlineEditorsExamplePhp\Configuration\ConfigurationManager;
|
||||
|
||||
final class ConfigurationManagerDocumentServerConverterURLTests extends TestCase {
|
||||
public array $env;
|
||||
|
||||
public function __construct(string $name) {
|
||||
$this->env = getenv();
|
||||
parent::__construct($name);
|
||||
}
|
||||
|
||||
protected function setUp(): void {
|
||||
foreach ($this->env as $key => $value) {
|
||||
putenv("{$key}={$value}");
|
||||
}
|
||||
}
|
||||
|
||||
public function test_assigns_a_default_value() {
|
||||
$config_manager = new ConfigurationManager();
|
||||
$url = $config_manager->document_server_converter_url();
|
||||
$this->assertEquals(
|
||||
'http://document-server/ConvertService.ashx',
|
||||
$url->string()
|
||||
);
|
||||
}
|
||||
|
||||
public function test_assigns_a_value_from_the_environment() {
|
||||
putenv('DOCUMENT_SERVER_CONVERTER_PATH=/converter');
|
||||
$config_manager = new ConfigurationManager();
|
||||
$url = $config_manager->document_server_converter_url();
|
||||
$this->assertEquals(
|
||||
'http://document-server/converter',
|
||||
$url->string()
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,53 @@
|
||||
<?php
|
||||
//
|
||||
// (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.
|
||||
//
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use OnlineEditorsExamplePhp\Configuration\ConfigurationManager;
|
||||
|
||||
final class ConfigurationManagerDocumentServerPreloaderURLTests extends TestCase {
|
||||
public array $env;
|
||||
|
||||
public function __construct(string $name) {
|
||||
$this->env = getenv();
|
||||
parent::__construct($name);
|
||||
}
|
||||
|
||||
protected function setUp(): void {
|
||||
foreach ($this->env as $key => $value) {
|
||||
putenv("{$key}={$value}");
|
||||
}
|
||||
}
|
||||
|
||||
public function test_assigns_a_default_value() {
|
||||
$config_manager = new ConfigurationManager();
|
||||
$url = $config_manager->document_server_preloader_url();
|
||||
$this->assertEquals(
|
||||
'http://document-server/web-apps/apps/api/documents/cache-scripts.html',
|
||||
$url->string()
|
||||
);
|
||||
}
|
||||
|
||||
public function test_assigns_a_value_from_the_environment() {
|
||||
putenv('DOCUMENT_SERVER_PRELOADER_PATH=/preloader');
|
||||
$config_manager = new ConfigurationManager();
|
||||
$url = $config_manager->document_server_preloader_url();
|
||||
$this->assertEquals(
|
||||
'http://document-server/preloader',
|
||||
$url->string()
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,47 @@
|
||||
<?php
|
||||
//
|
||||
// (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.
|
||||
//
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use OnlineEditorsExamplePhp\Configuration\ConfigurationManager;
|
||||
|
||||
final class ConfigurationManagerDocumentServerURLTests extends TestCase {
|
||||
public array $env;
|
||||
|
||||
public function __construct(string $name) {
|
||||
$this->env = getenv();
|
||||
parent::__construct($name);
|
||||
}
|
||||
|
||||
protected function setUp(): void {
|
||||
foreach ($this->env as $key => $value) {
|
||||
putenv("{$key}={$value}");
|
||||
}
|
||||
}
|
||||
|
||||
public function test_assigns_a_default_value() {
|
||||
$config_manager = new ConfigurationManager();
|
||||
$url = $config_manager->document_server_url();
|
||||
$this->assertEquals('http://document-server', $url->string());
|
||||
}
|
||||
|
||||
public function test_assigns_a_value_from_the_environment() {
|
||||
putenv('DOCUMENT_SERVER_URL=http://localhost');
|
||||
$config_manager = new ConfigurationManager();
|
||||
$url = $config_manager->document_server_url();
|
||||
$this->assertEquals('http://localhost', $url->string());
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,47 @@
|
||||
<?php
|
||||
//
|
||||
// (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.
|
||||
//
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use OnlineEditorsExamplePhp\Configuration\ConfigurationManager;
|
||||
|
||||
final class ConfigurationManagerExampleURLTests extends TestCase {
|
||||
public array $env;
|
||||
|
||||
public function __construct(string $name) {
|
||||
$this->env = getenv();
|
||||
parent::__construct($name);
|
||||
}
|
||||
|
||||
protected function setUp(): void {
|
||||
foreach ($this->env as $key => $value) {
|
||||
putenv("{$key}={$value}");
|
||||
}
|
||||
}
|
||||
|
||||
public function test_assigns_a_default_value() {
|
||||
$config_manager = new ConfigurationManager();
|
||||
$url = $config_manager->example_url();
|
||||
$this->assertNull($url);
|
||||
}
|
||||
|
||||
public function test_assigns_a_value_from_the_environment() {
|
||||
putenv('EXAMPLE_URL=http://localhost');
|
||||
$config_manager = new ConfigurationManager();
|
||||
$url = $config_manager->example_url();
|
||||
$this->assertEquals('http://localhost', $url->string());
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,47 @@
|
||||
<?php
|
||||
//
|
||||
// (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.
|
||||
//
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use OnlineEditorsExamplePhp\Configuration\ConfigurationManager;
|
||||
|
||||
final class ConfigurationManagerJWTHeaderTests extends TestCase {
|
||||
public array $env;
|
||||
|
||||
public function __construct(string $name) {
|
||||
$this->env = getenv();
|
||||
parent::__construct($name);
|
||||
}
|
||||
|
||||
protected function setUp(): void {
|
||||
foreach ($this->env as $key => $value) {
|
||||
putenv("{$key}={$value}");
|
||||
}
|
||||
}
|
||||
|
||||
public function test_assigns_a_default_value() {
|
||||
$config_manager = new ConfigurationManager();
|
||||
$header = $config_manager->jwt_header();
|
||||
$this->assertEquals('Authorization', $header);
|
||||
}
|
||||
|
||||
public function test_assigns_a_value_from_the_environment() {
|
||||
putenv('JWT_HEADER=Proxy-Authorization');
|
||||
$config_manager = new ConfigurationManager();
|
||||
$header = $config_manager->jwt_header();
|
||||
$this->assertEquals('Proxy-Authorization', $header);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,47 @@
|
||||
<?php
|
||||
//
|
||||
// (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.
|
||||
//
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use OnlineEditorsExamplePhp\Configuration\ConfigurationManager;
|
||||
|
||||
final class ConfigurationManagerJWTSecretTests extends TestCase {
|
||||
public array $env;
|
||||
|
||||
public function __construct(string $name) {
|
||||
$this->env = getenv();
|
||||
parent::__construct($name);
|
||||
}
|
||||
|
||||
protected function setUp(): void {
|
||||
foreach ($this->env as $key => $value) {
|
||||
putenv("{$key}={$value}");
|
||||
}
|
||||
}
|
||||
|
||||
public function test_assigns_a_default_value() {
|
||||
$config_manager = new ConfigurationManager();
|
||||
$secret = $config_manager->jwt_secret();
|
||||
$this->assertEquals('', $secret);
|
||||
}
|
||||
|
||||
public function test_assigns_a_value_from_the_environment() {
|
||||
putenv('JWT_SECRET=your-256-bit-secret');
|
||||
$config_manager = new ConfigurationManager();
|
||||
$secret = $config_manager->jwt_secret();
|
||||
$this->assertEquals('your-256-bit-secret', $secret);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,47 @@
|
||||
<?php
|
||||
//
|
||||
// (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.
|
||||
//
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use OnlineEditorsExamplePhp\Configuration\ConfigurationManager;
|
||||
|
||||
final class ConfigurationManagerJWTUseForRequest extends TestCase {
|
||||
public array $env;
|
||||
|
||||
public function __construct(string $name) {
|
||||
$this->env = getenv();
|
||||
parent::__construct($name);
|
||||
}
|
||||
|
||||
protected function setUp(): void {
|
||||
foreach ($this->env as $key => $value) {
|
||||
putenv("{$key}={$value}");
|
||||
}
|
||||
}
|
||||
|
||||
public function test_assigns_a_default_value() {
|
||||
$config_manager = new ConfigurationManager();
|
||||
$use = $config_manager->jwt_use_for_request();
|
||||
$this->assertTrue($use);
|
||||
}
|
||||
|
||||
public function test_assigns_a_value_from_the_environment() {
|
||||
putenv('JWT_USE_FOR_REQUEST=false');
|
||||
$config_manager = new ConfigurationManager();
|
||||
$use = $config_manager->jwt_use_for_request();
|
||||
$this->assertFalse($use);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,47 @@
|
||||
<?php
|
||||
//
|
||||
// (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.
|
||||
//
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use OnlineEditorsExamplePhp\Configuration\ConfigurationManager;
|
||||
|
||||
final class ConfigurationManagerMaximumFileSizeTests extends TestCase {
|
||||
public array $env;
|
||||
|
||||
public function __construct(string $name) {
|
||||
$this->env = getenv();
|
||||
parent::__construct($name);
|
||||
}
|
||||
|
||||
protected function setUp(): void {
|
||||
foreach ($this->env as $key => $value) {
|
||||
putenv("{$key}={$value}");
|
||||
}
|
||||
}
|
||||
|
||||
public function test_assigns_a_default_value() {
|
||||
$config_manager = new ConfigurationManager();
|
||||
$size = $config_manager->maximum_file_size();
|
||||
$this->assertEquals(5_242_880, $size);
|
||||
}
|
||||
|
||||
public function test_assigns_a_value_from_the_environment() {
|
||||
putenv('MAXIMUM_FILE_SIZE=10');
|
||||
$config_manager = new ConfigurationManager();
|
||||
$size = $config_manager->maximum_file_size();
|
||||
$this->assertEquals(10, $size);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,47 @@
|
||||
<?php
|
||||
//
|
||||
// (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.
|
||||
//
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use OnlineEditorsExamplePhp\Configuration\ConfigurationManager;
|
||||
|
||||
final class ConfigurationManagerSSLTests extends TestCase {
|
||||
public array $env;
|
||||
|
||||
public function __construct(string $name) {
|
||||
$this->env = getenv();
|
||||
parent::__construct($name);
|
||||
}
|
||||
|
||||
protected function setUp(): void {
|
||||
foreach ($this->env as $key => $value) {
|
||||
putenv("{$key}={$value}");
|
||||
}
|
||||
}
|
||||
|
||||
public function test_assigns_a_default_value() {
|
||||
$config_manager = new ConfigurationManager();
|
||||
$enabled = $config_manager->ssl_verify_peer_mode_enabled();
|
||||
$this->assertFalse($enabled);
|
||||
}
|
||||
|
||||
public function test_assigns_a_value_from_the_environment() {
|
||||
putenv('SSL_VERIFY_PEER_MODE_ENABLED=true');
|
||||
$config_manager = new ConfigurationManager();
|
||||
$enabled = $config_manager->ssl_verify_peer_mode_enabled();
|
||||
$this->assertTrue($enabled);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,47 @@
|
||||
<?php
|
||||
//
|
||||
// (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.
|
||||
//
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use OnlineEditorsExamplePhp\Configuration\ConfigurationManager;
|
||||
|
||||
final class ConfigurationManagerSingleUserTests extends TestCase {
|
||||
public array $env;
|
||||
|
||||
public function __construct(string $name) {
|
||||
$this->env = getenv();
|
||||
parent::__construct($name);
|
||||
}
|
||||
|
||||
protected function setUp(): void {
|
||||
foreach ($this->env as $key => $value) {
|
||||
putenv("{$key}={$value}");
|
||||
}
|
||||
}
|
||||
|
||||
public function test_assigns_a_default_value() {
|
||||
$config_manager = new ConfigurationManager();
|
||||
$single = $config_manager->single_user();
|
||||
$this->assertFalse($single);
|
||||
}
|
||||
|
||||
public function test_assigns_a_value_from_the_environment() {
|
||||
putenv('SINGLE_USER=true');
|
||||
$config_manager = new ConfigurationManager();
|
||||
$single = $config_manager->single_user();
|
||||
$this->assertTrue($single);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,56 @@
|
||||
<?php
|
||||
//
|
||||
// (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.
|
||||
//
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use OnlineEditorsExamplePhp\Configuration\ConfigurationManager;
|
||||
|
||||
final class ConfigurationManagerStoragePathTests extends TestCase {
|
||||
public array $env;
|
||||
|
||||
public function __construct(string $name) {
|
||||
$this->env = getenv();
|
||||
parent::__construct($name);
|
||||
}
|
||||
|
||||
protected function setUp(): void {
|
||||
foreach ($this->env as $key => $value) {
|
||||
putenv("{$key}={$value}");
|
||||
}
|
||||
}
|
||||
|
||||
public function test_assigns_a_default_value() {
|
||||
$config_manager = new ConfigurationManager();
|
||||
$path = $config_manager->storage_path();
|
||||
$this->assertTrue($path->absolute());
|
||||
$this->assertEquals($path->basename(), 'storage');
|
||||
}
|
||||
|
||||
public function test_assigns_a_relative_path_from_the_environment() {
|
||||
putenv('STORAGE_PATH=directory');
|
||||
$config_manager = new ConfigurationManager();
|
||||
$path = $config_manager->storage_path();
|
||||
$this->assertTrue($path->absolute());
|
||||
$this->assertEquals($path->basename(), 'directory');
|
||||
}
|
||||
|
||||
public function test_assigns_an_absolute_path_from_the_environment() {
|
||||
putenv('STORAGE_PATH=/directory');
|
||||
$config_manager = new ConfigurationManager();
|
||||
$path = $config_manager->storage_path();
|
||||
$this->assertEquals($path->string(), '/directory');
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,26 @@
|
||||
<?php
|
||||
//
|
||||
// (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.
|
||||
//
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use OnlineEditorsExamplePhp\Configuration\ConfigurationManager;
|
||||
|
||||
final class ConfigurationManagerTests extends TestCase {
|
||||
public function test_corresponds_the_latest_version() {
|
||||
$config_manager = new ConfigurationManager();
|
||||
$this->assertEquals('1.6.0', $config_manager->version);
|
||||
}
|
||||
}
|
||||
@ -1,26 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* (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.
|
||||
*/
|
||||
|
||||
namespace OnlineEditorsExamplePhp;
|
||||
|
||||
use OnlineEditorsExamplePhp\Views\DocEditorView;
|
||||
|
||||
require_once dirname(__FILE__) . '/functions.php';
|
||||
require_once dirname(__FILE__) . '/vendor/autoload.php';
|
||||
|
||||
$docEditorView = new DocEditorView($_REQUEST);
|
||||
$docEditorView->render();
|
||||
@ -18,6 +18,7 @@
|
||||
namespace OnlineEditorsExamplePhp;
|
||||
|
||||
use Exception;
|
||||
use OnlineEditorsExamplePhp\Configuration\ConfigurationManager;
|
||||
use OnlineEditorsExamplePhp\Helpers\ConfigManager;
|
||||
use OnlineEditorsExamplePhp\Helpers\ExampleUsers;
|
||||
use OnlineEditorsExamplePhp\Helpers\JwtManager;
|
||||
@ -92,10 +93,10 @@ function getClientIp()
|
||||
*/
|
||||
function serverPath($forDocumentServer = null)
|
||||
{
|
||||
$configManager = new ConfigManager();
|
||||
return $forDocumentServer && $configManager->getConfig("storagePath") != null
|
||||
&& $configManager->getConfig("exampleUrl") != ""
|
||||
? $configManager->getConfig("exampleUrl")
|
||||
$config_manager = new ConfigurationManager();
|
||||
$example_url = $config_manager->example_url();
|
||||
return $forDocumentServer && $example_url
|
||||
? $example_url->string()
|
||||
: (getScheme() . '://' . $_SERVER['HTTP_HOST']);
|
||||
}
|
||||
|
||||
@ -108,11 +109,8 @@ function serverPath($forDocumentServer = null)
|
||||
*/
|
||||
function getCurUserHostAddress($userAddress = null)
|
||||
{
|
||||
$configManager = new ConfigManager();
|
||||
if ($configManager->getConfig("alone")) {
|
||||
if (empty($configManager->getConfig("storagePath"))) {
|
||||
return "Storage";
|
||||
}
|
||||
$config_manager = new ConfigurationManager();
|
||||
if ($config_manager->single_user()) {
|
||||
return "";
|
||||
}
|
||||
if (is_null($userAddress)) {
|
||||
@ -222,39 +220,21 @@ function getScheme()
|
||||
*/
|
||||
function getStoragePath($fileName, $userAddress = null)
|
||||
{
|
||||
$configManager = new ConfigManager();
|
||||
$storagePath = trim(
|
||||
str_replace(['/', '\\'], DIRECTORY_SEPARATOR, $configManager->getConfig("storagePath")),
|
||||
DIRECTORY_SEPARATOR
|
||||
);
|
||||
if (!empty($storagePath) && !file_exists($storagePath) && !is_dir($storagePath)) {
|
||||
mkdir($storagePath);
|
||||
$config_manager = new ConfigurationManager();
|
||||
$storage_path = $config_manager->storage_path();
|
||||
|
||||
if (!$storage_path->exists()) {
|
||||
$storage_path->make_directory();
|
||||
}
|
||||
|
||||
if (realpath($storagePath) === $storagePath) {
|
||||
$directory = $storagePath;
|
||||
} else {
|
||||
$directory = __DIR__ . DIRECTORY_SEPARATOR . $storagePath;
|
||||
$user_ip = getCurUserHostAddress($userAddress);
|
||||
$user_directory = $storage_path->join_path($user_ip);
|
||||
if (!$user_directory->exists()) {
|
||||
$user_directory->make_directory();
|
||||
}
|
||||
|
||||
if ($storagePath != "") {
|
||||
$directory = $directory . DIRECTORY_SEPARATOR;
|
||||
|
||||
// if the file directory doesn't exist, make it
|
||||
if (!file_exists($directory) && !is_dir($directory)) {
|
||||
mkdir($directory);
|
||||
}
|
||||
}
|
||||
|
||||
if (realpath($storagePath) !== $storagePath) {
|
||||
$directory = $directory . getCurUserHostAddress($userAddress) . DIRECTORY_SEPARATOR;
|
||||
}
|
||||
|
||||
if (!file_exists($directory) && !is_dir($directory)) {
|
||||
mkdir($directory);
|
||||
}
|
||||
sendlog("getStoragePath result: " . $directory . basename($fileName), "common.log");
|
||||
return realpath($storagePath) === $storagePath ? $directory . $fileName : $directory . basename($fileName);
|
||||
$file = $user_directory->join_path($fileName);
|
||||
return $file->string();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -268,43 +248,30 @@ function getStoragePath($fileName, $userAddress = null)
|
||||
*/
|
||||
function getForcesavePath($fileName, $userAddress, $create)
|
||||
{
|
||||
$configManager = new ConfigManager();
|
||||
$storagePath = trim(
|
||||
str_replace(
|
||||
['/', '\\'],
|
||||
DIRECTORY_SEPARATOR,
|
||||
$configManager->getConfig("storagePath")
|
||||
),
|
||||
DIRECTORY_SEPARATOR
|
||||
);
|
||||
$config_manager = new ConfigurationManager();
|
||||
$storage_path = $config_manager->storage_path();
|
||||
|
||||
// create the directory to this file version
|
||||
if (realpath($storagePath) === $storagePath) {
|
||||
$directory = $storagePath . DIRECTORY_SEPARATOR;
|
||||
} else {
|
||||
$directory = __DIR__ . DIRECTORY_SEPARATOR . $storagePath . getCurUserHostAddress($userAddress) .
|
||||
DIRECTORY_SEPARATOR;
|
||||
$user_ip = getCurUserHostAddress($userAddress);
|
||||
$user_directory = $storage_path->join_path($user_ip);
|
||||
if (!$user_directory->exists()) {
|
||||
return '';
|
||||
}
|
||||
|
||||
if (!is_dir($directory)) {
|
||||
return "";
|
||||
$history_directory = $user_directory->join_path("{$fileName}-hist");
|
||||
if (!$history_directory->exists()) {
|
||||
if ($create) {
|
||||
$history_directory->make_directory();
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
// create the directory to the history of this file version
|
||||
$directory = $directory . $fileName . "-hist" . DIRECTORY_SEPARATOR;
|
||||
if (!$create && !is_dir($directory)) {
|
||||
return "";
|
||||
$file = $history_directory->join_path($fileName);
|
||||
if (!$file->exists() && !$create) {
|
||||
return '';
|
||||
}
|
||||
|
||||
if (!file_exists($directory) && !is_dir($directory)) {
|
||||
mkdir($directory);
|
||||
}
|
||||
$directory = $directory . $fileName;
|
||||
if (!$create && !file_exists($directory)) {
|
||||
return "";
|
||||
}
|
||||
|
||||
return $directory;
|
||||
return $file->string();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -370,38 +337,21 @@ function getFileVersion($histDir)
|
||||
function getStoredFiles()
|
||||
{
|
||||
$configManager = new ConfigManager();
|
||||
$storagePath = trim(str_replace(
|
||||
['/', '\\'],
|
||||
DIRECTORY_SEPARATOR,
|
||||
$configManager->getConfig("storagePath")
|
||||
), DIRECTORY_SEPARATOR);
|
||||
if (!empty($storagePath) && !file_exists($storagePath) && !is_dir($storagePath)) {
|
||||
mkdir($storagePath);
|
||||
|
||||
$config_manager = new ConfigurationManager();
|
||||
$storage_path = $config_manager->storage_path();
|
||||
|
||||
if (!$storage_path->exists()) {
|
||||
$storage_path->make_directory();
|
||||
}
|
||||
|
||||
if (realpath($storagePath) === $storagePath) {
|
||||
$directory = $storagePath;
|
||||
} else {
|
||||
$directory = __DIR__ . DIRECTORY_SEPARATOR . $storagePath;
|
||||
$user_ip = getCurUserHostAddress();
|
||||
$user_directory = $storage_path->join_path($user_ip);
|
||||
if (!$user_directory->exists()) {
|
||||
$user_directory->make_directory();
|
||||
}
|
||||
|
||||
// get the storage path and check if it exists
|
||||
$result = [];
|
||||
if ($storagePath != "") {
|
||||
$directory = $directory . DIRECTORY_SEPARATOR;
|
||||
|
||||
if (!file_exists($directory) && !is_dir($directory)) {
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
|
||||
if (realpath($storagePath) !== $storagePath) {
|
||||
$directory = $directory . getCurUserHostAddress() . DIRECTORY_SEPARATOR;
|
||||
}
|
||||
|
||||
if (!file_exists($directory) && !is_dir($directory)) {
|
||||
return $result;
|
||||
}
|
||||
$directory = $user_directory->string();
|
||||
|
||||
$cdir = scandir($directory); // get all the files and folders from the directory
|
||||
$result = [];
|
||||
@ -432,21 +382,8 @@ function getStoredFiles()
|
||||
*/
|
||||
function getVirtualPath($forDocumentServer)
|
||||
{
|
||||
$configManager = new ConfigManager();
|
||||
$storagePath = trim(str_replace(
|
||||
['/', '\\'],
|
||||
'/',
|
||||
$configManager->getConfig("storagePath")
|
||||
), '/');
|
||||
$storagePath = $storagePath != "" ? $storagePath . '/' : "";
|
||||
|
||||
if (realpath($storagePath) === $storagePath) {
|
||||
$virtPath = serverPath($forDocumentServer) . '/' . $storagePath . '/';
|
||||
} else {
|
||||
$virtPath = serverPath($forDocumentServer) . '/' . $storagePath . getCurUserHostAddress() . '/';
|
||||
}
|
||||
sendlog("getVirtualPath virtPath: " . $virtPath, "common.log");
|
||||
return $virtPath;
|
||||
$server_url = serverPath($forDocumentServer);
|
||||
return $server_url . '/' . getCurUserHostAddress() . '/';
|
||||
}
|
||||
|
||||
/**
|
||||
@ -689,6 +626,8 @@ function sendRequestToConvertService(
|
||||
$filePass,
|
||||
$lang
|
||||
) {
|
||||
$config_manager = new ConfigurationManager();
|
||||
|
||||
if (empty($from_extension)) {
|
||||
$path_parts = pathinfo($document_uri);
|
||||
$from_extension = mb_strtolower($path_parts['extension']);
|
||||
@ -707,9 +646,7 @@ function sendRequestToConvertService(
|
||||
// generate document token
|
||||
$document_revision_id = generateRevisionId($document_revision_id);
|
||||
|
||||
$configManager = new ConfigManager();
|
||||
$urlToConverter = $configManager->getConfig("docServSiteUrl").
|
||||
$configManager->getConfig("docServConverterUrl");
|
||||
$urlToConverter = $config_manager->document_server_converter_url()->string();
|
||||
|
||||
$arr = [
|
||||
"async" => $is_async,
|
||||
@ -724,8 +661,7 @@ function sendRequestToConvertService(
|
||||
|
||||
// add header token
|
||||
$headerToken = "";
|
||||
$jwtHeader = $configManager->getConfig("docServJwtHeader") ==
|
||||
"" ? "Authorization" : $configManager->getConfig("docServJwtHeader");
|
||||
$jwtHeader = $config_manager->jwt_header();
|
||||
|
||||
$jwtManager = new JwtManager();
|
||||
if ($jwtManager->isJwtEnabled() && $jwtManager->tokenUseForRequest()) {
|
||||
@ -738,7 +674,7 @@ function sendRequestToConvertService(
|
||||
// request parameters
|
||||
$opts = ['http' => [
|
||||
'method' => 'POST',
|
||||
'timeout' => $configManager->getConfig("docServTimeout"),
|
||||
'timeout' => $config_manager->conversion_timeout(),
|
||||
'header' => "Content-type: application/json\r\n" .
|
||||
"Accept: application/json\r\n" .
|
||||
(empty($headerToken) ? "" : $jwtHeader.": Bearer $headerToken\r\n"),
|
||||
@ -747,7 +683,7 @@ function sendRequestToConvertService(
|
||||
];
|
||||
|
||||
if (mb_substr($urlToConverter, 0, mb_strlen("https")) === "https") {
|
||||
if ($configManager->getConfig("docServVerifyPeerOff") === true) {
|
||||
if ($config_manager->ssl_verify_peer_mode_enabled()) {
|
||||
$opts['ssl'] = ['verify_peer' => false, 'verify_peer_name' => false];
|
||||
}
|
||||
}
|
||||
@ -890,7 +826,10 @@ function tryGetDefaultByType($createExt, $user)
|
||||
{
|
||||
$sample = isset($_GET["sample"]) && $_GET["sample"];
|
||||
$demoName = ($sample ? "sample." : "new.") . $createExt;
|
||||
$demoPath = "assets" . DIRECTORY_SEPARATOR . ($sample ? "sample" : "new") . DIRECTORY_SEPARATOR;
|
||||
$demoPath =
|
||||
"assets" . DIRECTORY_SEPARATOR .
|
||||
"document-templates" . DIRECTORY_SEPARATOR .
|
||||
($sample ? "sample" : "new") . DIRECTORY_SEPARATOR;
|
||||
$demoFilename = GetCorrectName($demoName);
|
||||
|
||||
if (!@copy(dirname(__FILE__) . DIRECTORY_SEPARATOR . $demoPath . $demoName, getStoragePath($demoFilename))) {
|
||||
@ -914,9 +853,8 @@ function tryGetDefaultByType($createExt, $user)
|
||||
function getCallbackUrl($fileName)
|
||||
{
|
||||
return serverPath(true) . '/'
|
||||
. "webeditor-ajax.php"
|
||||
. "?type=track"
|
||||
. "&fileName=" . urlencode($fileName)
|
||||
. "track"
|
||||
. "?fileName=" . urlencode($fileName)
|
||||
. "&userAddress=" . getClientIp();
|
||||
}
|
||||
|
||||
@ -933,10 +871,9 @@ function getCreateUrl($fileName, $uid, $type)
|
||||
{
|
||||
$ext = trim(getInternalExtension($fileName), '.');
|
||||
return serverPath(false) . '/'
|
||||
. "doceditor.php"
|
||||
. "editor"
|
||||
. "?fileExt=" . $ext
|
||||
. "&user=" . $uid
|
||||
. "&type=" . $type;
|
||||
. "&user=" . $uid;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -953,9 +890,8 @@ function getHistoryDownloadUrl($fileName, $version, $file, $isServer = true)
|
||||
{
|
||||
$userAddress = $isServer ? "&userAddress=" . getClientIp() : "";
|
||||
return serverPath($isServer) . '/'
|
||||
. "webeditor-ajax.php"
|
||||
. "?type=history"
|
||||
. "&fileName=" . urlencode($fileName)
|
||||
. "history"
|
||||
. "?fileName=" . urlencode($fileName)
|
||||
. "&ver=" . $version
|
||||
. "&file=" . urlencode($file)
|
||||
. $userAddress;
|
||||
@ -973,9 +909,8 @@ function getDownloadUrl($fileName, $isServer = true)
|
||||
{
|
||||
$userAddress = $isServer ? "&userAddress=" . getClientIp() : "";
|
||||
return serverPath($isServer) . '/'
|
||||
. "webeditor-ajax.php"
|
||||
. "?type=download"
|
||||
. "&fileName=" . urlencode($fileName)
|
||||
. "download"
|
||||
. "?fileName=" . urlencode($fileName)
|
||||
. $userAddress;
|
||||
}
|
||||
|
||||
@ -992,8 +927,6 @@ function getDownloadUrl($fileName, $isServer = true)
|
||||
*/
|
||||
function getHistory($filename, $filetype, $docKey, $fileuri, $isEnableDirectUrl)
|
||||
{
|
||||
$configManager = new ConfigManager();
|
||||
$storagePath = $configManager->getConfig("storagePath");
|
||||
$histDir = getHistoryDir(getStoragePath($filename)); // get the path to the file history
|
||||
|
||||
if (getFileVersion($histDir) > 0) { // check if the file was modified (the file version is greater than 0)
|
||||
@ -1034,13 +967,11 @@ function getHistory($filename, $filetype, $docKey, $fileuri, $isEnableDirectUrl)
|
||||
$directUrl = $i == $curVer ? fileUri($filename, false) :
|
||||
getHistoryDownloadUrl($filename, $i, "prev.".$fileExe, false);
|
||||
$prevFileUrl = $i == $curVer ? $fileuri : getHistoryDownloadUrl($filename, $i, "prev.".$fileExe);
|
||||
if (realpath($storagePath) === $storagePath) {
|
||||
$prevFileUrl = $i == $curVer ? getDownloadUrl($filename) :
|
||||
getHistoryDownloadUrl($filename, $i, "prev.".$fileExe);
|
||||
if ($isEnableDirectUrl) {
|
||||
$directUrl = $i == $curVer ? getDownloadUrl($filename, false) :
|
||||
getHistoryDownloadUrl($filename, $i, "prev.".$fileExe, false);
|
||||
}
|
||||
$prevFileUrl = $i == $curVer ? getDownloadUrl($filename) :
|
||||
getHistoryDownloadUrl($filename, $i, "prev.".$fileExe);
|
||||
if ($isEnableDirectUrl) {
|
||||
$directUrl = $i == $curVer ? getDownloadUrl($filename, false) :
|
||||
getHistoryDownloadUrl($filename, $i, "prev.".$fileExe, false);
|
||||
}
|
||||
|
||||
$dataObj["url"] = $prevFileUrl; // write file url to the data object
|
||||
|
||||
@ -20,20 +20,13 @@ namespace OnlineEditorsExamplePhp\Helpers;
|
||||
|
||||
final class ConfigManager
|
||||
{
|
||||
private mixed $config;
|
||||
private mixed $configFormats;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->config = json_decode($this->getConfigurationJson());
|
||||
$this->configFormats = json_decode($this->getConfigurationFromatsJson());
|
||||
}
|
||||
|
||||
private function getConfigurationJson(): bool|string
|
||||
{
|
||||
return file_exists("./config.json") ? file_get_contents("./config.json") : false;
|
||||
}
|
||||
|
||||
private function getConfigurationFromatsJson(): bool|string
|
||||
{
|
||||
return file_exists("./assets/document-formats/onlyoffice-docs-formats.json")
|
||||
@ -41,18 +34,6 @@ final class ConfigManager
|
||||
: false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string|null $configName
|
||||
* @return mixed
|
||||
*/
|
||||
public function getConfig(string $configName = null): mixed
|
||||
{
|
||||
if ($configName) {
|
||||
return $this->config->$configName ?? "";
|
||||
}
|
||||
return $this->config;
|
||||
}
|
||||
|
||||
public function getSuppotredFormats(): mixed
|
||||
{
|
||||
return $this->configFormats;
|
||||
|
||||
@ -18,6 +18,10 @@ namespace OnlineEditorsExamplePhp\Helpers;
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
use Firebase\JWT\JWT;
|
||||
use Firebase\JWT\Key;
|
||||
use OnlineEditorsExamplePhp\Configuration\ConfigurationManager;
|
||||
|
||||
final class JwtManager
|
||||
{
|
||||
/**
|
||||
@ -27,8 +31,8 @@ final class JwtManager
|
||||
*/
|
||||
public function isJwtEnabled(): bool
|
||||
{
|
||||
$configManager = new ConfigManager();
|
||||
return !empty($configManager->getConfig("docServJwtSecret"));
|
||||
$config_manager = new ConfigurationManager();
|
||||
return !empty($config_manager->jwt_secret());
|
||||
}
|
||||
|
||||
/**
|
||||
@ -38,8 +42,8 @@ final class JwtManager
|
||||
*/
|
||||
public function tokenUseForRequest(): bool
|
||||
{
|
||||
$configManager = new ConfigManager();
|
||||
return $configManager->getConfig("docServJwtUseForRequest") ?: false;
|
||||
$config_manager = new ConfigurationManager();
|
||||
return $config_manager->jwt_use_for_request() ?: false;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -51,8 +55,8 @@ final class JwtManager
|
||||
*/
|
||||
public function jwtEncode($payload)
|
||||
{
|
||||
$configManager = new ConfigManager();
|
||||
return \Firebase\JWT\JWT::encode($payload, $configManager->getConfig("docServJwtSecret"));
|
||||
$config_manager = new ConfigurationManager();
|
||||
return JWT::encode($payload, $config_manager->jwt_secret(), 'HS256');
|
||||
}
|
||||
|
||||
/**
|
||||
@ -64,12 +68,11 @@ final class JwtManager
|
||||
*/
|
||||
public function jwtDecode($token)
|
||||
{
|
||||
$configManager = new ConfigManager();
|
||||
$config_manager = new ConfigurationManager();
|
||||
try {
|
||||
$payload = \Firebase\JWT\JWT::decode(
|
||||
$payload = JWT::decode(
|
||||
$token,
|
||||
$configManager->getConfig("docServJwtSecret"),
|
||||
["HS256"]
|
||||
new Key($config_manager->jwt_secret(), 'HS256')
|
||||
);
|
||||
} catch (\UnexpectedValueException $e) {
|
||||
$payload = "";
|
||||
|
||||
@ -17,10 +17,140 @@
|
||||
|
||||
namespace OnlineEditorsExamplePhp;
|
||||
|
||||
require_once __DIR__ . '/vendor/autoload.php';
|
||||
require_once __DIR__ . '/ajax.php';
|
||||
require_once __DIR__ . '/functions.php';
|
||||
require_once __DIR__ . '/trackmanager.php';
|
||||
|
||||
use OnlineEditorsExamplePhp\Common\HTTPStatus;
|
||||
use OnlineEditorsExamplePhp\Common\URL;
|
||||
use OnlineEditorsExamplePhp\Configuration\ConfigurationManager;
|
||||
use OnlineEditorsExamplePhp\Views\DocEditorView;
|
||||
use OnlineEditorsExamplePhp\Views\IndexView;
|
||||
|
||||
require_once dirname(__FILE__) . '/functions.php';
|
||||
require_once dirname(__FILE__) . '/vendor/autoload.php';
|
||||
function configure() {
|
||||
$config_manager = new ConfigurationManager();
|
||||
if ($config_manager->ssl_verify_peer_mode_enabled()) {
|
||||
// Ignore self-signed certificate.
|
||||
stream_context_set_default([
|
||||
'ssl' => [
|
||||
'verify_peer' => false,
|
||||
'verify_peer_name' => false
|
||||
]
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
$indexView = new IndexView($_REQUEST);
|
||||
$indexView->render();
|
||||
function routers() {
|
||||
// TODO: delete fallback.
|
||||
// In theory, the content type of the response should be declared inside the
|
||||
// router function. However, this statement isn't true for all routers, and
|
||||
// it's also not true for all branches in all routers. Therefore, we are
|
||||
// setting the default content type for all routers here.
|
||||
header('Content-Type: application/json; charset=utf-8');
|
||||
|
||||
header('Cache-Control: no-cache, must-revalidate, max-age=0');
|
||||
header('Expires: Wed, 11 Jan 1984 05:00:00 GMT');
|
||||
header('Pragma: no-cache');
|
||||
@header_remove('Last-Modified');
|
||||
header('X-Content-Type-Options: nosniff');
|
||||
header('X-Robots-Tag: noindex');
|
||||
|
||||
$url = new URL($_SERVER['REQUEST_URI']);
|
||||
sendlog($url->string(), 'webedior-ajax.log');
|
||||
|
||||
$path = $url->path();
|
||||
if (!$path || $path === '/') {
|
||||
header('Content-Type: text/html; charset=utf-8');
|
||||
$view = new IndexView($_REQUEST);
|
||||
$view->render();
|
||||
return;
|
||||
}
|
||||
if (str_starts_with($path, '/editor')) {
|
||||
header('Content-Type: text/html; charset=utf-8');
|
||||
$view = new DocEditorView($_REQUEST);
|
||||
$view->render();
|
||||
return;
|
||||
}
|
||||
if (str_starts_with($path, '/assets')) {
|
||||
$response = assets();
|
||||
$response['status'] = 'success';
|
||||
echo json_encode($response);
|
||||
return;
|
||||
}
|
||||
if (str_starts_with($path, '/convert')) {
|
||||
$response = convert();
|
||||
$response['status'] = 'success';
|
||||
echo json_encode($response);
|
||||
return;
|
||||
}
|
||||
if (str_starts_with($path, '/csv')) {
|
||||
$response = csv();
|
||||
$response['status'] = 'success';
|
||||
echo json_encode($response);
|
||||
return;
|
||||
}
|
||||
if (str_starts_with($path, '/delete')) {
|
||||
$response = delete();
|
||||
$response['status'] = isset($response['error']) ? 'error' : 'success';
|
||||
echo json_encode($response);
|
||||
return;
|
||||
}
|
||||
if (str_starts_with($path, '/download')) {
|
||||
$response = download();
|
||||
$response['status'] = 'success';
|
||||
echo json_encode($response);
|
||||
return;
|
||||
}
|
||||
if (str_starts_with($path, '/files')) {
|
||||
$response = files();
|
||||
echo json_encode($response);
|
||||
return;
|
||||
}
|
||||
if (str_starts_with($path, '/history')) {
|
||||
$response = historyDownload();
|
||||
$response['status'] = 'success';
|
||||
echo json_encode($response);
|
||||
return;
|
||||
}
|
||||
if (str_starts_with($path, '/reference')) {
|
||||
$response = reference();
|
||||
$response['status'] = 'success';
|
||||
echo json_encode($response);
|
||||
return;
|
||||
}
|
||||
if (str_starts_with($path, '/rename')) {
|
||||
$response = renamefile();
|
||||
$content = json_encode($response);
|
||||
echo $content;
|
||||
return;
|
||||
}
|
||||
if (str_starts_with($path, '/restore')) {
|
||||
$response = restore();
|
||||
echo json_encode($response);
|
||||
return;
|
||||
}
|
||||
if (str_starts_with($path, '/saveas')) {
|
||||
$response = saveas();
|
||||
$response['status'] = 'success';
|
||||
echo json_encode($response);
|
||||
return;
|
||||
}
|
||||
if (str_starts_with($path, '/track')) {
|
||||
$response = track();
|
||||
$response['status'] = 'success';
|
||||
echo json_encode($response);
|
||||
return;
|
||||
}
|
||||
if (str_starts_with($path, '/upload')) {
|
||||
$response = upload();
|
||||
$response['status'] = isset($response['error']) ? 'error' : 'success';
|
||||
echo json_encode($response);
|
||||
return;
|
||||
}
|
||||
|
||||
http_response_code(HTTPStatus::not_found->value);
|
||||
}
|
||||
|
||||
configure();
|
||||
routers();
|
||||
|
||||
@ -125,7 +125,7 @@ if (typeof jQuery != "undefined") {
|
||||
jq("#filePass").val("");
|
||||
|
||||
timer = setTimeout(function () {
|
||||
var requestAddress = "webeditor-ajax.php?type=convert&user=" + user;
|
||||
var requestAddress = "convert?user=" + user;
|
||||
|
||||
jq.ajax({
|
||||
async: true,
|
||||
@ -247,7 +247,7 @@ if (typeof jQuery != "undefined") {
|
||||
|
||||
jq(document).on("click", "#beginEdit:not(.disable)", function () {
|
||||
var fileId = encodeURIComponent(jq('#hiddenFileName').val());
|
||||
var url = "doceditor.php?fileID=" + fileId + "&user=" + user + "&directUrl=" + directUrl;
|
||||
var url = "editor?fileID=" + fileId + "&user=" + user + "&directUrl=" + directUrl;
|
||||
window.open(url, "_blank");
|
||||
jq('#hiddenFileName').val("");
|
||||
jq.unblockUI();
|
||||
@ -256,7 +256,7 @@ if (typeof jQuery != "undefined") {
|
||||
|
||||
jq(document).on("click", "#beginView:not(.disable)", function () {
|
||||
var fileId = encodeURIComponent(jq('#hiddenFileName').val());
|
||||
var url = "doceditor.php?action=view&fileID=" + fileId + "&user=" + user + "&directUrl=" + directUrl;
|
||||
var url = "editor?action=view&fileID=" + fileId + "&user=" + user + "&directUrl=" + directUrl;
|
||||
window.open(url, "_blank");
|
||||
jq('#hiddenFileName').val("");
|
||||
jq.unblockUI();
|
||||
@ -265,7 +265,7 @@ if (typeof jQuery != "undefined") {
|
||||
|
||||
jq(document).on("click", "#beginEmbedded:not(.disable)", function () {
|
||||
var fileId = encodeURIComponent(jq('#hiddenFileName').val());
|
||||
var url = "doceditor.php?type=embedded&fileID=" + fileId + "&user=" + user + "&directUrl=" + directUrl;
|
||||
var url = "editor?type=embedded&fileID=" + fileId + "&user=" + user + "&directUrl=" + directUrl;
|
||||
|
||||
jq("#mainProgress").addClass("embedded");
|
||||
jq("#beginEmbedded").addClass("disable");
|
||||
@ -297,7 +297,7 @@ if (typeof jQuery != "undefined") {
|
||||
jq(document).on("click", ".delete-file", function () {
|
||||
var fileName = jq(this).attr("data");
|
||||
|
||||
var requestAddress = "webeditor-ajax.php?type=delete&fileName=" + fileName;
|
||||
var requestAddress = "delete?fileName=" + fileName;
|
||||
|
||||
jq.ajax({
|
||||
async: true,
|
||||
|
||||
@ -1,7 +0,0 @@
|
||||
<?php
|
||||
namespace Firebase\JWT;
|
||||
|
||||
class BeforeValidException extends \UnexpectedValueException
|
||||
{
|
||||
|
||||
}
|
||||
@ -1,7 +0,0 @@
|
||||
<?php
|
||||
namespace Firebase\JWT;
|
||||
|
||||
class ExpiredException extends \UnexpectedValueException
|
||||
{
|
||||
|
||||
}
|
||||
@ -1,370 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Firebase\JWT;
|
||||
use \DomainException;
|
||||
use \InvalidArgumentException;
|
||||
use \UnexpectedValueException;
|
||||
use \DateTime;
|
||||
|
||||
/**
|
||||
* JSON Web Token implementation, based on this spec:
|
||||
* http://tools.ietf.org/html/draft-ietf-oauth-json-web-token-06
|
||||
*
|
||||
* PHP version 5
|
||||
*
|
||||
* @category Authentication
|
||||
* @package Authentication_JWT
|
||||
* @author Neuman Vong <neuman@twilio.com>
|
||||
* @author Anant Narayanan <anant@php.net>
|
||||
* @license http://opensource.org/licenses/BSD-3-Clause 3-clause BSD
|
||||
* @link https://github.com/firebase/php-jwt
|
||||
*/
|
||||
class JWT
|
||||
{
|
||||
|
||||
/**
|
||||
* When checking nbf, iat or expiration times,
|
||||
* we want to provide some extra leeway time to
|
||||
* account for clock skew.
|
||||
*/
|
||||
public static $leeway = 0;
|
||||
|
||||
/**
|
||||
* Allow the current timestamp to be specified.
|
||||
* Useful for fixing a value within unit testing.
|
||||
*
|
||||
* Will default to PHP time() value if null.
|
||||
*/
|
||||
public static $timestamp = null;
|
||||
|
||||
public static $supported_algs = array(
|
||||
'HS256' => array('hash_hmac', 'SHA256'),
|
||||
'HS512' => array('hash_hmac', 'SHA512'),
|
||||
'HS384' => array('hash_hmac', 'SHA384'),
|
||||
'RS256' => array('openssl', 'SHA256'),
|
||||
);
|
||||
|
||||
/**
|
||||
* Decodes a JWT string into a PHP object.
|
||||
*
|
||||
* @param string $jwt The JWT
|
||||
* @param string|array $key The key, or map of keys.
|
||||
* If the algorithm used is asymmetric, this is the public key
|
||||
* @param array $allowed_algs List of supported verification algorithms
|
||||
* Supported algorithms are 'HS256', 'HS384', 'HS512' and 'RS256'
|
||||
*
|
||||
* @return object The JWT's payload as a PHP object
|
||||
*
|
||||
* @throws UnexpectedValueException Provided JWT was invalid
|
||||
* @throws SignatureInvalidException Provided JWT was invalid because the signature verification failed
|
||||
* @throws BeforeValidException Provided JWT is trying to be used before it's eligible as defined by 'nbf'
|
||||
* @throws BeforeValidException Provided JWT is trying to be used before it's been created as defined by 'iat'
|
||||
* @throws ExpiredException Provided JWT has since expired, as defined by the 'exp' claim
|
||||
*
|
||||
* @uses jsonDecode
|
||||
* @uses urlsafeB64Decode
|
||||
*/
|
||||
public static function decode($jwt, $key, $allowed_algs = array())
|
||||
{
|
||||
$timestamp = is_null(static::$timestamp) ? time() : static::$timestamp;
|
||||
|
||||
if (empty($key)) {
|
||||
throw new InvalidArgumentException('Key may not be empty');
|
||||
}
|
||||
if (!is_array($allowed_algs)) {
|
||||
throw new InvalidArgumentException('Algorithm not allowed');
|
||||
}
|
||||
$tks = explode('.', $jwt);
|
||||
if (count($tks) != 3) {
|
||||
throw new UnexpectedValueException('Wrong number of segments');
|
||||
}
|
||||
list($headb64, $bodyb64, $cryptob64) = $tks;
|
||||
if (null === ($header = static::jsonDecode(static::urlsafeB64Decode($headb64)))) {
|
||||
throw new UnexpectedValueException('Invalid header encoding');
|
||||
}
|
||||
if (null === $payload = static::jsonDecode(static::urlsafeB64Decode($bodyb64))) {
|
||||
throw new UnexpectedValueException('Invalid claims encoding');
|
||||
}
|
||||
$sig = static::urlsafeB64Decode($cryptob64);
|
||||
|
||||
if (empty($header->alg)) {
|
||||
throw new UnexpectedValueException('Empty algorithm');
|
||||
}
|
||||
if (empty(static::$supported_algs[$header->alg])) {
|
||||
throw new UnexpectedValueException('Algorithm not supported');
|
||||
}
|
||||
if (!in_array($header->alg, $allowed_algs)) {
|
||||
throw new UnexpectedValueException('Algorithm not allowed');
|
||||
}
|
||||
if (is_array($key) || $key instanceof \ArrayAccess) {
|
||||
if (isset($header->kid)) {
|
||||
$key = $key[$header->kid];
|
||||
} else {
|
||||
throw new UnexpectedValueException('"kid" empty, unable to lookup correct key');
|
||||
}
|
||||
}
|
||||
|
||||
// Check the signature
|
||||
if (!static::verify("$headb64.$bodyb64", $sig, $key, $header->alg)) {
|
||||
throw new SignatureInvalidException('Signature verification failed');
|
||||
}
|
||||
|
||||
// Check if the nbf if it is defined. This is the time that the
|
||||
// token can actually be used. If it's not yet that time, abort.
|
||||
if (isset($payload->nbf) && $payload->nbf > ($timestamp + static::$leeway)) {
|
||||
throw new BeforeValidException(
|
||||
'Cannot handle token prior to ' . date(DateTime::ISO8601, $payload->nbf)
|
||||
);
|
||||
}
|
||||
|
||||
// Check that this token has been created before 'now'. This prevents
|
||||
// using tokens that have been created for later use (and haven't
|
||||
// correctly used the nbf claim).
|
||||
if (isset($payload->iat) && $payload->iat > ($timestamp + static::$leeway)) {
|
||||
throw new BeforeValidException(
|
||||
'Cannot handle token prior to ' . date(DateTime::ISO8601, $payload->iat)
|
||||
);
|
||||
}
|
||||
|
||||
// Check if this token has expired.
|
||||
if (isset($payload->exp) && ($timestamp - static::$leeway) >= $payload->exp) {
|
||||
throw new ExpiredException('Expired token');
|
||||
}
|
||||
|
||||
return $payload;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts and signs a PHP object or array into a JWT string.
|
||||
*
|
||||
* @param object|array $payload PHP object or array
|
||||
* @param string $key The secret key.
|
||||
* If the algorithm used is asymmetric, this is the private key
|
||||
* @param string $alg The signing algorithm.
|
||||
* Supported algorithms are 'HS256', 'HS384', 'HS512' and 'RS256'
|
||||
* @param mixed $keyId
|
||||
* @param array $head An array with header elements to attach
|
||||
*
|
||||
* @return string A signed JWT
|
||||
*
|
||||
* @uses jsonEncode
|
||||
* @uses urlsafeB64Encode
|
||||
*/
|
||||
public static function encode($payload, $key, $alg = 'HS256', $keyId = null, $head = null)
|
||||
{
|
||||
$header = array('typ' => 'JWT', 'alg' => $alg);
|
||||
if ($keyId !== null) {
|
||||
$header['kid'] = $keyId;
|
||||
}
|
||||
if ( isset($head) && is_array($head) ) {
|
||||
$header = array_merge($head, $header);
|
||||
}
|
||||
$segments = array();
|
||||
$segments[] = static::urlsafeB64Encode(static::jsonEncode($header));
|
||||
$segments[] = static::urlsafeB64Encode(static::jsonEncode($payload));
|
||||
$signing_input = implode('.', $segments);
|
||||
|
||||
$signature = static::sign($signing_input, $key, $alg);
|
||||
$segments[] = static::urlsafeB64Encode($signature);
|
||||
|
||||
return implode('.', $segments);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sign a string with a given key and algorithm.
|
||||
*
|
||||
* @param string $msg The message to sign
|
||||
* @param string|resource $key The secret key
|
||||
* @param string $alg The signing algorithm.
|
||||
* Supported algorithms are 'HS256', 'HS384', 'HS512' and 'RS256'
|
||||
*
|
||||
* @return string An encrypted message
|
||||
*
|
||||
* @throws DomainException Unsupported algorithm was specified
|
||||
*/
|
||||
public static function sign($msg, $key, $alg = 'HS256')
|
||||
{
|
||||
if (empty(static::$supported_algs[$alg])) {
|
||||
throw new DomainException('Algorithm not supported');
|
||||
}
|
||||
list($function, $algorithm) = static::$supported_algs[$alg];
|
||||
switch($function) {
|
||||
case 'hash_hmac':
|
||||
return hash_hmac($algorithm, $msg, $key, true);
|
||||
case 'openssl':
|
||||
$signature = '';
|
||||
$success = openssl_sign($msg, $signature, $key, $algorithm);
|
||||
if (!$success) {
|
||||
throw new DomainException("OpenSSL unable to sign data");
|
||||
} else {
|
||||
return $signature;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify a signature with the message, key and method. Not all methods
|
||||
* are symmetric, so we must have a separate verify and sign method.
|
||||
*
|
||||
* @param string $msg The original message (header and body)
|
||||
* @param string $signature The original signature
|
||||
* @param string|resource $key For HS*, a string key works. for RS*, must be a resource of an openssl public key
|
||||
* @param string $alg The algorithm
|
||||
*
|
||||
* @return bool
|
||||
*
|
||||
* @throws DomainException Invalid Algorithm or OpenSSL failure
|
||||
*/
|
||||
private static function verify($msg, $signature, $key, $alg)
|
||||
{
|
||||
if (empty(static::$supported_algs[$alg])) {
|
||||
throw new DomainException('Algorithm not supported');
|
||||
}
|
||||
|
||||
list($function, $algorithm) = static::$supported_algs[$alg];
|
||||
switch($function) {
|
||||
case 'openssl':
|
||||
$success = openssl_verify($msg, $signature, $key, $algorithm);
|
||||
if (!$success) {
|
||||
throw new DomainException("OpenSSL unable to verify data: " . openssl_error_string());
|
||||
} else {
|
||||
return $signature;
|
||||
}
|
||||
case 'hash_hmac':
|
||||
default:
|
||||
$hash = hash_hmac($algorithm, $msg, $key, true);
|
||||
if (function_exists('hash_equals')) {
|
||||
return hash_equals($signature, $hash);
|
||||
}
|
||||
$len = min(static::safeStrlen($signature), static::safeStrlen($hash));
|
||||
|
||||
$status = 0;
|
||||
for ($i = 0; $i < $len; $i++) {
|
||||
$status |= (ord($signature[$i]) ^ ord($hash[$i]));
|
||||
}
|
||||
$status |= (static::safeStrlen($signature) ^ static::safeStrlen($hash));
|
||||
|
||||
return ($status === 0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode a JSON string into a PHP object.
|
||||
*
|
||||
* @param string $input JSON string
|
||||
*
|
||||
* @return object Object representation of JSON string
|
||||
*
|
||||
* @throws DomainException Provided string was invalid JSON
|
||||
*/
|
||||
public static function jsonDecode($input)
|
||||
{
|
||||
if (version_compare(PHP_VERSION, '5.4.0', '>=') && !(defined('JSON_C_VERSION') && PHP_INT_SIZE > 4)) {
|
||||
/** In PHP >=5.4.0, json_decode() accepts an options parameter, that allows you
|
||||
* to specify that large ints (like Steam Transaction IDs) should be treated as
|
||||
* strings, rather than the PHP default behaviour of converting them to floats.
|
||||
*/
|
||||
$obj = json_decode($input, false, 512, JSON_BIGINT_AS_STRING);
|
||||
} else {
|
||||
/** Not all servers will support that, however, so for older versions we must
|
||||
* manually detect large ints in the JSON string and quote them (thus converting
|
||||
*them to strings) before decoding, hence the preg_replace() call.
|
||||
*/
|
||||
$max_int_length = strlen((string) PHP_INT_MAX) - 1;
|
||||
$json_without_bigints = preg_replace('/:\s*(-?\d{'.$max_int_length.',})/', ': "$1"', $input);
|
||||
$obj = json_decode($json_without_bigints);
|
||||
}
|
||||
|
||||
if (function_exists('json_last_error') && $errno = json_last_error()) {
|
||||
static::handleJsonError($errno);
|
||||
} elseif ($obj === null && $input !== 'null') {
|
||||
throw new DomainException('Null result with non-null input');
|
||||
}
|
||||
return $obj;
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode a PHP object into a JSON string.
|
||||
*
|
||||
* @param object|array $input A PHP object or array
|
||||
*
|
||||
* @return string JSON representation of the PHP object or array
|
||||
*
|
||||
* @throws DomainException Provided object could not be encoded to valid JSON
|
||||
*/
|
||||
public static function jsonEncode($input)
|
||||
{
|
||||
$json = json_encode($input);
|
||||
if (function_exists('json_last_error') && $errno = json_last_error()) {
|
||||
static::handleJsonError($errno);
|
||||
} elseif ($json === 'null' && $input !== null) {
|
||||
throw new DomainException('Null result with non-null input');
|
||||
}
|
||||
return $json;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode a string with URL-safe Base64.
|
||||
*
|
||||
* @param string $input A Base64 encoded string
|
||||
*
|
||||
* @return string A decoded string
|
||||
*/
|
||||
public static function urlsafeB64Decode($input)
|
||||
{
|
||||
$remainder = strlen($input) % 4;
|
||||
if ($remainder) {
|
||||
$padlen = 4 - $remainder;
|
||||
$input .= str_repeat('=', $padlen);
|
||||
}
|
||||
return base64_decode(strtr($input, '-_', '+/'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode a string with URL-safe Base64.
|
||||
*
|
||||
* @param string $input The string you want encoded
|
||||
*
|
||||
* @return string The base64 encode of what you passed in
|
||||
*/
|
||||
public static function urlsafeB64Encode($input)
|
||||
{
|
||||
return str_replace('=', '', strtr(base64_encode($input), '+/', '-_'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to create a JSON error.
|
||||
*
|
||||
* @param int $errno An error number from json_last_error()
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private static function handleJsonError($errno)
|
||||
{
|
||||
$messages = array(
|
||||
JSON_ERROR_DEPTH => 'Maximum stack depth exceeded',
|
||||
JSON_ERROR_CTRL_CHAR => 'Unexpected control character found',
|
||||
JSON_ERROR_SYNTAX => 'Syntax error, malformed JSON'
|
||||
);
|
||||
throw new DomainException(
|
||||
isset($messages[$errno])
|
||||
? $messages[$errno]
|
||||
: 'Unknown JSON error: ' . $errno
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of bytes in cryptographic strings.
|
||||
*
|
||||
* @param string
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
private static function safeStrlen($str)
|
||||
{
|
||||
if (function_exists('mb_strlen')) {
|
||||
return mb_strlen($str, '8bit');
|
||||
}
|
||||
return strlen($str);
|
||||
}
|
||||
}
|
||||
@ -1,30 +0,0 @@
|
||||
Copyright (c) 2011, Neuman Vong
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following
|
||||
disclaimer in the documentation and/or other materials provided
|
||||
with the distribution.
|
||||
|
||||
* Neither the name of Neuman Vong nor the names of other
|
||||
contributors may be used to endorse or promote products derived
|
||||
from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
@ -1,7 +0,0 @@
|
||||
<?php
|
||||
namespace Firebase\JWT;
|
||||
|
||||
class SignatureInvalidException extends \UnexpectedValueException
|
||||
{
|
||||
|
||||
}
|
||||
@ -31,3 +31,7 @@ License File: jwt.license
|
||||
PHP_CodeSniffer - PHP_CodeSniffer is a set of two PHP scripts; the main phpcs script that tokenizes PHP, JavaScript and CSS files to detect violations of a defined coding standard, and a second phpcbf script to automatically correct coding standard violations. PHP_CodeSniffer is an essential development tool that ensures your code remains clean and consistent. (https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt)
|
||||
License: BSD-3-Clause
|
||||
License File: PHP_CodeSniffer.license
|
||||
|
||||
PHPUnit - The PHP Unit Testing framework. (https://github.com/sebastianbergmann/phpunit/blob/main/LICENSE)
|
||||
License: BSD 3-Clause
|
||||
License File: phpunit.license
|
||||
|
||||
29
web/documentserver-example/php/licenses/phpunit.license
Normal file
29
web/documentserver-example/php/licenses/phpunit.license
Normal file
@ -0,0 +1,29 @@
|
||||
BSD 3-Clause License
|
||||
|
||||
Copyright (c) 2001-2023, Sebastian Bergmann
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of the copyright holder nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
13
web/documentserver-example/php/php-fpm.conf
Normal file
13
web/documentserver-example/php/php-fpm.conf
Normal file
@ -0,0 +1,13 @@
|
||||
[global]
|
||||
daemonize = no
|
||||
|
||||
[www]
|
||||
user = www-data
|
||||
group = www-data
|
||||
listen = ${ADDRESS}:${PORT}
|
||||
pm = dynamic
|
||||
pm.max_children = 5
|
||||
pm.start_servers = 2
|
||||
pm.min_spare_servers = 1
|
||||
pm.max_spare_servers = 3
|
||||
clear_env = no
|
||||
13
web/documentserver-example/php/phpcs.xml
Normal file
13
web/documentserver-example/php/phpcs.xml
Normal file
@ -0,0 +1,13 @@
|
||||
<?xml version="1.0"?>
|
||||
<ruleset name="Custom Standard">
|
||||
<description>A custom coding standard</description>
|
||||
|
||||
<rule ref="PSR2"/>
|
||||
|
||||
<rule ref="Generic.Files.LineLength">
|
||||
<properties>
|
||||
<property name="lineLimit" value="120"/>
|
||||
<property name="absoluteLineLimit" value="0"/>
|
||||
</properties>
|
||||
</rule>
|
||||
</ruleset>
|
||||
@ -1,14 +0,0 @@
|
||||
<?xml version="1.0"?>
|
||||
<ruleset name="CustomRuleset">
|
||||
<description>This standard changes the line length</description>
|
||||
|
||||
<!-- Insert all sniff from PSR2 standard -->
|
||||
<rule ref="PSR2"/>
|
||||
|
||||
<rule ref="Generic.Files.LineLength">
|
||||
<properties>
|
||||
<property name="lineLimit" value="120"/>
|
||||
<property name="absoluteLineLimit" value="0"/>
|
||||
</properties>
|
||||
</rule>
|
||||
</ruleset>
|
||||
@ -103,7 +103,7 @@
|
||||
|
||||
event.data.directUrl = !!config.document.directUrl;
|
||||
let xhr = new XMLHttpRequest();
|
||||
xhr.open("POST", "webeditor-ajax.php?type=reference");
|
||||
xhr.open("POST", "reference");
|
||||
xhr.setRequestHeader("Content-Type", "application/json");
|
||||
xhr.send(JSON.stringify(event.data));
|
||||
xhr.onload = function () {
|
||||
@ -161,7 +161,7 @@
|
||||
url: url
|
||||
};
|
||||
let xhr = new XMLHttpRequest();
|
||||
xhr.open("POST", "webeditor-ajax.php?type=saveas");
|
||||
xhr.open("POST", "saveas");
|
||||
xhr.setRequestHeader('Content-Type', 'application/json');
|
||||
xhr.send(JSON.stringify(data));
|
||||
xhr.onload = function () {
|
||||
@ -181,7 +181,7 @@
|
||||
};
|
||||
|
||||
let xhr = new XMLHttpRequest();
|
||||
xhr.open("POST", "webeditor-ajax.php?type=rename");
|
||||
xhr.open("POST", "rename");
|
||||
xhr.setRequestHeader('Content-Type', 'application/json');
|
||||
xhr.send(JSON.stringify(data));
|
||||
xhr.onload = function () {
|
||||
@ -189,6 +189,27 @@
|
||||
}
|
||||
};
|
||||
|
||||
function onRequestRestore(event) {
|
||||
const query = new URLSearchParams(window.location.search)
|
||||
const config = {config}
|
||||
const payload = {
|
||||
fileName: query.get('fileID'),
|
||||
version: event.data.version,
|
||||
userId: query.get('user') || config.editorConfig.user.id
|
||||
}
|
||||
const request = new XMLHttpRequest()
|
||||
request.open("PUT", 'restore')
|
||||
request.send(JSON.stringify(payload))
|
||||
request.onload = function () {
|
||||
if (request.status != 200) {
|
||||
response = JSON.parse(request.response)
|
||||
innerAlert(response.error)
|
||||
return
|
||||
}
|
||||
document.location.reload();
|
||||
}
|
||||
}
|
||||
|
||||
var сonnectEditor = function () {
|
||||
{fileNotFoundAlert}
|
||||
|
||||
@ -208,6 +229,7 @@
|
||||
'onRequestCompareFile': onRequestCompareFile,
|
||||
'onRequestMailMergeRecipients': onRequestMailMergeRecipients,
|
||||
'onRequestReferenceData': onRequestReferenceData,
|
||||
'onRequestRestore': onRequestRestore
|
||||
};
|
||||
|
||||
{history}
|
||||
|
||||
@ -35,19 +35,19 @@
|
||||
<ul class="try-editor-list clearFix">
|
||||
<li>
|
||||
<a class="try-editor word reload-page" target="_blank"
|
||||
href="doceditor.php?fileExt=docx&user={user}">Document</a>
|
||||
href="editor?fileExt=docx&user={user}">Document</a>
|
||||
</li>
|
||||
<li>
|
||||
<a class="try-editor cell reload-page" target="_blank"
|
||||
href="doceditor.php?fileExt=xlsx&user={user}">Spreadsheet</a>
|
||||
href="editor?fileExt=xlsx&user={user}">Spreadsheet</a>
|
||||
</li>
|
||||
<li>
|
||||
<a class="try-editor slide reload-page" target="_blank"
|
||||
href="doceditor.php?fileExt=pptx&user={user}">Presentation</a>
|
||||
href="editor?fileExt=pptx&user={user}">Presentation</a>
|
||||
</li>
|
||||
<li>
|
||||
<a class="try-editor form reload-page" target="_blank"
|
||||
href="doceditor.php?fileExt=docxf&user={user}">Form template</a>
|
||||
href="editor?fileExt=docxf&user={user}">Form template</a>
|
||||
</li>
|
||||
</ul>
|
||||
<label class="side-option">
|
||||
@ -58,7 +58,7 @@
|
||||
<div class="upload-panel clearFix">
|
||||
<a class="file-upload">Upload file
|
||||
<input type="file" id="fileupload" name="files"
|
||||
data-url="webeditor-ajax.php?type=upload&user={user}" />
|
||||
data-url="upload?user={user}" />
|
||||
</a>
|
||||
</div>
|
||||
|
||||
|
||||
@ -18,6 +18,7 @@
|
||||
namespace OnlineEditorsExamplePhp;
|
||||
|
||||
use Exception;
|
||||
use OnlineEditorsExamplePhp\Configuration\ConfigurationManager;
|
||||
use OnlineEditorsExamplePhp\Helpers\ConfigManager;
|
||||
use OnlineEditorsExamplePhp\Helpers\JwtManager;
|
||||
|
||||
@ -28,6 +29,8 @@ use OnlineEditorsExamplePhp\Helpers\JwtManager;
|
||||
*/
|
||||
function readBody()
|
||||
{
|
||||
$config_manager = new ConfigurationManager();
|
||||
|
||||
$result["error"] = 0;
|
||||
$configManager = new ConfigManager();
|
||||
$jwtManager = new JwtManager();
|
||||
@ -53,8 +56,7 @@ function readBody()
|
||||
|
||||
$inHeader = false;
|
||||
$data = "";
|
||||
$jwtHeader = $configManager->getConfig("docServJwtHeader") ==
|
||||
"" ? "Authorization" : $configManager->getConfig("docServJwtHeader");
|
||||
$jwtHeader = $config_manager->jwt_header();
|
||||
|
||||
if (!empty($data["token"])) { // if the document token is in the data
|
||||
$data = $jwtManager->jwtDecode($data["token"]); // decode it
|
||||
@ -290,10 +292,10 @@ function processForceSave($data, $fileName, $userAddress)
|
||||
*/
|
||||
function commandRequest($method, $key, $meta = null)
|
||||
{
|
||||
$configManager = new ConfigManager();
|
||||
$config_manager = new ConfigurationManager();
|
||||
|
||||
$jwtManager = new JwtManager();
|
||||
$documentCommandUrl = $configManager->getConfig("docServSiteUrl").
|
||||
$configManager->getConfig("docServCommandUrl");
|
||||
$documentCommandUrl = $config_manager->document_server_command_url()->string();
|
||||
|
||||
$arr = [
|
||||
"c" => $method,
|
||||
@ -305,8 +307,7 @@ function commandRequest($method, $key, $meta = null)
|
||||
}
|
||||
|
||||
$headerToken = "";
|
||||
$jwtHeader = $configManager->getConfig("docServJwtHeader") == "" ? "Authorization" :
|
||||
$configManager->getConfig("docServJwtHeader");
|
||||
$jwtHeader = $config_manager->jwt_header();
|
||||
|
||||
// check if a secret key to generate token exists or not
|
||||
if ($jwtManager->isJwtEnabled() && $jwtManager->tokenUseForRequest()) {
|
||||
@ -326,7 +327,7 @@ function commandRequest($method, $key, $meta = null)
|
||||
]];
|
||||
|
||||
if (mb_substr($documentCommandUrl, 0, mb_strlen("https")) === "https") {
|
||||
if ($configManager->getConfig("docServVerifyPeerOff") === true) {
|
||||
if ($config_manager->ssl_verify_peer_mode_enabled()) {
|
||||
$opts['ssl'] = ['verify_peer' => false, 'verify_peer_name' => false];
|
||||
}
|
||||
}
|
||||
|
||||
@ -17,6 +17,7 @@
|
||||
|
||||
namespace OnlineEditorsExamplePhp\Views;
|
||||
|
||||
use OnlineEditorsExamplePhp\Configuration\ConfigurationManager;
|
||||
use OnlineEditorsExamplePhp\Helpers\ConfigManager;
|
||||
use OnlineEditorsExamplePhp\Helpers\ExampleUsers;
|
||||
use OnlineEditorsExamplePhp\Helpers\JwtManager;
|
||||
@ -39,6 +40,9 @@ final class DocEditorView extends View
|
||||
public function __construct($request, $tempName = "docEditor")
|
||||
{
|
||||
parent::__construct($tempName);
|
||||
|
||||
$config_manager = new ConfigurationManager();
|
||||
|
||||
$externalUrl = $request["fileUrl"] ?? "";
|
||||
$confgManager = new ConfigManager();
|
||||
$jwtManager = new JwtManager();
|
||||
@ -59,15 +63,12 @@ final class DocEditorView extends View
|
||||
$filename = tryGetDefaultByType($createExt, $user);
|
||||
|
||||
// create the demo file url
|
||||
$new_url = "doceditor.php?fileID=" . $filename . "&user=" . $request["user"];
|
||||
$new_url = "editor?fileID=" . $filename . "&user=" . $request["user"];
|
||||
header('Location: ' . $new_url, true);
|
||||
exit;
|
||||
}
|
||||
|
||||
$fileuri = fileUri($filename, true);
|
||||
$fileuriUser = realpath($confgManager->getConfig("storagePath")) ===
|
||||
$confgManager->getConfig("storagePath") ?
|
||||
getDownloadUrl($filename) . "&dmode=emb" : fileUri($filename);
|
||||
$directUrl = getDownloadUrl($filename, false);
|
||||
$docKey = getDocEditorKey($filename);
|
||||
$filetype = mb_strtolower(pathinfo($filename, PATHINFO_EXTENSION));
|
||||
@ -200,21 +201,21 @@ final class DocEditorView extends View
|
||||
// a document for comparing
|
||||
$dataCompareFile = $isEnableDirectUrl ? [
|
||||
"fileType" => "docx",
|
||||
"url" => serverPath(true) . "/webeditor-ajax.php?type=assets&name=sample.docx",
|
||||
"directUrl" => serverPath(false) . "/webeditor-ajax.php?type=assets&name=sample.docx",
|
||||
"url" => serverPath(true) . "/assets?name=sample.docx",
|
||||
"directUrl" => serverPath(false) . "/assets?name=sample.docx",
|
||||
] : [
|
||||
"fileType" => "docx",
|
||||
"url" => serverPath(true) . "/webeditor-ajax.php?type=assets&name=sample.docx",
|
||||
"url" => serverPath(true) . "/assets?name=sample.docx",
|
||||
];
|
||||
|
||||
// recipients data for mail merging
|
||||
$dataMailMergeRecipients = $isEnableDirectUrl ? [
|
||||
"fileType" => "csv",
|
||||
"url" => serverPath(true) . "/webeditor-ajax.php?type=csv",
|
||||
"directUrl" => serverPath(false) . "/webeditor-ajax.php?type=csv",
|
||||
"url" => serverPath(true) . "/csv",
|
||||
"directUrl" => serverPath(false) . "/csv",
|
||||
] : [
|
||||
"fileType" => "csv",
|
||||
"url" => serverPath(true) . "/webeditor-ajax.php?type=csv",
|
||||
"url" => serverPath(true) . "/csv",
|
||||
];
|
||||
|
||||
// users data for mentions
|
||||
@ -266,7 +267,7 @@ final class DocEditorView extends View
|
||||
}
|
||||
$this->tagsValues = [
|
||||
"docType" => getDocumentType($filename),
|
||||
"apiUrl" => $confgManager->getConfig("docServSiteUrl").$confgManager->getConfig("docServApiUrl"),
|
||||
"apiUrl" => $config_manager->document_server_api_url()->string(),
|
||||
"dataInsertImage" => mb_strimwidth(
|
||||
json_encode($dataInsertImage),
|
||||
1,
|
||||
|
||||
@ -50,40 +50,40 @@ class IndexStoredListView extends View
|
||||
)
|
||||
).']">';
|
||||
$layout .= ' <td class="contentCells"><a class="stored-edit '.
|
||||
$storeFile->documentType.'" href="doceditor.php?fileID='.
|
||||
$storeFile->documentType.'" href="editor?fileID='.
|
||||
urlencode($storeFile->name).
|
||||
'&user='.$user.
|
||||
$directUrlArg .'" target="_blank">'.'<span>'.$storeFile->name.'</span></a></td>';
|
||||
if ($storeFile->canEdit) {
|
||||
$layout .= ' <td class="contentCells contentCells-icon"> <a href="doceditor.php?fileID='.
|
||||
$layout .= ' <td class="contentCells contentCells-icon"> <a href="editor?fileID='.
|
||||
urlencode($storeFile->name).'&user=' . htmlentities($user).$directUrlArg.
|
||||
'&action=edit&type=desktop" target="_blank">'.
|
||||
'<img src="css/images/desktop.svg" alt="Open in editor for full size screens"'.
|
||||
' title="Open in editor for full size screens"/></a></td>'.
|
||||
' <td class="contentCells contentCells-icon"> <a href="doceditor.php?fileID='.
|
||||
' <td class="contentCells contentCells-icon"> <a href="editor?fileID='.
|
||||
urlencode($storeFile->name).'&user=' . htmlentities($user).$directUrlArg.
|
||||
'&action=edit&type=mobile" target="_blank">'.
|
||||
'<img src="css/images/mobile.svg" alt="Open in editor for mobile devices"'.
|
||||
' title="Open in editor for mobile devices" /></a></td>'.
|
||||
' <td class="contentCells contentCells-icon"> <a href="doceditor.php?fileID='.
|
||||
' <td class="contentCells contentCells-icon"> <a href="editor?fileID='.
|
||||
urlencode($storeFile->name).'&user='.htmlentities($user).$directUrlArg.
|
||||
'&action=comment&type=desktop" target="_blank">'.
|
||||
' <img src="css/images/comment.svg" alt="Open in editor for comment"'.
|
||||
' title="Open in editor for comment" /></a></td>';
|
||||
if ($storeFile->documentType == "word") {
|
||||
$layout .= '<td class="contentCells contentCells-icon"> <a href="doceditor.php?fileID='.
|
||||
$layout .= '<td class="contentCells contentCells-icon"> <a href="editor?fileID='.
|
||||
urlencode($storeFile->name).'&user='.htmlentities($user).$directUrlArg.
|
||||
'&action=review&type=desktop" target="_blank">'.
|
||||
' <img src="css/images/review.svg" alt="Open in editor for review"'.
|
||||
' title="Open in editor for review" /></a></td>'.
|
||||
' <td class="contentCells contentCells-icon "> <a href="doceditor.php?fileID='.
|
||||
' <td class="contentCells contentCells-icon "> <a href="editor?fileID='.
|
||||
urlencode($storeFile->name).'&user='.htmlentities($user).$directUrlArg.
|
||||
'&action=blockcontent&type=desktop" target="_blank">'.
|
||||
' <img src="css/images/block-content.svg"'.
|
||||
' alt="Open in editor without content control modification"'.
|
||||
' title="Open in editor without content control modification"</a></td>';
|
||||
} elseif ($storeFile->documentType == "cell") {
|
||||
$layout .= '<td class="contentCells contentCells-icon"> <a href="doceditor.php?fileID='.
|
||||
$layout .= '<td class="contentCells contentCells-icon"> <a href="editor?fileID='.
|
||||
urlencode($storeFile->name).'&user='.htmlentities($user).$directUrlArg.
|
||||
'&action=filter&type=desktop" target="_blank">'.
|
||||
' <img src="css/images/filter.svg" alt="Open in editor without access to change the filter"'.
|
||||
@ -95,7 +95,7 @@ class IndexStoredListView extends View
|
||||
if ($storeFile->isFillFormDoc) {
|
||||
$layout.= ' <td class="contentCells contentCells-shift contentCells-icon'.
|
||||
' firstContentCellShift">'.
|
||||
' <a href="doceditor.php?fileID='.urlencode($storeFile->name).
|
||||
' <a href="editor?fileID='.urlencode($storeFile->name).
|
||||
'&user='.htmlentities($user).$directUrlArg.
|
||||
'&action=fillForms&type=desktop" target="_blank">'.
|
||||
' <img src="css/images/fill-forms.svg" alt="Open in editor for filling in forms"'.
|
||||
@ -105,7 +105,7 @@ class IndexStoredListView extends View
|
||||
'firstContentCellShift"></td>';
|
||||
}
|
||||
} elseif ($storeFile->isFillFormDoc) {
|
||||
$layout .= '<td class="contentCells contentCells-icon"> <a href="doceditor.php?fileID='.
|
||||
$layout .= '<td class="contentCells contentCells-icon"> <a href="editor?fileID='.
|
||||
urlencode($storeFile->name).'&user='.htmlentities($user).$directUrlArg.
|
||||
'&action=fillForms&type=desktop" target="_blank">'.
|
||||
' <img src="css/images/mobile-fill-forms.svg" alt="Open in editor for filling in forms'.
|
||||
@ -114,7 +114,7 @@ class IndexStoredListView extends View
|
||||
'<td class="contentCells contentCells-icon"></td>'.
|
||||
'<td class="contentCells contentCells-icon"></td>'.
|
||||
'<td class="contentCells contentCells-shift contentCells-icon firstContentCellShift">'.
|
||||
'<a href="doceditor.php?fileID='.urlencode($storeFile->name).'&user='.htmlentities($user).
|
||||
'<a href="editor?fileID='.urlencode($storeFile->name).'&user='.htmlentities($user).
|
||||
$directUrlArg.'&action=fillForms&type=desktop" target="_blank">'.
|
||||
'<img src="css/images/fill-forms.svg" alt="Open in editor for filling in forms"'.
|
||||
' title="Open in editor for filling in forms"/></a></td>';
|
||||
@ -123,22 +123,22 @@ class IndexStoredListView extends View
|
||||
'contentCellsEmpty" colspan="6"></td>';
|
||||
}
|
||||
$layout .= '<td class="contentCells contentCells-icon firstContentCellViewers">'.
|
||||
' <a href="doceditor.php?fileID='.urlencode($storeFile->name).'&user='.htmlentities($user).
|
||||
' <a href="editor?fileID='.urlencode($storeFile->name).'&user='.htmlentities($user).
|
||||
$directUrlArg.'&action=view&type=desktop" target="_blank">'.
|
||||
' <img src="css/images/desktop.svg" alt="Open in viewer for full size screens"'.
|
||||
' title="Open in viewer for full size screens" /></a></td>'.
|
||||
' <td class="contentCells contentCells-icon"> <a href="doceditor.php?fileID='.
|
||||
' <td class="contentCells contentCells-icon"> <a href="editor?fileID='.
|
||||
urlencode($storeFile->name).'&user='.htmlentities($user).$directUrlArg.
|
||||
'&action=view&type=mobile" target="_blank">'.
|
||||
' <img src="css/images/mobile.svg" alt="Open in viewer for mobile devices"'.
|
||||
' title="Open in viewer for mobile devices" /></a></td>'.
|
||||
' <td class="contentCells contentCells-icon contentCells-shift">'.
|
||||
' <a href="doceditor.php?fileID='.urlencode($storeFile->name).'&user='.htmlentities($user).
|
||||
' <a href="editor?fileID='.urlencode($storeFile->name).'&user='.htmlentities($user).
|
||||
$directUrlArg.'&action=embedded&type=embedded" target="_blank">'.
|
||||
' <img src="css/images/embeded.svg" alt="Open in embedded mode"'.
|
||||
' title="Open in embedded mode" /></a>'.
|
||||
' <td class="contentCells contentCells-icon contentCells-shift downloadContentCellShift">'.
|
||||
'<a href="webeditor-ajax.php?type=download&fileName='.urlencode($storeFile->name).'">'.
|
||||
'<a href="download?fileName='.urlencode($storeFile->name).'">'.
|
||||
' <img class="icon-download" src="css/images/download.svg" alt="Download" title="Download"'.
|
||||
' /></a></td>'.
|
||||
'<td class="contentCells contentCells-icon contentCells-shift">'.
|
||||
|
||||
@ -17,6 +17,7 @@
|
||||
|
||||
namespace OnlineEditorsExamplePhp\Views;
|
||||
|
||||
use OnlineEditorsExamplePhp\Configuration\ConfigurationManager;
|
||||
use OnlineEditorsExamplePhp\Helpers\ConfigManager;
|
||||
use OnlineEditorsExamplePhp\Helpers\ExampleUsers;
|
||||
use function OnlineEditorsExamplePhp\getStoredFiles;
|
||||
@ -61,8 +62,8 @@ final class IndexView extends View
|
||||
private function getLanguageListOptionsLayout()
|
||||
{
|
||||
$layout = "";
|
||||
$configManager = new ConfigManager();
|
||||
foreach ($configManager->getConfig("languages") as $key => $language) {
|
||||
$config_manager = new ConfigurationManager();
|
||||
foreach ($config_manager->languages() as $key => $language) {
|
||||
$layout .= '<option value="'.$key.'">'.$language.'</option>'.PHP_EOL;
|
||||
}
|
||||
return $layout;
|
||||
@ -100,16 +101,12 @@ final class IndexView extends View
|
||||
|
||||
private function getPreloaderUrl()
|
||||
{
|
||||
$configManager = new ConfigManager();
|
||||
|
||||
return $configManager->getConfig("docServSiteUrl").
|
||||
$configManager->getConfig("docServPreloaderUrl");
|
||||
$config_manager = new ConfigurationManager();
|
||||
return $config_manager->document_server_preloader_url()->string();
|
||||
}
|
||||
|
||||
private function getEditButton()
|
||||
{
|
||||
$configManager = new ConfigManager();
|
||||
return $configManager->getConfig("mode") != "view" ?
|
||||
'<div id="beginEdit" class="button orange disable">Edit</div>' : "";
|
||||
return '<div id="beginEdit" class="button orange disable">Edit</div>';
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,16 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<configuration>
|
||||
<system.web>
|
||||
<customErrors mode="Off"/>
|
||||
</system.web>
|
||||
<system.webServer>
|
||||
<defaultDocument enabled="true" />
|
||||
<httpErrors errorMode="Detailed"/>
|
||||
<urlCompression doDynamicCompression="false"/>
|
||||
<httpProtocol>
|
||||
<customHeaders>
|
||||
<add name="Access-Control-Allow-Origin" value="*" />
|
||||
</customHeaders>
|
||||
</httpProtocol>
|
||||
</system.webServer>
|
||||
</configuration>
|
||||
@ -1,120 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* (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.
|
||||
*/
|
||||
|
||||
namespace OnlineEditorsExamplePhp;
|
||||
|
||||
use OnlineEditorsExamplePhp\Helpers\ConfigManager;
|
||||
|
||||
/**
|
||||
* WebEditor AJAX Process Execution.
|
||||
*/
|
||||
|
||||
require_once dirname(__FILE__) . '/ajax.php';
|
||||
require_once dirname(__FILE__) . '/functions.php';
|
||||
require_once dirname(__FILE__) . '/trackmanager.php';
|
||||
require_once dirname(__FILE__) . '/vendor/autoload.php';
|
||||
|
||||
$configManager = new ConfigManager();
|
||||
// define tracker status
|
||||
$_trackerStatus = [
|
||||
0 => 'NotFound',
|
||||
1 => 'Editing',
|
||||
2 => 'MustSave',
|
||||
3 => 'Corrupted',
|
||||
4 => 'Closed',
|
||||
6 => 'MustForceSave',
|
||||
7 => 'CorruptedForceSave',
|
||||
];
|
||||
|
||||
// ignore self-signed certificate
|
||||
if ($configManager->getConfig("docServVerifyPeerOff") === true) {
|
||||
stream_context_set_default([
|
||||
'ssl' => [
|
||||
'verify_peer' => false,
|
||||
'verify_peer_name' => false,
|
||||
],
|
||||
]);
|
||||
}
|
||||
|
||||
// check if type value exists
|
||||
if (isset($_GET["type"]) && !empty($_GET["type"])) {
|
||||
@header('Content-Type: application/json; charset==utf-8');
|
||||
@header('X-Robots-Tag: noindex');
|
||||
@header('X-Content-Type-Options: nosniff');
|
||||
|
||||
// set headers that prevent caching in all the browsers
|
||||
nocacheHeaders();
|
||||
|
||||
// write the request result to the log file
|
||||
sendlog(serialize($_GET), "webedior-ajax.log");
|
||||
|
||||
$type = $_GET["type"];
|
||||
|
||||
// switch case for type value
|
||||
switch ($type) {
|
||||
case "upload":
|
||||
$response_array = upload();
|
||||
$response_array['status'] = isset($response_array['error']) ? 'error' : 'success';
|
||||
die(json_encode($response_array));
|
||||
case "download":
|
||||
$response_array = download();
|
||||
$response_array['status'] = 'success';
|
||||
die(json_encode($response_array));
|
||||
case "history":
|
||||
$response_array = historyDownload();
|
||||
$response_array['status'] = 'success';
|
||||
die(json_encode($response_array));
|
||||
case "convert":
|
||||
$response_array = convert();
|
||||
$response_array['status'] = 'success';
|
||||
die(json_encode($response_array));
|
||||
case "track":
|
||||
$response_array = track();
|
||||
$response_array['status'] = 'success';
|
||||
die(json_encode($response_array));
|
||||
case "delete":
|
||||
$response_array = delete();
|
||||
$response_array['status'] = 'success';
|
||||
die(json_encode($response_array));
|
||||
case "assets":
|
||||
$response_array = assets();
|
||||
$response_array['status'] = 'success';
|
||||
die(json_encode($response_array));
|
||||
case "csv":
|
||||
$response_array = csv();
|
||||
$response_array['status'] = 'success';
|
||||
die(json_encode($response_array));
|
||||
case "reference":
|
||||
$response_array = reference();
|
||||
$response_array['status'] = 'success';
|
||||
die(json_encode($response_array));
|
||||
case "files":
|
||||
$response_array = files();
|
||||
die(json_encode($response_array));
|
||||
case "saveas":
|
||||
$response_array = saveas();
|
||||
$response_array['status'] = 'success';
|
||||
die(json_encode($response_array));
|
||||
case "rename":
|
||||
$response_array = renamefile();
|
||||
die(json_encode($response_array));
|
||||
default:
|
||||
$response_array['status'] = 'error';
|
||||
$response_array['error'] = '404 Method not found';
|
||||
die(json_encode($response_array));
|
||||
}
|
||||
}
|
||||
19
web/documentserver-example/python/Dockerfile
Normal file
19
web/documentserver-example/python/Dockerfile
Normal file
@ -0,0 +1,19 @@
|
||||
FROM python:3.11.4-alpine3.18 AS example-base
|
||||
WORKDIR /srv
|
||||
COPY . .
|
||||
RUN \
|
||||
apk update && \
|
||||
apk add --no-cache \
|
||||
libmagic \
|
||||
make
|
||||
|
||||
FROM example-base AS example-dev
|
||||
RUN make dev
|
||||
CMD ["make", "server-dev"]
|
||||
|
||||
FROM example-base AS example-prod
|
||||
RUN make prod
|
||||
CMD ["make", "server-prod"]
|
||||
|
||||
FROM nginx:1.23.4-alpine3.17 AS proxy
|
||||
COPY proxy/nginx.conf /etc/nginx/nginx.conf
|
||||
@ -1,34 +1,55 @@
|
||||
.DEFAULT_GOAL := help
|
||||
|
||||
.PHONY: help
|
||||
help: # Show help message for each of the Makefile recipes.
|
||||
help: # Show help message for each of the Makefile recipes.
|
||||
@grep -E "^[a-z-]+: #" $(MAKEFILE_LIST) | \
|
||||
sort | \
|
||||
awk 'BEGIN {FS = ": # "}; {printf "%s: %s\n", $$1, $$2}'
|
||||
|
||||
.PHONY: dev
|
||||
dev: # Install development dependencies.
|
||||
dev: # Install development dependencies.
|
||||
@pip install --editable .[development]
|
||||
|
||||
.PHONY: lint
|
||||
lint: # Lint the source code for style and check for types.
|
||||
@flake8
|
||||
@mypy .
|
||||
|
||||
.PHONY: prod
|
||||
prod: # Install production dependencies.
|
||||
prod: # Install production dependencies.
|
||||
@pip install .
|
||||
|
||||
.PHONY: server-dev
|
||||
server-dev: # Start the development server on localhost at $PORT (default: 8000).
|
||||
server-dev: # Start the development server on localhost at $PORT (default: 8000).
|
||||
@python manage.py runserver
|
||||
|
||||
.PHONY: server-prod
|
||||
server-prod: \
|
||||
export DEBUG := false
|
||||
server-prod: # Start the production server on 0.0.0.0 at $PORT (default: 8000).
|
||||
server-prod: # Start the production server on 0.0.0.0 at $PORT (default: 8000).
|
||||
@python manage.py runserver
|
||||
|
||||
.PHONY: compose-dev
|
||||
compose-dev: # Up containers in a development environment.
|
||||
@docker-compose \
|
||||
--file compose-base.yml \
|
||||
--file compose-dev.yml \
|
||||
build
|
||||
@docker-compose \
|
||||
--file compose-base.yml \
|
||||
--file compose-dev.yml \
|
||||
up --detach
|
||||
|
||||
.PHONY: compose-prod
|
||||
compose-prod: # Up containers in a production environment.
|
||||
@docker-compose \
|
||||
--file compose-base.yml \
|
||||
--file compose-prod.yml \
|
||||
build
|
||||
@docker-compose \
|
||||
--file compose-base.yml \
|
||||
--file compose-prod.yml \
|
||||
up --detach
|
||||
|
||||
.PHONY: lint
|
||||
lint: # Lint the source code for style and check for types.
|
||||
@flake8
|
||||
@mypy .
|
||||
|
||||
.PHONY: test
|
||||
test: # Recursively run the tests.
|
||||
test: # Recursively run the tests.
|
||||
@python -m unittest ./src/**/*_tests.py
|
||||
|
||||
Submodule web/documentserver-example/python/assets/document-formats added at 6e38b17679
33
web/documentserver-example/python/compose-base.yml
Normal file
33
web/documentserver-example/python/compose-base.yml
Normal file
@ -0,0 +1,33 @@
|
||||
version: "3.8"
|
||||
|
||||
services:
|
||||
# document-server:
|
||||
# container_name: document-server
|
||||
# image: onlyoffice/documentserver:7.3.3.50
|
||||
# expose:
|
||||
# - "80"
|
||||
# environment:
|
||||
# - JWT_SECRET=your-256-bit-secret
|
||||
|
||||
example:
|
||||
container_name: example
|
||||
build:
|
||||
context: .
|
||||
expose:
|
||||
- "80"
|
||||
environment:
|
||||
- ADDRESS=0.0.0.0
|
||||
- DOCUMENT_SERVER_PRIVATE_URL=http://proxy:8080
|
||||
- DOCUMENT_SERVER_PUBLIC_URL=http://localhost:8080
|
||||
- EXAMPLE_URL=http://proxy
|
||||
- JWT_SECRET=your-256-bit-secret
|
||||
- PORT=80
|
||||
|
||||
proxy:
|
||||
container_name: proxy
|
||||
build:
|
||||
context: .
|
||||
target: proxy
|
||||
ports:
|
||||
- "80:80"
|
||||
- "8080:8080"
|
||||
6
web/documentserver-example/python/compose-dev.yml
Normal file
6
web/documentserver-example/python/compose-dev.yml
Normal file
@ -0,0 +1,6 @@
|
||||
version: "3.8"
|
||||
|
||||
services:
|
||||
example:
|
||||
build:
|
||||
target: example-dev
|
||||
6
web/documentserver-example/python/compose-prod.yml
Normal file
6
web/documentserver-example/python/compose-prod.yml
Normal file
@ -0,0 +1,6 @@
|
||||
version: "3.8"
|
||||
|
||||
services:
|
||||
example:
|
||||
build:
|
||||
target: example-prod
|
||||
@ -16,6 +16,9 @@ def debug():
|
||||
return string.boolean(env, True)
|
||||
|
||||
def address():
|
||||
env = environ.get('ADDRESS')
|
||||
if env is not None:
|
||||
return env
|
||||
if settings.DEBUG:
|
||||
return RunServer.default_addr
|
||||
return '0.0.0.0'
|
||||
@ -64,9 +67,11 @@ def routers():
|
||||
path('downloadhistory', actions.downloadhistory),
|
||||
path('edit', actions.edit),
|
||||
path('files', actions.files),
|
||||
path('formats-convertible', actions.formats_convertible),
|
||||
path('reference', actions.reference),
|
||||
path('remove', actions.remove),
|
||||
path('rename', actions.rename),
|
||||
path('restore', actions.restore),
|
||||
path('saveas', actions.saveAs),
|
||||
path('track', actions.track),
|
||||
path('upload', actions.upload)
|
||||
|
||||
38
web/documentserver-example/python/proxy/nginx.conf
Normal file
38
web/documentserver-example/python/proxy/nginx.conf
Normal file
@ -0,0 +1,38 @@
|
||||
worker_processes auto;
|
||||
|
||||
events {
|
||||
worker_connections 512;
|
||||
}
|
||||
|
||||
http {
|
||||
include /etc/nginx/mime.types;
|
||||
|
||||
server {
|
||||
listen 80;
|
||||
server_name localhost;
|
||||
|
||||
location / {
|
||||
proxy_http_version 1.1;
|
||||
proxy_pass http://example;
|
||||
}
|
||||
}
|
||||
|
||||
# server {
|
||||
# listen 8080;
|
||||
# server_name localhost;
|
||||
|
||||
# location / {
|
||||
# client_max_body_size 100m;
|
||||
# proxy_http_version 1.1;
|
||||
# proxy_pass http://document-server;
|
||||
# proxy_redirect off;
|
||||
# proxy_set_header Connection "upgrade";
|
||||
# proxy_set_header Host $http_host;
|
||||
# proxy_set_header Upgrade $http_upgrade;
|
||||
# proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
# proxy_set_header X-Forwarded-Host $http_x_forwarded_host;
|
||||
# proxy_set_header X-Forwarded-Proto $http_x_forwarded_proto;
|
||||
# proxy_set_header X-Real-IP $remote_addr;
|
||||
# }
|
||||
# }
|
||||
}
|
||||
35
web/documentserver-example/python/src/codable/__init__.py
Normal file
35
web/documentserver-example/python/src/codable/__init__.py
Normal 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.
|
||||
#
|
||||
|
||||
'''
|
||||
The Codable module provides the ability to decode a string JSON into a class
|
||||
instance and encode it back. It also provides the ability to remap JSON keys and
|
||||
work with nested Codable instances.
|
||||
|
||||
```python
|
||||
from dataclasses import dataclass
|
||||
from src.codable import Codable, CodingKey
|
||||
|
||||
@dataclass
|
||||
class Fruit(Codable):
|
||||
class CodingKeys(CodingKey):
|
||||
native_for_python: 'foreignForPython'
|
||||
|
||||
native_for_python: str
|
||||
```
|
||||
'''
|
||||
|
||||
from .codable import Codable, CodingKey
|
||||
189
web/documentserver-example/python/src/codable/codable.py
Normal file
189
web/documentserver-example/python/src/codable/codable.py
Normal file
@ -0,0 +1,189 @@
|
||||
#
|
||||
# (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.
|
||||
#
|
||||
|
||||
from __future__ import annotations
|
||||
from copy import deepcopy
|
||||
from enum import StrEnum
|
||||
from json import JSONDecoder, JSONEncoder
|
||||
from typing import Any, Optional, Self, Type, get_args, get_origin, get_type_hints
|
||||
|
||||
class Monkey():
|
||||
key: str
|
||||
|
||||
def __init__(self, key: str = '_slugs'):
|
||||
self.key = key
|
||||
|
||||
def patch(self, obj: dict[str, Any]) -> dict[str, Any]:
|
||||
def inner(slug: list[str], value: Any):
|
||||
if isinstance(value, dict):
|
||||
value[self.key] = slug
|
||||
|
||||
for child_slug, child_value in value.items():
|
||||
inner(slug + [child_slug], child_value)
|
||||
|
||||
return
|
||||
|
||||
if isinstance(value, list):
|
||||
for child_value in value:
|
||||
inner(slug, child_value)
|
||||
|
||||
copied = deepcopy(obj)
|
||||
inner([], copied)
|
||||
return copied
|
||||
|
||||
def slugs(self, obj: dict[str, Any]) -> list[str]:
|
||||
return obj[self.key]
|
||||
|
||||
def clean(self, obj: dict[str, Any]) -> dict[str, Any]:
|
||||
copied = deepcopy(obj)
|
||||
del copied[self.key]
|
||||
return copied
|
||||
|
||||
class CodingKey(StrEnum):
|
||||
@classmethod
|
||||
def keywords(cls, obj: dict[str, Any]) -> dict[str, Any]:
|
||||
words = {}
|
||||
|
||||
for pair in list(cls):
|
||||
# Errors are false positives.
|
||||
native = pair.name # type: ignore
|
||||
foreign = pair.value # type: ignore
|
||||
value = obj.get(foreign)
|
||||
words[native] = value
|
||||
|
||||
return words
|
||||
|
||||
class Codable():
|
||||
__decoder = JSONDecoder()
|
||||
__encoder = JSONEncoder()
|
||||
__monkey = Monkey()
|
||||
|
||||
class CodingKeys(CodingKey):
|
||||
pass
|
||||
|
||||
@classmethod
|
||||
def decode(cls, content: str) -> Self:
|
||||
decoded = cls.__decoder.decode(content)
|
||||
patched = cls.__monkey.patch(decoded)
|
||||
encoded = cls.__encoder.encode(patched)
|
||||
decoder = Decoder(
|
||||
monkey=cls.__monkey,
|
||||
cls=cls
|
||||
)
|
||||
return decoder.decode(encoded)
|
||||
|
||||
def encode(self) -> str:
|
||||
cls = type(self)
|
||||
encoder = Encoder(
|
||||
decoder=self.__decoder,
|
||||
cls=cls
|
||||
)
|
||||
return encoder.encode(self)
|
||||
|
||||
class Decoder(JSONDecoder):
|
||||
monkey: Monkey
|
||||
cls: Type[Codable]
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
monkey: Monkey,
|
||||
cls: Type[Codable],
|
||||
**kwargs
|
||||
):
|
||||
self.monkey = monkey
|
||||
self.cls = cls
|
||||
kwargs['object_hook'] = self.__object_hook
|
||||
super().__init__(**kwargs)
|
||||
|
||||
def __object_hook(self, obj):
|
||||
cls = self.cls
|
||||
|
||||
for foreign in self.monkey.slugs(obj):
|
||||
native = cls.CodingKeys(foreign).name
|
||||
|
||||
if native is None:
|
||||
return self.monkey.clean(obj)
|
||||
|
||||
types = get_type_hints(cls)
|
||||
cls = self.__find_codable(types[native])
|
||||
|
||||
if cls is None:
|
||||
return self.monkey.clean(obj)
|
||||
|
||||
cleaned = self.monkey.clean(obj)
|
||||
return self.__init_codable(cls, cleaned)
|
||||
|
||||
def __find_codable(self, cls: Type) -> Optional[Type[Codable]]:
|
||||
if issubclass(cls, Codable):
|
||||
return cls
|
||||
|
||||
if get_origin(cls) is list:
|
||||
item = get_args(cls)[0]
|
||||
return self.__find_codable(item)
|
||||
|
||||
return None
|
||||
|
||||
def __init_codable(self, cls: Type[Codable], obj: dict[str, Any]) -> Codable:
|
||||
keywords = cls.CodingKeys.keywords(obj)
|
||||
return cls(**keywords)
|
||||
|
||||
class Encoder(JSONEncoder):
|
||||
decoder: JSONDecoder
|
||||
cls: Type[Codable]
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
decoder: JSONDecoder,
|
||||
cls: Type[Codable],
|
||||
indent: int = 2,
|
||||
**kwargs
|
||||
):
|
||||
self.decoder = decoder
|
||||
self.cls = cls
|
||||
kwargs['indent'] = indent
|
||||
super().__init__(**kwargs)
|
||||
|
||||
def default(self, o):
|
||||
obj = {}
|
||||
|
||||
for pair in list(self.cls.CodingKeys):
|
||||
native = pair.name
|
||||
foreign = pair.value
|
||||
|
||||
if not hasattr(o, native):
|
||||
continue
|
||||
|
||||
value = getattr(o, native)
|
||||
obj[foreign] = self.__prepare_value(value)
|
||||
|
||||
return obj
|
||||
|
||||
def __prepare_value(self, value: Any) -> Any:
|
||||
if isinstance(value, Codable):
|
||||
return self.__prepare_codable(value)
|
||||
|
||||
if isinstance(value, list):
|
||||
return self.__prepare_list(value)
|
||||
|
||||
return value
|
||||
|
||||
def __prepare_codable(self, value: Codable) -> Any:
|
||||
content = value.encode()
|
||||
return self.decoder.decode(content)
|
||||
|
||||
def __prepare_list(self, value: list[Any]) -> list[Any]:
|
||||
mapped = map(self.__prepare_value, value)
|
||||
return list(mapped)
|
||||
154
web/documentserver-example/python/src/codable/codable_tests.py
Normal file
154
web/documentserver-example/python/src/codable/codable_tests.py
Normal file
@ -0,0 +1,154 @@
|
||||
#
|
||||
# (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.
|
||||
#
|
||||
|
||||
from __future__ import annotations
|
||||
from dataclasses import dataclass
|
||||
from textwrap import dedent
|
||||
from typing import Optional
|
||||
from unittest import TestCase
|
||||
from . import Codable, CodingKey
|
||||
|
||||
@dataclass
|
||||
class Fruit(Codable):
|
||||
class CodingKeys(CodingKey):
|
||||
name = 'fruit_name'
|
||||
weight = 'fruitWeight'
|
||||
texture = 'fruit_texture'
|
||||
vitamins = 'fruitVitamins'
|
||||
organic = 'fruit_organic'
|
||||
|
||||
name: str
|
||||
weight: int
|
||||
texture: Optional[str]
|
||||
vitamins: list[str]
|
||||
organic: bool
|
||||
|
||||
class CodablePlainTests(TestCase):
|
||||
json = (
|
||||
dedent(
|
||||
'''
|
||||
{
|
||||
"fruit_name": "kiwi",
|
||||
"fruitWeight": 100,
|
||||
"fruit_texture": null,
|
||||
"fruitVitamins": [
|
||||
"Vitamin C",
|
||||
"Vitamin K"
|
||||
],
|
||||
"fruit_organic": true
|
||||
}
|
||||
'''
|
||||
)
|
||||
.strip()
|
||||
)
|
||||
|
||||
def test_decodes(self):
|
||||
fruit = Fruit.decode(self.json)
|
||||
self.assertEqual(fruit.name, 'kiwi')
|
||||
self.assertEqual(fruit.weight, 100)
|
||||
self.assertIsNone(fruit.texture)
|
||||
self.assertEqual(fruit.vitamins, ['Vitamin C', 'Vitamin K'])
|
||||
self.assertTrue(fruit.organic)
|
||||
|
||||
def test_encodes(self):
|
||||
fruit = Fruit(
|
||||
name='kiwi',
|
||||
weight=100,
|
||||
texture=None,
|
||||
vitamins=['Vitamin C', 'Vitamin K'],
|
||||
organic=True
|
||||
)
|
||||
content = fruit.encode()
|
||||
self.assertEqual(content, self.json)
|
||||
|
||||
@dataclass
|
||||
class Smoothie(Codable):
|
||||
class CodingKeys(CodingKey):
|
||||
recipe = 'recipe'
|
||||
|
||||
recipe: Recipe
|
||||
|
||||
@dataclass
|
||||
class Recipe(Codable):
|
||||
class CodingKeys(CodingKey):
|
||||
ingredients = 'ingredients'
|
||||
|
||||
ingredients: list[Ingredient]
|
||||
|
||||
@dataclass
|
||||
class Ingredient(Codable):
|
||||
class CodingKeys(CodingKey):
|
||||
name = 'name'
|
||||
|
||||
name: str
|
||||
|
||||
class CodableNestedTests(TestCase):
|
||||
json = (
|
||||
dedent(
|
||||
'''
|
||||
{
|
||||
"recipe": {
|
||||
"ingredients": [
|
||||
{
|
||||
"name": "kiwi"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
'''
|
||||
)
|
||||
.strip()
|
||||
)
|
||||
|
||||
def test_decodes(self):
|
||||
smoothie = Smoothie.decode(self.json)
|
||||
self.assertEqual(smoothie.recipe.ingredients[0].name, 'kiwi')
|
||||
|
||||
def test_encodes(self):
|
||||
ingredient = Ingredient(name='kiwi')
|
||||
recipe = Recipe(ingredients=[ingredient])
|
||||
smoothie = Smoothie(recipe=recipe)
|
||||
content = smoothie.encode()
|
||||
self.assertEqual(content, self.json)
|
||||
|
||||
@dataclass
|
||||
class Vegetable(Codable):
|
||||
class CodingKeys(CodingKey):
|
||||
name = 'name'
|
||||
|
||||
name: Optional[str]
|
||||
|
||||
class CodableMissedTests(TestCase):
|
||||
source_json = '{}'
|
||||
distribute_json = (
|
||||
dedent(
|
||||
'''
|
||||
{
|
||||
"name": null
|
||||
}
|
||||
'''
|
||||
)
|
||||
.strip()
|
||||
)
|
||||
|
||||
def test_decodes(self):
|
||||
vegetable = Vegetable.decode(self.source_json)
|
||||
self.assertIsNone(vegetable.name)
|
||||
|
||||
def test_encodes(self):
|
||||
vegetable = Vegetable(name=None)
|
||||
content = vegetable.encode()
|
||||
self.assertEqual(content, self.distribute_json)
|
||||
@ -19,4 +19,5 @@ The common module is a collection of small, generic functions that are
|
||||
independent of business logic.
|
||||
'''
|
||||
|
||||
from . import http
|
||||
from . import string
|
||||
|
||||
49
web/documentserver-example/python/src/common/http.py
Normal file
49
web/documentserver-example/python/src/common/http.py
Normal file
@ -0,0 +1,49 @@
|
||||
#
|
||||
# (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.
|
||||
#
|
||||
|
||||
# TODO: add types for parameters.
|
||||
# https://github.com/python/typing/discussions/946r
|
||||
|
||||
from http import HTTPStatus, HTTPMethod
|
||||
from django.http import HttpRequest, HttpResponse
|
||||
|
||||
def GET():
|
||||
return method(HTTPMethod.GET)
|
||||
|
||||
def POST():
|
||||
return method(HTTPMethod.POST)
|
||||
|
||||
def PUT():
|
||||
return method(HTTPMethod.PUT)
|
||||
|
||||
def method(meth: HTTPMethod):
|
||||
def wrapper(func):
|
||||
def inner(request: HttpRequest, *args, **kwargs):
|
||||
if request.method is None:
|
||||
return HttpResponse(
|
||||
status=HTTPStatus.METHOD_NOT_ALLOWED
|
||||
)
|
||||
|
||||
if request.method.upper() != meth.name:
|
||||
return HttpResponse(
|
||||
status=HTTPStatus.METHOD_NOT_ALLOWED
|
||||
)
|
||||
|
||||
return func(request, *args, **kwargs)
|
||||
|
||||
return inner
|
||||
|
||||
return wrapper
|
||||
41
web/documentserver-example/python/src/common/http_tests.py
Normal file
41
web/documentserver-example/python/src/common/http_tests.py
Normal file
@ -0,0 +1,41 @@
|
||||
#
|
||||
# (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.
|
||||
#
|
||||
|
||||
from http import HTTPMethod, HTTPStatus
|
||||
from unittest import TestCase
|
||||
from django.conf import settings
|
||||
from django.http import HttpRequest, HttpResponse
|
||||
from . import http
|
||||
|
||||
# Under the hood, HttpRequest uses a settings object.
|
||||
settings.configure()
|
||||
|
||||
@http.GET()
|
||||
def endpoint(_: HttpRequest) -> HttpResponse:
|
||||
return HttpResponse()
|
||||
|
||||
class HTTPMethodTests(TestCase):
|
||||
def test_returns_a_response_from_the_endpoint(self):
|
||||
request = HttpRequest()
|
||||
request.method = HTTPMethod.GET
|
||||
response = endpoint(request)
|
||||
self.assertEqual(response.status_code, HTTPStatus.OK)
|
||||
|
||||
def test_returns_an_error_response(self):
|
||||
request = HttpRequest()
|
||||
request.method = HTTPMethod.POST
|
||||
response = endpoint(request)
|
||||
self.assertEqual(response.status_code, HTTPStatus.METHOD_NOT_ALLOWED)
|
||||
@ -29,15 +29,21 @@ class ConfigurationManager:
|
||||
return None
|
||||
return urlparse(url)
|
||||
|
||||
def document_server_url(self) -> ParseResult:
|
||||
def document_server_public_url(self) -> ParseResult:
|
||||
url = (
|
||||
environ.get('DOCUMENT_SERVER_URL') or
|
||||
environ.get('DOCUMENT_SERVER_PUBLIC_URL') or
|
||||
'http://document-server'
|
||||
)
|
||||
return urlparse(url)
|
||||
|
||||
def document_server_private_url(self) -> ParseResult:
|
||||
url = environ.get('DOCUMENT_SERVER_PRIVATE_URL')
|
||||
if not url:
|
||||
return self.document_server_public_url()
|
||||
return urlparse(url)
|
||||
|
||||
def document_server_api_url(self) -> ParseResult:
|
||||
server_url = self.document_server_url()
|
||||
server_url = self.document_server_public_url()
|
||||
base_url = server_url.geturl()
|
||||
path = (
|
||||
environ.get('DOCUMENT_SERVER_API_PATH') or
|
||||
@ -47,7 +53,7 @@ class ConfigurationManager:
|
||||
return urlparse(url)
|
||||
|
||||
def document_server_preloader_url(self) -> ParseResult:
|
||||
server_url = self.document_server_url()
|
||||
server_url = self.document_server_public_url()
|
||||
base_url = server_url.geturl()
|
||||
path = (
|
||||
environ.get('DOCUMENT_SERVER_PRELOADER_PATH') or
|
||||
@ -57,7 +63,7 @@ class ConfigurationManager:
|
||||
return urlparse(url)
|
||||
|
||||
def document_server_command_url(self) -> ParseResult:
|
||||
server_url = self.document_server_url()
|
||||
server_url = self.document_server_private_url()
|
||||
base_url = server_url.geturl()
|
||||
path = (
|
||||
environ.get('DOCUMENT_SERVER_COMMAND_PATH') or
|
||||
@ -67,7 +73,7 @@ class ConfigurationManager:
|
||||
return urlparse(url)
|
||||
|
||||
def document_server_converter_url(self) -> ParseResult:
|
||||
server_url = self.document_server_url()
|
||||
server_url = self.document_server_private_url()
|
||||
base_url = server_url.geturl()
|
||||
path = (
|
||||
environ.get('DOCUMENT_SERVER_CONVERTER_PATH') or
|
||||
@ -111,78 +117,6 @@ class ConfigurationManager:
|
||||
return int(timeout)
|
||||
return 120 * 1000
|
||||
|
||||
def fillable_file_extensions(self) -> list[str]:
|
||||
return [
|
||||
'.docx',
|
||||
'.oform'
|
||||
]
|
||||
|
||||
def viewable_file_extensions(self) -> list[str]:
|
||||
return [
|
||||
'.djvu',
|
||||
'.oxps',
|
||||
'.pdf',
|
||||
'.xps'
|
||||
]
|
||||
|
||||
def editable_file_extensions(self) -> list[str]:
|
||||
return [
|
||||
'.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'
|
||||
]
|
||||
|
||||
def convertible_file_extensions(self) -> list[str]:
|
||||
return [
|
||||
'.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'
|
||||
]
|
||||
|
||||
def spreadsheet_file_extensions(self) -> list[str]:
|
||||
return [
|
||||
'.xls', '.xlsx',
|
||||
'.xlsm', '.xlsb',
|
||||
'.xlt', '.xltx',
|
||||
'.xltm', '.ods',
|
||||
'.fods', '.ots',
|
||||
'.csv'
|
||||
]
|
||||
|
||||
def presentation_file_extensions(self) -> list[str]:
|
||||
return [
|
||||
'.pps', '.ppsx',
|
||||
'.ppsm', '.ppt',
|
||||
'.pptx', '.pptm',
|
||||
'.pot', '.potx',
|
||||
'.potm', '.odp',
|
||||
'.fodp', '.otp'
|
||||
]
|
||||
|
||||
def document_file_extensions(self) -> list[str]:
|
||||
return [
|
||||
'.doc', '.docx', '.docm',
|
||||
'.dot', '.dotx', '.dotm',
|
||||
'.odt', '.fodt', '.ott',
|
||||
'.rtf', '.txt', '.html',
|
||||
'.htm', '.mht', '.xml',
|
||||
'.pdf', '.djvu', '.fb2',
|
||||
'.epub', '.xps', '.oxps',
|
||||
'.oform'
|
||||
]
|
||||
|
||||
def languages(self) -> dict[str, str]:
|
||||
return {
|
||||
'en': 'English',
|
||||
|
||||
@ -17,6 +17,7 @@
|
||||
from os import environ
|
||||
from unittest import TestCase
|
||||
from unittest.mock import patch
|
||||
from urllib.parse import urlparse
|
||||
from . import ConfigurationManager
|
||||
|
||||
class ConfigurationManagerTests(TestCase):
|
||||
@ -38,98 +39,152 @@ class ConfigurationManagerExampleURLTests(TestCase):
|
||||
url = config_manager.example_url()
|
||||
self.assertEqual(url.geturl(), 'http://localhost')
|
||||
|
||||
class ConfigurationManagerDocumentServerURLTests(TestCase):
|
||||
class ConfigurationManagerDocumentServerPublicURLTests(TestCase):
|
||||
def test_assigns_a_default_value(self):
|
||||
config_manager = ConfigurationManager()
|
||||
url = config_manager.document_server_url()
|
||||
url = config_manager.document_server_public_url()
|
||||
self.assertEqual(url.geturl(), 'http://document-server')
|
||||
|
||||
@patch.dict(environ, {
|
||||
'DOCUMENT_SERVER_URL': 'http://localhost'
|
||||
'DOCUMENT_SERVER_PUBLIC_URL': 'http://localhost'
|
||||
})
|
||||
def test_assigns_a_value_from_the_environment(self):
|
||||
config_manager = ConfigurationManager()
|
||||
url = config_manager.document_server_url()
|
||||
url = config_manager.document_server_public_url()
|
||||
self.assertEqual(url.geturl(), 'http://localhost')
|
||||
|
||||
class ConfigurationManagerDocumentServerPrivateURLTests(TestCase):
|
||||
def test_assigns_a_default_value(self):
|
||||
config_manager = ConfigurationManager()
|
||||
url = config_manager.document_server_private_url()
|
||||
self.assertEqual(url.geturl(), 'http://document-server')
|
||||
|
||||
@patch.dict(environ, {
|
||||
'DOCUMENT_SERVER_PRIVATE_URL': 'http://localhost'
|
||||
})
|
||||
def test_assigns_a_value_from_the_environment(self):
|
||||
config_manager = ConfigurationManager()
|
||||
url = config_manager.document_server_private_url()
|
||||
self.assertEqual(url.geturl(), 'http://localhost')
|
||||
|
||||
class ConfigurationManagerDocumentServerAPIURLTests(TestCase):
|
||||
def test_assigns_a_default_value(self):
|
||||
@patch.object(
|
||||
ConfigurationManager,
|
||||
'document_server_public_url',
|
||||
return_value=urlparse('http://localhost')
|
||||
)
|
||||
def test_assigns_a_default_value(self, _):
|
||||
config_manager = ConfigurationManager()
|
||||
url = config_manager.document_server_api_url()
|
||||
self.assertEqual(
|
||||
url.geturl(),
|
||||
'http://document-server/web-apps/apps/api/documents/api.js'
|
||||
'http://localhost/web-apps/apps/api/documents/api.js'
|
||||
)
|
||||
|
||||
@patch.object(
|
||||
ConfigurationManager,
|
||||
'document_server_public_url',
|
||||
return_value=urlparse('http://localhost')
|
||||
)
|
||||
@patch.dict(environ, {
|
||||
'DOCUMENT_SERVER_API_PATH': '/api'
|
||||
})
|
||||
def test_assigns_a_value_from_the_environment(self):
|
||||
def test_assigns_a_value_from_the_environment(self, _):
|
||||
config_manager = ConfigurationManager()
|
||||
url = config_manager.document_server_api_url()
|
||||
self.assertEqual(
|
||||
url.geturl(),
|
||||
'http://document-server/api'
|
||||
'http://localhost/api'
|
||||
)
|
||||
|
||||
class ConfigurationManagerDocumentServerPreloaderURLTests(TestCase):
|
||||
def test_assigns_a_default_value(self):
|
||||
@patch.object(
|
||||
ConfigurationManager,
|
||||
'document_server_public_url',
|
||||
return_value=urlparse('http://localhost')
|
||||
)
|
||||
def test_assigns_a_default_value(self, _):
|
||||
config_manager = ConfigurationManager()
|
||||
url = config_manager.document_server_preloader_url()
|
||||
self.assertEqual(
|
||||
url.geturl(),
|
||||
'http://document-server/web-apps/apps/api/documents/cache-scripts.html'
|
||||
'http://localhost/web-apps/apps/api/documents/cache-scripts.html'
|
||||
)
|
||||
|
||||
@patch.object(
|
||||
ConfigurationManager,
|
||||
'document_server_public_url',
|
||||
return_value=urlparse('http://localhost')
|
||||
)
|
||||
@patch.dict(environ, {
|
||||
'DOCUMENT_SERVER_PRELOADER_PATH': '/preloader'
|
||||
})
|
||||
def test_assigns_a_value_from_the_environment(self):
|
||||
def test_assigns_a_value_from_the_environment(self, _):
|
||||
config_manager = ConfigurationManager()
|
||||
url = config_manager.document_server_preloader_url()
|
||||
self.assertEqual(
|
||||
url.geturl(),
|
||||
'http://document-server/preloader'
|
||||
'http://localhost/preloader'
|
||||
)
|
||||
|
||||
class ConfigurationManagerDocumentServerCommandURLTests(TestCase):
|
||||
def test_assigns_a_default_value(self):
|
||||
@patch.object(
|
||||
ConfigurationManager,
|
||||
'document_server_private_url',
|
||||
return_value=urlparse('http://localhost')
|
||||
)
|
||||
def test_assigns_a_default_value(self, _):
|
||||
config_manager = ConfigurationManager()
|
||||
url = config_manager.document_server_command_url()
|
||||
self.assertEqual(
|
||||
url.geturl(),
|
||||
'http://document-server/coauthoring/CommandService.ashx'
|
||||
'http://localhost/coauthoring/CommandService.ashx'
|
||||
)
|
||||
|
||||
@patch.object(
|
||||
ConfigurationManager,
|
||||
'document_server_private_url',
|
||||
return_value=urlparse('http://localhost')
|
||||
)
|
||||
@patch.dict(environ, {
|
||||
'DOCUMENT_SERVER_COMMAND_PATH': '/command'
|
||||
})
|
||||
def test_assigns_a_value_from_the_environment(self):
|
||||
def test_assigns_a_value_from_the_environment(self, _):
|
||||
config_manager = ConfigurationManager()
|
||||
url = config_manager.document_server_command_url()
|
||||
self.assertEqual(
|
||||
url.geturl(),
|
||||
'http://document-server/command'
|
||||
'http://localhost/command'
|
||||
)
|
||||
|
||||
class ConfigurationManagerDocumentServerConverterURLTests(TestCase):
|
||||
def test_assigns_a_default_value(self):
|
||||
@patch.object(
|
||||
ConfigurationManager,
|
||||
'document_server_private_url',
|
||||
return_value=urlparse('http://localhost')
|
||||
)
|
||||
def test_assigns_a_default_value(self, _):
|
||||
config_manager = ConfigurationManager()
|
||||
url = config_manager.document_server_converter_url()
|
||||
self.assertEqual(
|
||||
url.geturl(),
|
||||
'http://document-server/ConvertService.ashx'
|
||||
'http://localhost/ConvertService.ashx'
|
||||
)
|
||||
|
||||
@patch.object(
|
||||
ConfigurationManager,
|
||||
'document_server_private_url',
|
||||
return_value=urlparse('http://localhost')
|
||||
)
|
||||
@patch.dict(environ, {
|
||||
'DOCUMENT_SERVER_CONVERTER_PATH': '/converter'
|
||||
})
|
||||
def test_assigns_a_value_from_the_environment(self):
|
||||
def test_assigns_a_value_from_the_environment(self, _):
|
||||
config_manager = ConfigurationManager()
|
||||
url = config_manager.document_server_converter_url()
|
||||
self.assertEqual(
|
||||
url.geturl(),
|
||||
'http://document-server/converter'
|
||||
'http://localhost/converter'
|
||||
)
|
||||
|
||||
class ConfigurationManagerJWTSecretTests(TestCase):
|
||||
|
||||
17
web/documentserver-example/python/src/format/__init__.py
Normal file
17
web/documentserver-example/python/src/format/__init__.py
Normal file
@ -0,0 +1,17 @@
|
||||
#
|
||||
# (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.
|
||||
#
|
||||
|
||||
from .format import *
|
||||
177
web/documentserver-example/python/src/format/format.py
Normal file
177
web/documentserver-example/python/src/format/format.py
Normal file
@ -0,0 +1,177 @@
|
||||
#
|
||||
# (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.
|
||||
#
|
||||
|
||||
from dataclasses import dataclass
|
||||
from json import dumps, loads
|
||||
from pathlib import Path
|
||||
from src.codable import Codable, CodingKey
|
||||
|
||||
@dataclass
|
||||
class Format(Codable):
|
||||
class CodingKeys(CodingKey):
|
||||
name = 'name'
|
||||
type = 'type'
|
||||
actions = 'actions'
|
||||
convert = 'convert'
|
||||
mime = 'mime'
|
||||
|
||||
name: str
|
||||
type: str
|
||||
actions: list[str]
|
||||
convert: list[str]
|
||||
mime: list[str]
|
||||
|
||||
def extension(self) -> str:
|
||||
return f'.{self.name}'
|
||||
|
||||
class FormatManager():
|
||||
def spreadsheet_extensions(self) -> list[str]:
|
||||
formats = self.spreadsheets()
|
||||
mapped = map(lambda format: format.extension(), formats)
|
||||
return list(mapped)
|
||||
|
||||
def spreadsheets(self) -> list[Format]:
|
||||
formats = self.all()
|
||||
mapped = filter(lambda format: format.type == 'cell', formats)
|
||||
return list(mapped)
|
||||
|
||||
def presentation_extensions(self) -> list[str]:
|
||||
formats = self.presentations()
|
||||
mapped = map(lambda format: format.extension(), formats)
|
||||
return list(mapped)
|
||||
|
||||
def presentations(self) -> list[Format]:
|
||||
formats = self.all()
|
||||
mapped = filter(lambda format: format.type == 'slide', formats)
|
||||
return list(mapped)
|
||||
|
||||
def document_extensions(self) -> list[str]:
|
||||
formats = self.documents()
|
||||
mapped = map(lambda format: format.extension(), formats)
|
||||
return list(mapped)
|
||||
|
||||
def documents(self) -> list[Format]:
|
||||
formats = self.all()
|
||||
mapped = filter(lambda format: format.type == 'word', formats)
|
||||
return list(mapped)
|
||||
|
||||
def fillable_extensions(self) -> list[str]:
|
||||
formats = self.fillable()
|
||||
mapped = map(lambda format: format.extension(), formats)
|
||||
return list(mapped)
|
||||
|
||||
def fillable(self) -> list[Format]:
|
||||
formats = self.all()
|
||||
mapped = filter(lambda format: 'fill' in format.actions, formats)
|
||||
return list(mapped)
|
||||
|
||||
def viewable_extensions(self) -> list[str]:
|
||||
formats = self.viewable()
|
||||
mapped = map(lambda format: format.extension(), formats)
|
||||
return list(mapped)
|
||||
|
||||
def viewable(self) -> list[Format]:
|
||||
formats = self.all()
|
||||
mapped = filter(lambda format: 'view' in format.actions, formats)
|
||||
return list(mapped)
|
||||
|
||||
def editable_extensions(self) -> list[str]:
|
||||
formats = self.editable()
|
||||
mapped = map(lambda format: format.extension(), formats)
|
||||
return list(mapped)
|
||||
|
||||
def editable(self) -> list[Format]:
|
||||
formats = self.all()
|
||||
mapped = filter(
|
||||
lambda format: (
|
||||
'edit' in format.actions or
|
||||
'lossy-edit' in format.actions
|
||||
),
|
||||
formats
|
||||
)
|
||||
return list(mapped)
|
||||
|
||||
def convertible_to_names(self, extension) -> list[str]:
|
||||
formats = self.convertible_to(extension)
|
||||
mapped = map(lambda format: format.name, formats)
|
||||
return list(mapped)
|
||||
|
||||
def convertible_to(self, extension) -> list[Format]:
|
||||
formats = self.all()
|
||||
filtered: list[Format] = []
|
||||
names: list[str] = []
|
||||
|
||||
for format in formats:
|
||||
if format.extension() == extension:
|
||||
names = format.convert
|
||||
break
|
||||
|
||||
for name in names:
|
||||
for format in formats:
|
||||
if format.name == name:
|
||||
filtered.append(format)
|
||||
break
|
||||
|
||||
return list(filtered)
|
||||
|
||||
def convertible_extensions(self) -> list[str]:
|
||||
formats = self.convertible()
|
||||
mapped = map(lambda format: format.extension(), formats)
|
||||
return list(mapped)
|
||||
|
||||
def convertible(self) -> list[Format]:
|
||||
formats = self.all()
|
||||
filtered = filter(
|
||||
lambda format: (
|
||||
format.type == 'cell' and 'xlsx' in format.convert or
|
||||
format.type == 'slide' and 'pptx' in format.convert or
|
||||
format.type == 'word' and 'docx' in format.convert
|
||||
),
|
||||
formats
|
||||
)
|
||||
return list(filtered)
|
||||
|
||||
def all_extensions(self) -> list[str]:
|
||||
formats = self.all()
|
||||
mapped = map(lambda format: format.extension(), formats)
|
||||
return list(mapped)
|
||||
|
||||
def all(self) -> list[Format]:
|
||||
path = self.__file()
|
||||
formats: list[Format] = []
|
||||
with open(path, 'r', encoding='utf-8') as file:
|
||||
content = file.read()
|
||||
array = loads(content)
|
||||
for obj in array:
|
||||
raw = dumps(obj)
|
||||
decoded = Format.decode(raw)
|
||||
formats.append(decoded)
|
||||
return formats
|
||||
|
||||
def __file(self) -> Path:
|
||||
directory = self.__directory()
|
||||
return directory.joinpath('onlyoffice-docs-formats.json')
|
||||
|
||||
def __directory(self) -> Path:
|
||||
current_file = Path(__file__)
|
||||
directory = current_file.joinpath(
|
||||
'..',
|
||||
'..',
|
||||
'..',
|
||||
'assets',
|
||||
'document-formats'
|
||||
)
|
||||
return directory.resolve()
|
||||
104
web/documentserver-example/python/src/format/format_tests.py
Normal file
104
web/documentserver-example/python/src/format/format_tests.py
Normal file
@ -0,0 +1,104 @@
|
||||
#
|
||||
# (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.
|
||||
#
|
||||
|
||||
from __future__ import annotations
|
||||
from unittest import TestCase
|
||||
from . import Format, FormatManager
|
||||
|
||||
class FormatTests(TestCase):
|
||||
json = \
|
||||
'''
|
||||
{
|
||||
"name": "djvu",
|
||||
"type": "word",
|
||||
"actions": ["view"],
|
||||
"convert": ["bmp", "gif", "jpg", "pdf", "pdfa", "png"],
|
||||
"mime": ["image/vnd.djvu"]
|
||||
}
|
||||
'''
|
||||
|
||||
def test_generates_extension(self):
|
||||
form = Format.decode(self.json)
|
||||
self.assertEqual(form.extension(), '.djvu')
|
||||
|
||||
class FormatManagerAllTests(TestCase):
|
||||
def test_loads(self):
|
||||
format_manager = FormatManager()
|
||||
formats = format_manager.all()
|
||||
empty = len(formats) == 0
|
||||
self.assertFalse(empty)
|
||||
|
||||
class FormatManagerDocumentsTests(TestCase):
|
||||
def test_loads(self):
|
||||
format_manager = FormatManager()
|
||||
formats = format_manager.documents()
|
||||
mapped = map(lambda format: format.type == 'word', formats)
|
||||
self.assertTrue(all(mapped))
|
||||
|
||||
class FormatManagerPresentationsTests(TestCase):
|
||||
def test_loads(self):
|
||||
format_manager = FormatManager()
|
||||
formats = format_manager.presentations()
|
||||
mapped = map(lambda format: format.type == 'slide', formats)
|
||||
self.assertTrue(all(mapped))
|
||||
|
||||
class FormatManagerSpreadsheetsTests(TestCase):
|
||||
def test_loads(self):
|
||||
format_manager = FormatManager()
|
||||
formats = format_manager.spreadsheets()
|
||||
mapped = map(lambda format: format.type == 'cell', formats)
|
||||
self.assertTrue(all(mapped))
|
||||
|
||||
class FormatManagerConvertibleTests(TestCase):
|
||||
def test_loads(self):
|
||||
format_manager = FormatManager()
|
||||
formats = format_manager.convertible()
|
||||
mapped = map(
|
||||
lambda format: (
|
||||
format.type == 'cell' and 'xlsx' in format.actions or
|
||||
format.type == 'slide' and 'pptx' in format.actions or
|
||||
format.type == 'word' and 'docx' in format.actions
|
||||
),
|
||||
formats
|
||||
)
|
||||
self.assertTrue(all(mapped))
|
||||
|
||||
class FormatManagerEditableTests(TestCase):
|
||||
def test_loads(self):
|
||||
format_manager = FormatManager()
|
||||
formats = format_manager.editable()
|
||||
mapped = map(
|
||||
lambda format: (
|
||||
'edit' in format.actions or
|
||||
'lossy-edit' in format.actions
|
||||
),
|
||||
formats
|
||||
)
|
||||
self.assertTrue(all(mapped))
|
||||
|
||||
class FormatManagerViewableTests(TestCase):
|
||||
def test_loads(self):
|
||||
format_manager = FormatManager()
|
||||
formats = format_manager.viewable()
|
||||
mapped = map(lambda format: 'view' in format.actions, formats)
|
||||
self.assertTrue(all(mapped))
|
||||
|
||||
class FormatManagerFillableTests(TestCase):
|
||||
def test_loads(self):
|
||||
format_manager = FormatManager()
|
||||
formats = format_manager.fillable()
|
||||
mapped = map(lambda format: 'fill' in format.actions, formats)
|
||||
self.assertTrue(all(mapped))
|
||||
17
web/documentserver-example/python/src/proxy/__init__.py
Normal file
17
web/documentserver-example/python/src/proxy/__init__.py
Normal file
@ -0,0 +1,17 @@
|
||||
#
|
||||
# (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.
|
||||
#
|
||||
|
||||
from .proxy import *
|
||||
48
web/documentserver-example/python/src/proxy/proxy.py
Normal file
48
web/documentserver-example/python/src/proxy/proxy.py
Normal file
@ -0,0 +1,48 @@
|
||||
#
|
||||
# (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.
|
||||
#
|
||||
|
||||
from urllib.parse import ParseResult
|
||||
from src.configuration import ConfigurationManager
|
||||
|
||||
class ProxyManager():
|
||||
config_manager: ConfigurationManager
|
||||
|
||||
def __init__(self, config_manager: ConfigurationManager):
|
||||
self.config_manager = config_manager
|
||||
|
||||
def resolve_url(self, url: ParseResult) -> ParseResult:
|
||||
if not self.__refer_public_url(url):
|
||||
return url
|
||||
return self.__redirect_public_url(url)
|
||||
|
||||
def __refer_public_url(self, url: ParseResult) -> bool:
|
||||
public_url = self.config_manager.document_server_public_url()
|
||||
return (
|
||||
url.scheme == public_url.scheme and
|
||||
url.hostname == public_url.hostname and
|
||||
url.port == public_url.port
|
||||
)
|
||||
|
||||
def __redirect_public_url(self, url: ParseResult) -> ParseResult:
|
||||
private_url = self.config_manager.document_server_private_url()
|
||||
return ParseResult(
|
||||
scheme=private_url.scheme,
|
||||
netloc=private_url.netloc,
|
||||
path=url.path,
|
||||
params=url.params,
|
||||
query=url.query,
|
||||
fragment=url.fragment
|
||||
)
|
||||
63
web/documentserver-example/python/src/proxy/proxy_tests.py
Normal file
63
web/documentserver-example/python/src/proxy/proxy_tests.py
Normal file
@ -0,0 +1,63 @@
|
||||
#
|
||||
# (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.
|
||||
#
|
||||
|
||||
from unittest import TestCase
|
||||
from unittest.mock import patch
|
||||
from urllib.parse import urlparse
|
||||
from src.configuration import ConfigurationManager
|
||||
from . import ProxyManager
|
||||
|
||||
class ProxyManagerTests(TestCase):
|
||||
@patch.object(
|
||||
ConfigurationManager,
|
||||
'document_server_public_url',
|
||||
return_value=urlparse('http://localhost')
|
||||
)
|
||||
@patch.object(
|
||||
ConfigurationManager,
|
||||
'document_server_private_url',
|
||||
return_value=urlparse('http://proxy')
|
||||
)
|
||||
def test_resolves_a_url_that_refers_to_the_public_url(self, *_):
|
||||
config_manager = ConfigurationManager()
|
||||
proxy_manager = ProxyManager(config_manager)
|
||||
|
||||
raw_url = 'http://localhost/endpoint?query=string'
|
||||
url = urlparse(raw_url)
|
||||
resolved_url = proxy_manager.resolve_url(url)
|
||||
|
||||
self.assertEqual(
|
||||
resolved_url.geturl(),
|
||||
'http://proxy/endpoint?query=string'
|
||||
)
|
||||
|
||||
@patch.object(
|
||||
ConfigurationManager,
|
||||
'document_server_public_url',
|
||||
return_value=urlparse('http://localhost')
|
||||
)
|
||||
def test_resolves_a_url_that_does_not_refers_to_the_public_url(self, *_):
|
||||
config_manager = ConfigurationManager()
|
||||
proxy_manager = ProxyManager(config_manager)
|
||||
|
||||
raw_url = 'http://proxy/endpoint?query=string'
|
||||
url = urlparse(raw_url)
|
||||
resolved_url = proxy_manager.resolve_url(url)
|
||||
|
||||
self.assertEqual(
|
||||
resolved_url.geturl(),
|
||||
'http://proxy/endpoint?query=string'
|
||||
)
|
||||
17
web/documentserver-example/python/src/response/__init__.py
Normal file
17
web/documentserver-example/python/src/response/__init__.py
Normal file
@ -0,0 +1,17 @@
|
||||
#
|
||||
# (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.
|
||||
#
|
||||
|
||||
from .response import *
|
||||
32
web/documentserver-example/python/src/response/response.py
Normal file
32
web/documentserver-example/python/src/response/response.py
Normal file
@ -0,0 +1,32 @@
|
||||
#
|
||||
# (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.
|
||||
#
|
||||
|
||||
from http import HTTPStatus
|
||||
from json import dumps
|
||||
from django.http import HttpResponse
|
||||
|
||||
class ErrorResponse(HttpResponse):
|
||||
def __init__(self, message: str, status: HTTPStatus):
|
||||
payload = {
|
||||
'error': message,
|
||||
'success': False
|
||||
}
|
||||
content = dumps(payload)
|
||||
super().__init__(
|
||||
content,
|
||||
content_type='application/json',
|
||||
status=status
|
||||
)
|
||||
@ -29,24 +29,26 @@ import magic
|
||||
from django.conf import settings
|
||||
from django.http import HttpResponse, HttpResponseRedirect, FileResponse
|
||||
from src.configuration import ConfigurationManager
|
||||
from src.format import FormatManager
|
||||
from . import fileUtils, historyManager
|
||||
|
||||
config_manager = ConfigurationManager()
|
||||
format_manager = FormatManager()
|
||||
|
||||
def isCanFillForms(ext):
|
||||
return ext in config_manager.fillable_file_extensions()
|
||||
return ext in format_manager.fillable_extensions()
|
||||
|
||||
# check if the file extension can be viewed
|
||||
def isCanView(ext):
|
||||
return ext in config_manager.viewable_file_extensions()
|
||||
return ext in format_manager.viewable_extensions()
|
||||
|
||||
# check if the file extension can be edited
|
||||
def isCanEdit(ext):
|
||||
return ext in config_manager.editable_file_extensions()
|
||||
return ext in format_manager.editable_extensions()
|
||||
|
||||
# check if the file extension can be converted
|
||||
def isCanConvert(ext):
|
||||
return ext in config_manager.convertible_file_extensions()
|
||||
return ext in format_manager.convertible_extensions()
|
||||
|
||||
# check if the file extension is supported by the editor (it can be viewed or edited or converted)
|
||||
def isSupportedExt(ext):
|
||||
@ -238,7 +240,7 @@ def createSample(fileType, sample, req):
|
||||
filename = getCorrectName(f'{sampleName}{ext}', req) # get file name with an index if such a file name already exists
|
||||
path = getStoragePath(filename, req)
|
||||
|
||||
with io.open(os.path.join('assets', 'sample' if sample == 'true' else 'new', f'{sampleName}{ext}'), 'rb') as stream: # create sample file of the necessary extension in the directory
|
||||
with io.open(os.path.join('assets', 'document-templates', 'sample' if sample == 'true' else 'new', f'{sampleName}{ext}'), 'rb') as stream: # create sample file of the necessary extension in the directory
|
||||
createFile(stream, path, req, True)
|
||||
return filename
|
||||
|
||||
|
||||
@ -17,8 +17,10 @@
|
||||
"""
|
||||
|
||||
from src.configuration import ConfigurationManager
|
||||
from src.format import FormatManager
|
||||
|
||||
config_manager = ConfigurationManager()
|
||||
format_manager = FormatManager()
|
||||
|
||||
# get file name from the document url
|
||||
def getFileName(str):
|
||||
@ -40,11 +42,11 @@ def getFileExt(str):
|
||||
# get file type
|
||||
def getFileType(str):
|
||||
ext = getFileExt(str)
|
||||
if ext in config_manager.document_file_extensions():
|
||||
if ext in format_manager.document_extensions():
|
||||
return 'word'
|
||||
if ext in config_manager.spreadsheet_file_extensions():
|
||||
if ext in format_manager.spreadsheet_extensions():
|
||||
return 'cell'
|
||||
if ext in config_manager.presentation_file_extensions():
|
||||
if ext in format_manager.presentation_extensions():
|
||||
return 'slide'
|
||||
|
||||
return 'word' # default file type is word
|
||||
@ -22,12 +22,9 @@ import json
|
||||
|
||||
from . import users, fileUtils
|
||||
from datetime import datetime
|
||||
from src.configuration import ConfigurationManager
|
||||
from src.utils import docManager
|
||||
from src.utils import jwtManager
|
||||
|
||||
config_manager = ConfigurationManager()
|
||||
|
||||
# get the path to the history direction
|
||||
def getHistoryDir(storagePath):
|
||||
return f'{storagePath}-hist'
|
||||
@ -227,5 +224,5 @@ class CorsHeaderMiddleware:
|
||||
def __call__(self, request):
|
||||
resp = self.get_response(request)
|
||||
if request.path == '/downloadhistory':
|
||||
resp['Access-Control-Allow-Origin'] = config_manager.document_server_url().geturl()
|
||||
return resp
|
||||
resp['Access-Control-Allow-Origin'] = '*'
|
||||
return resp
|
||||
|
||||
@ -16,14 +16,17 @@
|
||||
|
||||
"""
|
||||
|
||||
|
||||
import requests
|
||||
import os
|
||||
from copy import deepcopy
|
||||
import json
|
||||
import os
|
||||
from urllib.parse import urlparse
|
||||
import requests
|
||||
from src.configuration import ConfigurationManager
|
||||
from src.proxy import ProxyManager
|
||||
from . import jwtManager, docManager, historyManager, fileUtils, serviceConverter
|
||||
|
||||
config_manager = ConfigurationManager()
|
||||
proxy_manager = ProxyManager(config_manager=config_manager)
|
||||
|
||||
# read request body
|
||||
def readBody(request):
|
||||
@ -45,7 +48,9 @@ def readBody(request):
|
||||
return body
|
||||
|
||||
# file saving process
|
||||
def processSave(body, filename, usAddr):
|
||||
def processSave(raw_body, filename, usAddr):
|
||||
body = resolve_process_save_body(raw_body)
|
||||
|
||||
download = body.get('url')
|
||||
if (download is None):
|
||||
raise Exception("DownloadUrl is null")
|
||||
@ -176,3 +181,19 @@ def commandRequest(method, key, meta = None):
|
||||
|
||||
return
|
||||
|
||||
def resolve_process_save_body(body):
|
||||
copied = deepcopy(body)
|
||||
|
||||
url = copied.get('url')
|
||||
if url is not None:
|
||||
parsed_url = urlparse(url)
|
||||
resolved_url = proxy_manager.resolve_url(parsed_url)
|
||||
copied['url'] = resolved_url.geturl()
|
||||
|
||||
changes_url = copied.get('changesurl')
|
||||
if changes_url is not None:
|
||||
parsed_url = urlparse(changes_url)
|
||||
resolved_url = proxy_manager.resolve_url(parsed_url)
|
||||
copied['changesurl'] = resolved_url.geturl()
|
||||
|
||||
return copied
|
||||
|
||||
@ -16,7 +16,7 @@
|
||||
|
||||
"""
|
||||
|
||||
from urllib.parse import unquote
|
||||
from typing import Optional
|
||||
|
||||
class User:
|
||||
def __init__(self, id, name, email, group, reviewGroups, commentGroups, userInfoGroups, favorite, deniedPermissions, descriptions, templates):
|
||||
@ -125,3 +125,12 @@ def getUsersForMentions(uid):
|
||||
if(user.id != uid and user.name != None and user.email != None):
|
||||
usersData.append({'name':user.name, 'email':user.email})
|
||||
return usersData
|
||||
|
||||
def find_user(id: Optional[str]) -> User:
|
||||
if id is None:
|
||||
return DEFAULT_USER
|
||||
for user in USERS:
|
||||
if not user.id == id:
|
||||
continue
|
||||
return user
|
||||
return DEFAULT_USER
|
||||
|
||||
@ -15,19 +15,24 @@
|
||||
limitations under the License.
|
||||
|
||||
"""
|
||||
import requests
|
||||
|
||||
import json
|
||||
import os
|
||||
import urllib.parse
|
||||
|
||||
from datetime import datetime
|
||||
from django.http import HttpResponse, HttpResponseRedirect, FileResponse
|
||||
from http import HTTPStatus
|
||||
import json
|
||||
import os
|
||||
from pathlib import Path
|
||||
from shutil import copy
|
||||
from django.http import HttpRequest, HttpResponse, HttpResponseRedirect
|
||||
from django.shortcuts import render
|
||||
import requests
|
||||
from src.common import http
|
||||
from src.configuration import ConfigurationManager
|
||||
from src.format import FormatManager
|
||||
from src.response import ErrorResponse
|
||||
from src.utils import docManager, fileUtils, serviceConverter, users, jwtManager, historyManager, trackManager
|
||||
|
||||
config_manager = ConfigurationManager()
|
||||
format_manager = FormatManager()
|
||||
|
||||
# upload a file from the document storage service to the document editing service
|
||||
def upload(request):
|
||||
@ -393,7 +398,7 @@ def files(request):
|
||||
|
||||
# download a csv file
|
||||
def csv(request):
|
||||
filePath = os.path.join('assets', 'sample', "csv.csv")
|
||||
filePath = os.path.join('assets', 'document-templates', 'sample', "csv.csv")
|
||||
response = docManager.download(filePath)
|
||||
return response
|
||||
|
||||
@ -505,3 +510,66 @@ def reference(request):
|
||||
data['token'] = jwtManager.encode(data)
|
||||
|
||||
return HttpResponse(json.dumps(data), content_type='application/json')
|
||||
|
||||
@http.PUT()
|
||||
def restore(request: HttpRequest) -> HttpResponse:
|
||||
try:
|
||||
body = json.loads(request.body)
|
||||
source_basename: str = body['fileName']
|
||||
version: int = body['version']
|
||||
user_id: str = body.get('userId')
|
||||
source_extension = Path(source_basename).suffix
|
||||
|
||||
user = users.find_user(user_id)
|
||||
|
||||
source_file = docManager.getStoragePath(source_basename, request)
|
||||
history_directory = historyManager.getHistoryDir(source_file)
|
||||
|
||||
recovery_version_directory = historyManager.getVersionDir(history_directory, version)
|
||||
recovery_file = historyManager.getPrevFilePath(recovery_version_directory, source_extension)
|
||||
|
||||
bumped_version_directory = historyManager.getNextVersionDir(history_directory)
|
||||
bumped_key = docManager.generateFileKey(source_basename, request)
|
||||
bumped_key_file = historyManager.getKeyPath(bumped_version_directory)
|
||||
bumped_changes_file = historyManager.getChangesHistoryPath(bumped_version_directory)
|
||||
bumped_changes = {
|
||||
'serverVersion': None,
|
||||
'changes': [
|
||||
{
|
||||
'created': datetime.today().strftime('%Y-%m-%d %H:%M:%S'),
|
||||
'user': {
|
||||
'id': user.id,
|
||||
'name': user.name
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
bumped_changes_content = json.dumps(bumped_changes)
|
||||
bumped_file = historyManager.getPrevFilePath(bumped_version_directory, source_extension)
|
||||
|
||||
Path(bumped_key_file).write_text(bumped_key, 'utf-8')
|
||||
Path(bumped_changes_file).write_text(bumped_changes_content, 'utf-8')
|
||||
copy(source_file, bumped_file)
|
||||
copy(recovery_file, source_file)
|
||||
|
||||
return HttpResponse()
|
||||
except Exception as error:
|
||||
return ErrorResponse(
|
||||
message=f'{type(error)}: {error}',
|
||||
status=HTTPStatus.INTERNAL_SERVER_ERROR
|
||||
)
|
||||
|
||||
@http.POST()
|
||||
def formats_convertible(request: HttpRequest) -> HttpResponse:
|
||||
try:
|
||||
body = json.loads(request.body)
|
||||
source_basename: str = body['fileName']
|
||||
source_extension = Path(source_basename).suffix
|
||||
names = format_manager.convertible_to_names(source_extension)
|
||||
content = json.dumps(names)
|
||||
return HttpResponse(content)
|
||||
except Exception as error:
|
||||
return ErrorResponse(
|
||||
message=f'{type(error)}: {error}',
|
||||
status=HTTPStatus.INTERNAL_SERVER_ERROR
|
||||
)
|
||||
|
||||
@ -23,10 +23,12 @@ import json
|
||||
from django.shortcuts import render
|
||||
|
||||
from src.configuration import ConfigurationManager
|
||||
from src.format import FormatManager
|
||||
from src.utils import users
|
||||
from src.utils import docManager
|
||||
|
||||
config_manager = ConfigurationManager()
|
||||
format_manager = FormatManager()
|
||||
|
||||
def getDirectUrlParam(request):
|
||||
if ('directUrl' in request.GET):
|
||||
@ -39,10 +41,10 @@ def default(request): # default parameters that will be passed to the template
|
||||
'users': users.USERS,
|
||||
'languages': config_manager.languages(),
|
||||
'preloadurl': config_manager.document_server_preloader_url().geturl(),
|
||||
'editExt': json.dumps(config_manager.editable_file_extensions()), # file extensions that can be edited
|
||||
'convExt': json.dumps(config_manager.convertible_file_extensions()), # file extensions that can be converted
|
||||
'editExt': json.dumps(format_manager.editable_extensions()), # file extensions that can be edited
|
||||
'convExt': json.dumps(format_manager.convertible_extensions()), # file extensions that can be converted
|
||||
'files': docManager.getStoredFiles(request), # information about stored files
|
||||
'fillExt': json.dumps(config_manager.fillable_file_extensions()),
|
||||
'fillExt': json.dumps(format_manager.fillable_extensions()),
|
||||
'directUrl': str(getDirectUrlParam(request)).lower
|
||||
}
|
||||
return render(request, 'index.html', context) # execute the "index.html" template with context data and return http response in json format
|
||||
@ -0,0 +1,326 @@
|
||||
.conversion {
|
||||
/* ui container */
|
||||
/* padding: 32px 48px; */
|
||||
|
||||
display: none;
|
||||
padding: 26px 35px;
|
||||
}
|
||||
|
||||
@media (max-width: 593px) {
|
||||
.conversion {
|
||||
padding: 24px 16px;
|
||||
}
|
||||
}
|
||||
|
||||
.converting > :first-child {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.conversion-file {
|
||||
column-gap: 8px;
|
||||
display: grid;
|
||||
grid-template-columns: min-content 1fr;
|
||||
}
|
||||
|
||||
.conversion-file__basename {
|
||||
color: #333333;
|
||||
font-size: 14px;
|
||||
grid-column: 2;
|
||||
grid-row: 1;
|
||||
line-height: 1.5;
|
||||
padding-top: 1.5px;
|
||||
}
|
||||
|
||||
.conversion-file__type {
|
||||
grid-column: 1;
|
||||
grid-row: 1;
|
||||
}
|
||||
|
||||
.conversion-steps {
|
||||
list-style-type: none;
|
||||
margin: 16px 0 0 0;
|
||||
padding-inline-start: 0;
|
||||
}
|
||||
|
||||
.conversion-steps__step {
|
||||
column-gap: 8px;
|
||||
display: grid;
|
||||
grid-template-columns: min-content 1fr;
|
||||
}
|
||||
|
||||
.conversion-steps__step:not(:first-of-type) {
|
||||
margin-top: 16px;
|
||||
}
|
||||
|
||||
.conversion-steps__step_skipped {
|
||||
opacity: 30%;
|
||||
}
|
||||
|
||||
.conversion-steps__title {
|
||||
color: #333333;
|
||||
font-size: 12px;
|
||||
font-weight: 700;
|
||||
grid-column: 2;
|
||||
grid-row: 1;
|
||||
line-height: 1.5;
|
||||
margin: 0;
|
||||
padding-top: 3px;
|
||||
}
|
||||
|
||||
.conversion-steps__status {
|
||||
grid-column: 1;
|
||||
grid-row: 1;
|
||||
}
|
||||
|
||||
.conversion-steps__contents {
|
||||
grid-column: 2;
|
||||
grid-row: 2;
|
||||
}
|
||||
|
||||
.conversion-steps__step_failed .conversion-steps__contents {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.conversion-steps__step_skipped .conversion-steps__contents {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.conversion-steps__description {
|
||||
color: #333333;
|
||||
font-size: 11px;
|
||||
line-height: 1.5;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.conversion-options {
|
||||
border: none;
|
||||
display: grid;
|
||||
gap: 8px;
|
||||
grid-template-columns: repeat(6, 1fr);
|
||||
margin: 16px 0 0 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
@media (max-width: 593px) {
|
||||
.conversion-options {
|
||||
grid-template-columns: repeat(4, 1fr);
|
||||
}
|
||||
}
|
||||
|
||||
.conversion-options__option {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.conversion-options__control {
|
||||
border-radius: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
margin: 0;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0;
|
||||
z-index: -1;
|
||||
}
|
||||
|
||||
.conversion-options__indicator {
|
||||
background-color: #EFEFEF;
|
||||
border-radius: 2px;
|
||||
color: #333333;
|
||||
cursor: pointer;
|
||||
display: block;
|
||||
font-size: 11px;
|
||||
font-weight: 600;
|
||||
line-height: 1;
|
||||
padding: 10.5px 10px;
|
||||
text-align: center;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.conversion-options__control:not(:disabled):not(:checked):not(:required) +
|
||||
.conversion-options__indicator:focus-visible,
|
||||
.conversion-options__control:not(:disabled):not(:checked):not(:required) +
|
||||
.conversion-options__indicator:hover {
|
||||
background-color: #FF6F3D;
|
||||
color: #FFFFFF;
|
||||
}
|
||||
|
||||
.conversion-options__control:disabled +
|
||||
.conversion-options__indicator {
|
||||
background-color: #EFEFEF;
|
||||
color: #333333;
|
||||
cursor: default;
|
||||
opacity: 30%;
|
||||
}
|
||||
|
||||
.conversion-options__control:checked +
|
||||
.conversion-options__indicator {
|
||||
background-color: #FF6F3D;
|
||||
color: #FFFFFF;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.conversion-options__control:required +
|
||||
.conversion-options__indicator {
|
||||
background-color: #444444;
|
||||
color: #FFFFFF;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.conversion-progress {
|
||||
color: #333333;
|
||||
font-size: 11px;
|
||||
line-height: 1.5;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.conversion-progress__indicator {
|
||||
color: #FF6F3D;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.conversion-note {
|
||||
color: #333333;
|
||||
font-size: 12px;
|
||||
line-height: 1.5;
|
||||
margin: 16px 0 0 0;
|
||||
}
|
||||
|
||||
.conversion-error {
|
||||
column-gap: 8px;
|
||||
display: grid;
|
||||
grid-template-columns: min-content 1fr;
|
||||
margin-top: 16px;
|
||||
}
|
||||
|
||||
.conversion-error__message {
|
||||
color: #CB0000;
|
||||
font-size: 12px;
|
||||
grid-column: 2;
|
||||
grid-row: 1;
|
||||
line-height: 1.5;
|
||||
margin: 0;
|
||||
padding-top: 3px;
|
||||
}
|
||||
|
||||
.conversion-error__type {
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.conversion-error__icon {
|
||||
grid-column: 1;
|
||||
grid-row: 1;
|
||||
}
|
||||
|
||||
.conversion-actions {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
margin-top: 16px;
|
||||
}
|
||||
|
||||
@media (max-width: 593px) {
|
||||
.conversion-actions {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
}
|
||||
}
|
||||
|
||||
.conversion-actions__action {
|
||||
/* Override */
|
||||
/* .ui-widget button */
|
||||
/* .ui-widget-content a */
|
||||
|
||||
border-radius: 3px;
|
||||
border: 1px solid;
|
||||
color: inherit !important;
|
||||
cursor: pointer;
|
||||
display: inline-block;
|
||||
font-family: inherit !important;
|
||||
font-size: 12px !important;
|
||||
line-height: 1;
|
||||
padding: 16px 24px;
|
||||
text-align: center;
|
||||
text-decoration: none;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.conversion-actions__action[disabled] {
|
||||
cursor: default;
|
||||
opacity: 30%;
|
||||
}
|
||||
|
||||
.conversion-actions__action_style_neutral {
|
||||
background-color: #FFFFFF;
|
||||
border-color: #808080;
|
||||
color: #444444 !important;
|
||||
}
|
||||
|
||||
.conversion-actions__action_style_neutral:focus-visible,
|
||||
.conversion-actions__action_style_neutral:hover {
|
||||
border-color: #FF6F3D;
|
||||
color: #FF6F3D !important;
|
||||
}
|
||||
|
||||
.conversion-actions__action_style_neutral[disabled]:focus-visible,
|
||||
.conversion-actions__action_style_neutral[disabled]:hover {
|
||||
border-color: #808080;
|
||||
color: #444444 !important;
|
||||
}
|
||||
|
||||
.conversion-actions__action_style_accent {
|
||||
background-color: #FF6F3D;
|
||||
border-color: #FF6F3D;
|
||||
color: #FFFFFF !important;
|
||||
}
|
||||
|
||||
.conversion-loading {
|
||||
animation: conversion-loading 2.5s linear infinite;
|
||||
height: 24px;
|
||||
width: 24px;
|
||||
}
|
||||
|
||||
@keyframes conversion-loading {
|
||||
100% {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
.conversion-steps__step .conversion-loading {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.conversion-steps__step_loading .conversion-loading {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.conversion-succeeded {
|
||||
fill: #8BB825;
|
||||
height: 24px;
|
||||
width: 24px;
|
||||
}
|
||||
|
||||
.conversion-steps__step .conversion-succeeded {
|
||||
fill: #444444;
|
||||
opacity: 30%;
|
||||
}
|
||||
|
||||
.conversion-steps__step_loading .conversion-succeeded {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.conversion-steps__step_succeeded .conversion-succeeded {
|
||||
fill: #8BB825;
|
||||
opacity: 100%;
|
||||
}
|
||||
|
||||
.conversion-steps__step_skipped .conversion-succeeded {
|
||||
fill: #444444;
|
||||
opacity: 100%;
|
||||
}
|
||||
|
||||
.conversion-failed {
|
||||
/* viewBox="0 0 16 16" */
|
||||
fill: #CB0000;
|
||||
height: 16px;
|
||||
padding: 4px;
|
||||
width: 16px;
|
||||
}
|
||||
@ -0,0 +1,889 @@
|
||||
//
|
||||
// (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.
|
||||
//
|
||||
|
||||
// @ts-check
|
||||
// https://github.com/microsoft/TypeScript/issues/13206
|
||||
// https://github.com/microsoft/TypeScript/issues/38985
|
||||
|
||||
// click on button
|
||||
// show popup
|
||||
// loading on select step
|
||||
// fetch formats
|
||||
// show select step
|
||||
|
||||
// mount
|
||||
// unmount <- removeEventListener
|
||||
|
||||
;(function () {
|
||||
"use strict"
|
||||
|
||||
/**
|
||||
* @class
|
||||
*/
|
||||
function Conversion() {
|
||||
/** @type {Element | null} */
|
||||
this.element = null
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Element} root
|
||||
*/
|
||||
Conversion.prototype.connectedCallback = function connectedCallback(root) {
|
||||
this.element = root.querySelector(".conversion")
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
Conversion.prototype.mount = function mount() {
|
||||
var parameters = {
|
||||
fileName: "document.docx",
|
||||
conversionTimeout: 1000
|
||||
}
|
||||
|
||||
this.selectStep.start()
|
||||
|
||||
var formatsParameters = {
|
||||
fileName: parameters.fileName
|
||||
}
|
||||
this.fetchFormats(formatsParameters, function (error, formats) {
|
||||
if (error) {
|
||||
this.selectStep.fail()
|
||||
this.fault.show(error)
|
||||
return
|
||||
}
|
||||
|
||||
this.selectStep.abort()
|
||||
|
||||
this.options.setup(formats)
|
||||
// this!!!!!!!
|
||||
this.options.onSelect = function onSelect(error, format) {}
|
||||
|
||||
this.addOptionsClick(options, function (error, format) {
|
||||
if (error) {
|
||||
this.selectStep.fail()
|
||||
this.fault.show(error)
|
||||
return
|
||||
}
|
||||
|
||||
this.selectStep.success()
|
||||
this.conversionStep.start()
|
||||
|
||||
var conversionParameters = {
|
||||
timeout: parameters.conversionTimeout
|
||||
}
|
||||
this.fetchConversion(conversionParameters, function (error, data, cancel) {
|
||||
if (error) {
|
||||
cancel()
|
||||
this.conversionStep.fail()
|
||||
this.fault.show(error)
|
||||
return
|
||||
}
|
||||
|
||||
this.progress.setup(data.percent)
|
||||
|
||||
if (data.percent !== 100) {
|
||||
return
|
||||
}
|
||||
|
||||
cancel()
|
||||
|
||||
if (!data.fileUrl) {
|
||||
this.conversionStep.fail()
|
||||
this.fault.show(new ConversionError2())
|
||||
return
|
||||
}
|
||||
|
||||
this.conversionStep.success()
|
||||
|
||||
this.actions.setupDownload(data.fileUrl)
|
||||
this.actions.enable()
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @callback ConversionOptionsOnSelect
|
||||
* @param {ConversionOptions} this
|
||||
* @param {string} format
|
||||
* @returns {void}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @class
|
||||
*/
|
||||
function ConversionOptions() {
|
||||
/** @type {Element | null} */
|
||||
this.element = null
|
||||
|
||||
/** @type {ConversionOptionsOnSelect | undefined} */
|
||||
this.onSelect = undefined
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Element} root
|
||||
*/
|
||||
ConversionOptions.prototype.connectedCallback = function connectedCallback(root) {
|
||||
var element = root.querySelector(".conversion-options")
|
||||
if (!element) {
|
||||
return
|
||||
}
|
||||
|
||||
element.addEventListener("click", this.handleSelect.bind(this))
|
||||
this.element = element
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string[]} values
|
||||
*/
|
||||
ConversionOptions.prototype.setValues = function setValues(values) {
|
||||
var element = this.element
|
||||
if (!element) {
|
||||
return
|
||||
}
|
||||
|
||||
for (var index = 0; index < values.length; index += 1) {
|
||||
var value = values[index]
|
||||
var option = ConversionOptions.createOption(value)
|
||||
element.appendChild(option)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} value
|
||||
* @returns {Element}
|
||||
*/
|
||||
ConversionOptions.createOption = function createOption(value) {
|
||||
var control = this.createControl(value)
|
||||
var indicator = this.createIndicator(value)
|
||||
var option = document.createElement("label")
|
||||
option.setAttribute("class", "conversion-options__option")
|
||||
option.appendChild(control)
|
||||
option.appendChild(indicator)
|
||||
return option
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} value
|
||||
* @returns {Element}
|
||||
*/
|
||||
ConversionOptions.createControl = function createControl(value) {
|
||||
var control = document.createElement("input")
|
||||
control.setAttribute("class", "conversion-options__control")
|
||||
control.setAttribute("type", "radio")
|
||||
control.setAttribute("name", "format")
|
||||
control.setAttribute("value", value)
|
||||
return control
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Element} element
|
||||
* @returns {boolean}
|
||||
*/
|
||||
ConversionOptions.isIndicator = function isIndicator(element) {
|
||||
var classes = element.getAttribute("class")
|
||||
return (
|
||||
!!classes &&
|
||||
classes.indexOf("conversion-options__indicator") !== -1
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} value
|
||||
* @returns {Element}
|
||||
*/
|
||||
ConversionOptions.createIndicator = function createIndicator(value) {
|
||||
var indicator = document.createElement("span")
|
||||
indicator.setAttribute("class", "conversion-options__indicator")
|
||||
indicator.textContent = value
|
||||
return indicator
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {MouseEvent} event
|
||||
*/
|
||||
ConversionOptions.prototype.handleSelect = function handleSelect(event) {
|
||||
event.preventDefault()
|
||||
|
||||
var element = this.element
|
||||
if (!element) {
|
||||
return
|
||||
}
|
||||
|
||||
if (
|
||||
!event.target ||
|
||||
!(event.target instanceof Element) ||
|
||||
!ConversionOptions.isIndicator(event.target)
|
||||
) {
|
||||
return
|
||||
}
|
||||
|
||||
var control = event.target.previousSibling
|
||||
if (
|
||||
!control ||
|
||||
!(control instanceof Element) ||
|
||||
!control.hasAttribute("checked") ||
|
||||
control.hasAttribute("required")
|
||||
) {
|
||||
return
|
||||
}
|
||||
|
||||
var controls = element.querySelectorAll(".conversion-options__control")
|
||||
for (var index = 0; index < controls.length; index += 1) {
|
||||
var sub = controls[index]
|
||||
if (sub.hasAttribute("checked")) {
|
||||
continue
|
||||
}
|
||||
sub.setAttribute("disabled", "")
|
||||
}
|
||||
|
||||
control.setAttribute("required", "")
|
||||
|
||||
var onSelect = this.onSelect
|
||||
if (!onSelect) {
|
||||
return
|
||||
}
|
||||
|
||||
var format = control.getAttribute("value")
|
||||
if (!format) {
|
||||
return
|
||||
}
|
||||
|
||||
// @ts-ignore
|
||||
onSelect(format)
|
||||
}
|
||||
|
||||
/**
|
||||
* @class
|
||||
*/
|
||||
function ConversionProgress() {
|
||||
/** @type {Element | null} */
|
||||
this.element = null
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Element} root
|
||||
*/
|
||||
ConversionProgress.prototype.connectedCallback = function connectedCallback(root) {
|
||||
this.element = root.querySelector(".conversion-progress")
|
||||
}
|
||||
|
||||
ConversionProgress.prototype.reset = function reset() {
|
||||
this.setValue(0)
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {number} value
|
||||
*/
|
||||
ConversionProgress.prototype.setValue = function setValue(value) {
|
||||
var element = this.element
|
||||
if (!element) {
|
||||
return
|
||||
}
|
||||
|
||||
var bar = element.querySelector("progress")
|
||||
if (!bar) {
|
||||
return
|
||||
}
|
||||
|
||||
var indicator = element.querySelector(".conversion-progress__indicator")
|
||||
if (!indicator) {
|
||||
return
|
||||
}
|
||||
|
||||
bar.setAttribute("value", String(value))
|
||||
bar.textContent = value + "%"
|
||||
indicator.textContent = value + "%"
|
||||
}
|
||||
|
||||
/**
|
||||
* @class
|
||||
*/
|
||||
function ConversionError() {
|
||||
/** @type {Element | null} */
|
||||
this.element = null
|
||||
}
|
||||
|
||||
ConversionError.prototype.connectedCallback = function connectedCallback(root) {
|
||||
this.element = root.querySelector(".conversion-error")
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Error} error
|
||||
*/
|
||||
ConversionError.prototype.show = function show(error) {
|
||||
var element = this.element
|
||||
if (!element) {
|
||||
return
|
||||
}
|
||||
|
||||
var type = element.querySelector(".conversion-error__type")
|
||||
if (!type) {
|
||||
return
|
||||
}
|
||||
|
||||
var body = type.nextSibling
|
||||
if (!body) {
|
||||
return
|
||||
}
|
||||
|
||||
type.textContent = error.name
|
||||
body.textContent = error.message
|
||||
element.removeAttribute("hidden")
|
||||
}
|
||||
|
||||
ConversionError.prototype.hide = function hide() {
|
||||
var element = this.element
|
||||
if (!element) {
|
||||
return
|
||||
}
|
||||
|
||||
var type = element.querySelector(".conversion-error__type")
|
||||
if (!type) {
|
||||
return
|
||||
}
|
||||
|
||||
var body = type.nextSibling
|
||||
if (!body) {
|
||||
return
|
||||
}
|
||||
|
||||
type.textContent = null
|
||||
body.textContent = null
|
||||
element.setAttribute("hidden", "")
|
||||
}
|
||||
|
||||
/**
|
||||
* @class
|
||||
*/
|
||||
function ConversionActions() {
|
||||
/** @type {Element | null} */
|
||||
this.element = null
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Element} root
|
||||
*/
|
||||
ConversionActions.prototype.connectedCallback = function connectedCallback(root) {
|
||||
this.element = root.querySelector(".conversion-actions")
|
||||
}
|
||||
|
||||
ConversionActions.prototype.enable = function enable() {
|
||||
this.enableNth(1)
|
||||
this.enableNth(2)
|
||||
this.enableNth(3)
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {number} nth
|
||||
*/
|
||||
ConversionActions.prototype.enableNth = function enableNth(nth) {
|
||||
var element = this.element
|
||||
if (!element) {
|
||||
return
|
||||
}
|
||||
|
||||
var action = element.querySelector(
|
||||
".conversion-actions__action:nth-of-type(" + String(nth) + ")"
|
||||
)
|
||||
if (!action) {
|
||||
return
|
||||
}
|
||||
|
||||
action.removeAttribute("disabled")
|
||||
}
|
||||
|
||||
ConversionActions.prototype.disable = function disable() {
|
||||
this.disableNth(1)
|
||||
this.disableNth(2)
|
||||
this.disableNth(3)
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {number} nth
|
||||
*/
|
||||
ConversionActions.prototype.disableNth = function disableNth(nth) {
|
||||
var element = this.element
|
||||
if (!element) {
|
||||
return
|
||||
}
|
||||
|
||||
var action = element.querySelector(
|
||||
".conversion-actions__action:nth-of-type(" + String(nth) + ")"
|
||||
)
|
||||
if (!action) {
|
||||
return
|
||||
}
|
||||
|
||||
action.setAttribute("disabled", "")
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} url
|
||||
*/
|
||||
ConversionActions.prototype.setDownload = function setDownload(url) {
|
||||
this.setNth(1, url)
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} url
|
||||
*/
|
||||
ConversionActions.prototype.setView = function setView(url) {
|
||||
this.setNth(2, url)
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} url
|
||||
*/
|
||||
ConversionActions.prototype.setEdit = function setEdit(url) {
|
||||
this.setNth(3, url)
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {number} nth
|
||||
* @param {string} url
|
||||
*/
|
||||
ConversionActions.prototype.setNth = function setNth(nth, url) {
|
||||
var element = this.element
|
||||
if (!element) {
|
||||
return
|
||||
}
|
||||
|
||||
var action = element.querySelector(
|
||||
".conversion-actions__action:nth-of-type(" + String(nth) + "1)"
|
||||
)
|
||||
if (!action) {
|
||||
return
|
||||
}
|
||||
|
||||
action.setAttribute("href", url)
|
||||
}
|
||||
|
||||
ConversionActions.prototype.unsetDownload = function unsetDownload() {
|
||||
this.unsetNth(1)
|
||||
}
|
||||
|
||||
ConversionActions.prototype.unsetView = function unsetView() {
|
||||
this.unsetNth(2)
|
||||
}
|
||||
|
||||
ConversionActions.prototype.unsetEdit = function unsetEdit() {
|
||||
this.unsetNth(3)
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {number} nth
|
||||
*/
|
||||
ConversionActions.prototype.unsetNth = function unsetNth(nth) {
|
||||
var element = this.element
|
||||
if (!element) {
|
||||
return
|
||||
}
|
||||
|
||||
var action = element.querySelector(
|
||||
".conversion-actions__action:nth-of-type(" + String(nth) + "1)"
|
||||
)
|
||||
if (!action) {
|
||||
return
|
||||
}
|
||||
|
||||
action.removeAttribute("href")
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @class
|
||||
*/
|
||||
function ConversionStep() {
|
||||
/** @type {Element | null} */
|
||||
this.element = null
|
||||
}
|
||||
|
||||
ConversionStep.prototype.start = function start() {
|
||||
var element = this.element
|
||||
if (!element) {
|
||||
return
|
||||
}
|
||||
|
||||
element.setAttribute(
|
||||
"class",
|
||||
"conversion-steps__step conversion-steps__step_loading"
|
||||
)
|
||||
}
|
||||
|
||||
ConversionStep.prototype.fail = function fail() {
|
||||
var element = this.element
|
||||
if (!element) {
|
||||
return
|
||||
}
|
||||
|
||||
element.setAttribute(
|
||||
"class",
|
||||
"conversion-steps__step conversion-steps__step_failed"
|
||||
)
|
||||
}
|
||||
|
||||
ConversionStep.prototype.abort = function abort() {
|
||||
var element = this.element
|
||||
if (!element) {
|
||||
return
|
||||
}
|
||||
|
||||
element.setAttribute(
|
||||
"class",
|
||||
"conversion-steps__step"
|
||||
)
|
||||
}
|
||||
|
||||
ConversionStep.prototype.success = function success() {
|
||||
var element = this.element
|
||||
if (!element) {
|
||||
return
|
||||
}
|
||||
|
||||
element.setAttribute(
|
||||
"class",
|
||||
"conversion-steps__step conversion-steps__step_succeeded"
|
||||
)
|
||||
}
|
||||
|
||||
ConversionStep.prototype.skip = function skip() {
|
||||
var element = this.element
|
||||
if (!element) {
|
||||
return
|
||||
}
|
||||
|
||||
element.setAttribute(
|
||||
"class",
|
||||
"conversion-steps__step conversion-steps__step_skipped"
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// Select Step
|
||||
|
||||
/**
|
||||
* @class
|
||||
* @extends ConversionStep
|
||||
* @param {Element} root
|
||||
*/
|
||||
function ConversionSelectStep(root) {
|
||||
var element = ConversionSelectStep.queryStep(root)
|
||||
ConversionSelectStep.call(this, element)
|
||||
}
|
||||
|
||||
ConversionSelectStep.prototype = Object.create(ConversionStep.prototype)
|
||||
ConversionSelectStep.prototype.constructor = ConversionSelectStep
|
||||
|
||||
/**
|
||||
* @param {Element} root
|
||||
* @returns {Element}
|
||||
*/
|
||||
ConversionSelectStep.queryStep = function queryStep(root) {
|
||||
var step = root.querySelector(".conversion-steps__step:nth-of-type(1)")
|
||||
if (!step) {
|
||||
throw new ConversionError2()
|
||||
}
|
||||
return step
|
||||
}
|
||||
|
||||
// Conversion Step
|
||||
|
||||
/**
|
||||
* @class
|
||||
* @extends ConversionStep
|
||||
* @param {Element} root
|
||||
*/
|
||||
function ConversionConversionStep(root) {
|
||||
var element = ConversionConversionStep.queryStep(root)
|
||||
ConversionSelectStep.call(this, element)
|
||||
}
|
||||
|
||||
ConversionSelectStep.prototype = Object.create(ConversionStep.prototype)
|
||||
ConversionSelectStep.prototype.constructor = ConversionSelectStep
|
||||
|
||||
/**
|
||||
* @param {Element} root
|
||||
* @returns {Element}
|
||||
*/
|
||||
ConversionConversionStep.queryStep = function queryStep(root) {
|
||||
var step = root.querySelector(".conversion-steps__step:nth-of-type(2)")
|
||||
if (!step) {
|
||||
throw new ConversionError2()
|
||||
}
|
||||
return step
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @typedef {Object} ConversionFetchFormatsParameters
|
||||
* @property {string} fileName
|
||||
*/
|
||||
|
||||
/**
|
||||
* @callback ConversionFetchFormatsCallback
|
||||
* @param {Conversion} this
|
||||
* @param {ConversionError2 | undefined} error
|
||||
* @param {string[]} formats
|
||||
*/
|
||||
|
||||
/**
|
||||
* @param {ConversionFetchFormatsParameters} parameters
|
||||
* @param {ConversionFetchFormatsCallback} callback
|
||||
*/
|
||||
Conversion.prototype.fetchFormats = function fetchFormats(parameters, callback) {
|
||||
// var payload = JSON.stringify(parameters)
|
||||
// var request = new XMLHttpRequest()
|
||||
// request.open("POST", "formats-convertible")
|
||||
// request.send(payload)
|
||||
// request.onload = function () {
|
||||
// /**
|
||||
// * @type {string[] | { error: string }}
|
||||
// */
|
||||
// var response = JSON.parse(this.response)
|
||||
|
||||
// if (this.status != 200) {
|
||||
// var error = Array.isArray(response)
|
||||
// ? "Unknown error. Please, contact the administrator."
|
||||
// : response.error
|
||||
// callback(undefined, error)
|
||||
// return
|
||||
// }
|
||||
|
||||
// if (!Array.isArray(response)) {
|
||||
// callback(undefined, response.error)
|
||||
// return
|
||||
// }
|
||||
|
||||
// callback(response, undefined)
|
||||
// }
|
||||
|
||||
setTimeout(
|
||||
(function () {
|
||||
callback.call(this, undefined, [
|
||||
"pdf", "pdfа", "docxf",
|
||||
"docx", "jpg", "png",
|
||||
"txt", "bmp", "rtf",
|
||||
"ebub", "fb2", "html",
|
||||
"docm", "dotm", "odt",
|
||||
"ott", "dotx"
|
||||
])
|
||||
}).bind(this),
|
||||
5000
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* @typedef {Object} ConversionFetchConversionParameters
|
||||
* @property {number} timeout
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} ConversionFetchConversionCallbackData
|
||||
* @property {number} percent
|
||||
* @property {string | undefined} fileUrl
|
||||
*/
|
||||
|
||||
/**
|
||||
* @callback ConversionFetchConversionCallback
|
||||
* @param {Conversion} this
|
||||
* @param {ConversionError2 | undefined} error
|
||||
* @param {ConversionFetchConversionCallbackData} data
|
||||
* @param {() => void} cancel
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} ConversionFormatsConvertibleResponse
|
||||
* @property {string=} error
|
||||
* @property {number} percent
|
||||
* @property {string | undefined} fileUrl
|
||||
*/
|
||||
|
||||
/**
|
||||
* @param {ConversionFetchConversionParameters} parameters
|
||||
* @param {ConversionFetchConversionCallback} callback
|
||||
*/
|
||||
Conversion.prototype.fetchConversion = function fetchConversion(parameters, callback) {
|
||||
/**
|
||||
* @type {number | undefined}
|
||||
*/
|
||||
var timer
|
||||
|
||||
function cancel() {
|
||||
clearTimeout(timer)
|
||||
}
|
||||
|
||||
/**
|
||||
* @this Conversion
|
||||
*/
|
||||
function handler() {
|
||||
// var payload = JSON.stringify(parameters)
|
||||
var request = new XMLHttpRequest()
|
||||
request.open("POST", "formats-convertible")
|
||||
request.send(payload)
|
||||
|
||||
/**
|
||||
* @this Conversion
|
||||
*/
|
||||
function onLoad() {
|
||||
/**
|
||||
* @type {ConversionFormatsConvertibleResponse}
|
||||
*/
|
||||
var response = JSON.parse(request.response)
|
||||
if (response.error) {
|
||||
callback.call(this, new ConversionError2(), undefined, cancel)
|
||||
return
|
||||
}
|
||||
|
||||
/**
|
||||
* @type {ConversionFetchConversionCallbackData}
|
||||
*/
|
||||
var data = {
|
||||
percent: response.percent,
|
||||
fileUrl: response.fileUrl
|
||||
}
|
||||
callback.call(this, undefined, data, cancel)
|
||||
}
|
||||
|
||||
request.onload = onLoad.bind(this)
|
||||
}
|
||||
|
||||
setTimeout(handler.bind(this), parameters.timeout)
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// Error
|
||||
|
||||
/**
|
||||
* @class {Error}
|
||||
* @extends Error
|
||||
* @param {string} message
|
||||
*/
|
||||
function ConversionError2(message) {
|
||||
Error.call(this, message)
|
||||
this.name = "ConversionError2"
|
||||
}
|
||||
|
||||
ConversionError2.prototype = Object.create(Error.prototype)
|
||||
ConversionError2.prototype.constructor = ConversionError2
|
||||
|
||||
})()
|
||||
@ -765,4 +765,4 @@ html {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
}
|
||||
|
||||
@ -16,6 +16,35 @@
|
||||
*
|
||||
*/
|
||||
|
||||
function convertingConstruct() {
|
||||
var button = document.querySelector("#MYBUTTON");
|
||||
if (!button) {
|
||||
return;
|
||||
}
|
||||
|
||||
button.addEventListener("click", convertingClick);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {MouseEvent} event
|
||||
*/
|
||||
function convertingClick(event) {
|
||||
jq.blockUI({
|
||||
theme: true,
|
||||
title: "File Conversion" + "<div class=\"dialog-close\"></div>",
|
||||
message: jq(".conversion"),
|
||||
overlayCSS: {
|
||||
"background-color": "#aaa"
|
||||
},
|
||||
themedCSS: {
|
||||
width: "539px",
|
||||
top: "20%",
|
||||
left: "50%",
|
||||
marginLeft: "-269px"
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
var directUrl;
|
||||
|
||||
if (typeof jQuery !== "undefined") {
|
||||
@ -365,4 +394,6 @@ if (typeof jQuery !== "undefined") {
|
||||
}).mouseout(function () {
|
||||
jq("div.tooltip").remove();
|
||||
});
|
||||
}
|
||||
|
||||
convertingConstruct();
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user