mirror of
https://github.com/ONLYOFFICE/document-server-integration.git
synced 2026-04-07 14:06:11 +08:00
Compare commits
69 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 |
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
|
||||
|
||||
@ -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")
|
||||
{
|
||||
|
||||
@ -1,22 +1,80 @@
|
||||
.DEFAULT_GOAL := help
|
||||
|
||||
ADDRESS := $(ADDRESS)
|
||||
PORT := $(PORT)
|
||||
|
||||
.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) | \
|
||||
awk 'BEGIN {FS = ": # "}; {printf "%s: %s\n", $$1, $$2}'
|
||||
|
||||
.PHONY: dev
|
||||
dev: # Install development dependencies.
|
||||
dev: # Install development dependencies.
|
||||
@composer install
|
||||
|
||||
.PHONY: prod
|
||||
prod: # Install production dependencies.
|
||||
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.
|
||||
lint: # Lint the source code for the style.
|
||||
@./vendor/bin/phpcs .
|
||||
|
||||
.PHONY: test
|
||||
test: # Run tests recursively.
|
||||
@./vendor/bin/phpunit ./**/*Tests.php
|
||||
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
|
||||
|
||||
@ -19,6 +19,7 @@ namespace OnlineEditorsExamplePhp;
|
||||
|
||||
use Exception;
|
||||
use OnlineEditorsExamplePhp\Common\Path;
|
||||
use OnlineEditorsExamplePhp\Configuration\ConfigurationManager;
|
||||
use OnlineEditorsExamplePhp\Helpers\ConfigManager;
|
||||
use OnlineEditorsExamplePhp\Helpers\ExampleUsers;
|
||||
use OnlineEditorsExamplePhp\Helpers\JwtManager;
|
||||
@ -48,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...
|
||||
*
|
||||
@ -91,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"];
|
||||
@ -107,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;
|
||||
}
|
||||
@ -134,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']);
|
||||
@ -155,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;
|
||||
}
|
||||
@ -204,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"];
|
||||
@ -257,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);
|
||||
@ -392,6 +368,8 @@ function csv()
|
||||
function historyDownload()
|
||||
{
|
||||
try {
|
||||
$config_manager = new ConfigurationManager();
|
||||
|
||||
$fileName = basename($_GET["fileName"]); // get the file name
|
||||
$userAddress = $_GET["userAddress"];
|
||||
|
||||
@ -401,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],
|
||||
@ -439,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],
|
||||
@ -627,7 +602,7 @@ function restore()
|
||||
}
|
||||
$bumped_version_directory = new Path($bumped_version_string_directory);
|
||||
|
||||
$bumped_key_file = $bumped_version_directory->join('key.txt');
|
||||
$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);
|
||||
@ -635,7 +610,7 @@ function restore()
|
||||
$users = new ExampleUsers();
|
||||
$user = $users->getUser($user_id);
|
||||
|
||||
$bumped_changes_file = $bumped_version_directory->join('changes.json');
|
||||
$bumped_changes_file = $bumped_version_directory->join_path('changes.json');
|
||||
$bumped_changes_string_file = $bumped_changes_file->string();
|
||||
$bumped_changes = [
|
||||
'serverVersion' => null,
|
||||
@ -655,13 +630,13 @@ function restore()
|
||||
$source_extension = pathinfo($source_basename, PATHINFO_EXTENSION);
|
||||
$previous_basename = "prev.{$source_extension}";
|
||||
|
||||
$bumped_file = $bumped_version_directory->join($previous_basename);
|
||||
$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($previous_basename);
|
||||
$recovery_file = $recovery_version_directory->join_path($previous_basename);
|
||||
$recovery_string_file = $recovery_file->string();
|
||||
copy($recovery_string_file, $source_file);
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
@ -18,86 +18,110 @@
|
||||
namespace OnlineEditorsExamplePhp\Common;
|
||||
|
||||
final class Path {
|
||||
public string $separator;
|
||||
public ?string $dirname;
|
||||
public ?string $basename;
|
||||
public ?string $extension;
|
||||
public ?string $filename;
|
||||
private string $separator = DIRECTORY_SEPARATOR;
|
||||
private string $string;
|
||||
|
||||
public function __construct(
|
||||
string $path,
|
||||
string $separator = DIRECTORY_SEPARATOR
|
||||
) {
|
||||
$parsed_path = pathinfo($path);
|
||||
$this->separator = $separator;
|
||||
$this->dirname = self::dirname($parsed_path);
|
||||
$this->basename = self::basename($parsed_path);
|
||||
$this->extension = self::extension($parsed_path);
|
||||
$this->filename = self::filename($parsed_path);
|
||||
}
|
||||
|
||||
private static function dirname(array $path): ?string {
|
||||
return isset($path['dirname'])
|
||||
? $path['dirname']
|
||||
: null;
|
||||
}
|
||||
|
||||
private static function basename(array $path): ?string {
|
||||
return isset($path['basename'])
|
||||
? $path['basename']
|
||||
: null;
|
||||
}
|
||||
|
||||
private static function extension(array $path): ?string {
|
||||
return isset($path['extension'])
|
||||
? $path['extension']
|
||||
: null;
|
||||
}
|
||||
|
||||
private static function filename(array $path): ?string {
|
||||
return isset($path['filename'])
|
||||
? $path['filename']
|
||||
: null;
|
||||
public function __construct(string $path) {
|
||||
$this->string = $path;
|
||||
}
|
||||
|
||||
public function string(): string {
|
||||
$parts = array();
|
||||
if (!$this->dirname && !$this->basename) {
|
||||
return '.';
|
||||
}
|
||||
if ($this->dirname === $this->separator && $this->basename) {
|
||||
return "{$this->dirname}{$this->basename}";
|
||||
}
|
||||
if ($this->dirname !== '.') {
|
||||
$parts[] = $this->dirname;
|
||||
}
|
||||
if ($this->basename) {
|
||||
$parts[] = $this->basename;
|
||||
}
|
||||
return implode($this->separator, $parts);
|
||||
return $this->string;
|
||||
}
|
||||
|
||||
public function join(string ...$paths): self {
|
||||
if (!isset($paths[0])) {
|
||||
return $this;
|
||||
}
|
||||
|
||||
$next_paths = array_slice($paths, 1);
|
||||
if ($paths[0] == '' || $paths[0] == '.') {
|
||||
return $this->join(...$next_paths);
|
||||
}
|
||||
|
||||
$sub = new Path($paths[0], $this->separator);
|
||||
$sub_string = $sub->string();
|
||||
|
||||
public function dirname(): ?string {
|
||||
$string = $this->string();
|
||||
$separator = str_starts_with($sub_string, $this->separator)
|
||||
$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}");
|
||||
}
|
||||
|
||||
$joined_string = "{$string}{$separator}{$sub_string}";
|
||||
$joined = new Path($joined_string, $this->separator);
|
||||
public function absolute(): bool {
|
||||
$string = $this->string();
|
||||
|
||||
return $joined->join(...$next_paths);
|
||||
$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
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -11,6 +11,7 @@
|
||||
"psr-4": {
|
||||
"OnlineEditorsExamplePhp\\" : "",
|
||||
"OnlineEditorsExamplePhp\\Common\\": "common/",
|
||||
"OnlineEditorsExamplePhp\\Configuration\\" : "configuration/",
|
||||
"OnlineEditorsExamplePhp\\Helpers\\" : "helpers/",
|
||||
"OnlineEditorsExamplePhp\\Views\\" : "views/"
|
||||
}
|
||||
|
||||
@ -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];
|
||||
}
|
||||
}
|
||||
@ -917,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();
|
||||
}
|
||||
|
||||
@ -936,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;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -956,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;
|
||||
@ -976,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;
|
||||
}
|
||||
|
||||
@ -995,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)
|
||||
@ -1037,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;
|
||||
|
||||
@ -20,6 +20,7 @@ namespace OnlineEditorsExamplePhp\Helpers;
|
||||
|
||||
use Firebase\JWT\JWT;
|
||||
use Firebase\JWT\Key;
|
||||
use OnlineEditorsExamplePhp\Configuration\ConfigurationManager;
|
||||
|
||||
final class JwtManager
|
||||
{
|
||||
@ -30,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());
|
||||
}
|
||||
|
||||
/**
|
||||
@ -41,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;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -54,8 +55,8 @@ final class JwtManager
|
||||
*/
|
||||
public function jwtEncode($payload)
|
||||
{
|
||||
$configManager = new ConfigManager();
|
||||
return JWT::encode($payload, $configManager->getConfig("docServJwtSecret"), 'HS256');
|
||||
$config_manager = new ConfigurationManager();
|
||||
return JWT::encode($payload, $config_manager->jwt_secret(), 'HS256');
|
||||
}
|
||||
|
||||
/**
|
||||
@ -67,11 +68,11 @@ final class JwtManager
|
||||
*/
|
||||
public function jwtDecode($token)
|
||||
{
|
||||
$configManager = new ConfigManager();
|
||||
$config_manager = new ConfigurationManager();
|
||||
try {
|
||||
$payload = JWT::decode(
|
||||
$token,
|
||||
new Key($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,
|
||||
|
||||
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
|
||||
@ -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 () {
|
||||
@ -198,7 +198,7 @@
|
||||
userId: query.get('user') || config.editorConfig.user.id
|
||||
}
|
||||
const request = new XMLHttpRequest()
|
||||
request.open("PUT", '/webeditor-ajax.php?type=restore')
|
||||
request.open("PUT", 'restore')
|
||||
request.send(JSON.stringify(payload))
|
||||
request.onload = function () {
|
||||
if (request.status != 200) {
|
||||
|
||||
@ -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,123 +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));
|
||||
case 'restore':
|
||||
$response_array = restore();
|
||||
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,6 +67,7 @@ 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),
|
||||
|
||||
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)
|
||||
@ -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'
|
||||
)
|
||||
@ -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
|
||||
|
||||
@ -27,10 +27,12 @@ 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):
|
||||
@ -396,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
|
||||
|
||||
@ -556,3 +558,18 @@ def restore(request: HttpRequest) -> HttpResponse:
|
||||
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();
|
||||
}
|
||||
|
||||
10
web/documentserver-example/python/static/sr-only/sr-only.css
Normal file
10
web/documentserver-example/python/static/sr-only/sr-only.css
Normal file
@ -0,0 +1,10 @@
|
||||
.sr-only {
|
||||
border: 0;
|
||||
clip: rect(0, 0, 0, 0);
|
||||
height: 1px;
|
||||
overflow: hidden;
|
||||
padding: 0;
|
||||
position: absolute;
|
||||
width: 1px;
|
||||
word-wrap: normal;
|
||||
}
|
||||
@ -309,6 +309,103 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button id="MYBUTTON" type="button">click</button>
|
||||
|
||||
<form class="conversion">
|
||||
<div class="conversion-file">
|
||||
<span class="conversion-file__basename">document.docx</span>
|
||||
<span class="conversion-file__type">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none">
|
||||
<path d="M6 5H14L18 9V19H6V5Z" fill="white"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M18 9L14 5H6V19H18V9ZM14 4L19 9V20H5V4H14Z" fill="#BFBFBF"/>
|
||||
<rect x="7" y="14" width="10" height="4" fill="#3779A6"/>
|
||||
<path d="M7 8H8V9H7V8Z" fill="#BFBFBF"/>
|
||||
<path d="M7 10H8V11H7V10Z" fill="#BFBFBF"/>
|
||||
<path d="M8 12H7V13H8V12Z" fill="#BFBFBF"/>
|
||||
<path d="M16 12H9V13H16V12Z" fill="#BFBFBF"/>
|
||||
<path d="M16 10H9V11H16V10Z" fill="#BFBFBF"/>
|
||||
<path d="M12 8H9V9H12V8Z" fill="#BFBFBF"/>
|
||||
<path opacity="0.3" d="M13 5H14V8H17L18 9H13V5Z" fill="#333333"/>
|
||||
</svg>
|
||||
</span>
|
||||
</div>
|
||||
<ul class="conversion-steps">
|
||||
<li class="conversion-steps__step conversion-steps__step_skipped">
|
||||
<p class="conversion-steps__title"><span aria-hidden="true">1.</span> Select a format file to convert</p>
|
||||
<span class="conversion-steps__status">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="conversion-loading" aria-hidden="true" viewBox="0 0 24 24">
|
||||
<circle cx="12.5" cy="5.5" r="1.5" fill="#D9D9D9"/>
|
||||
<circle cx="16.5" cy="7.5" r="1.5" fill="#A4A4A4"/>
|
||||
<circle cx="18.5" cy="11.5" r="1.5" fill="#727272"/>
|
||||
<circle cx="16.5" cy="15.5" r="1.5" fill="#505050"/>
|
||||
<circle cx="12.5" cy="17.5" r="1.5" fill="#505050"/>
|
||||
<circle cx="8.5" cy="15.5" r="1.5" fill="#333333"/>
|
||||
</svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="conversion-succeeded" aria-hidden="true" viewBox="0 0 24 24">
|
||||
<path d="M10.3765 15.128C9.98789 15.5187 9.35642 15.5214 8.96449 15.134L6.14517 12.3473C5.75561 11.9622 5.12876 11.9622 4.7392 12.3473L4.72038 12.3659C4.32403 12.7576 4.32441 13.3978 4.72124 13.7891L8.96526 17.974C9.35702 18.3603 9.98726 18.3576 10.3757 17.9679L20.2877 8.02322C20.6801 7.62959 20.67 6.98549 20.2729 6.59667V6.59667C19.8804 6.21243 19.2454 6.21063 18.8581 6.60004L10.3765 15.128Z"/>
|
||||
</svg>
|
||||
</span>
|
||||
<div class="conversion-steps__contents">
|
||||
<p class="conversion-steps__description">The converting speed depends on file size and additional elements it contains.</p>
|
||||
<fieldset class="conversion-options">
|
||||
<legend class="sr-only">Select a format file to convert</legend>
|
||||
<label class="conversion-options__option"><input class="conversion-options__control" type="radio" name="format" value="pdf"><span class="conversion-options__indicator">pdf</span></label>
|
||||
<label class="conversion-options__option"><input class="conversion-options__control" type="radio" name="format" value="pdfа"><span class="conversion-options__indicator">pdfа</span></label>
|
||||
<label class="conversion-options__option"><input class="conversion-options__control" type="radio" name="format" value="docxf"><span class="conversion-options__indicator">docxf</span></label>
|
||||
<label class="conversion-options__option"><input class="conversion-options__control" type="radio" name="format" value="docx"><span class="conversion-options__indicator">docx</span></label>
|
||||
<label class="conversion-options__option"><input class="conversion-options__control" type="radio" name="format" value="jpg"><span class="conversion-options__indicator">jpg</span></label>
|
||||
<label class="conversion-options__option"><input class="conversion-options__control" type="radio" name="format" value="png"><span class="conversion-options__indicator">png</span></label>
|
||||
<label class="conversion-options__option"><input class="conversion-options__control" type="radio" name="format" value="txt"><span class="conversion-options__indicator">txt</span></label>
|
||||
<label class="conversion-options__option"><input class="conversion-options__control" type="radio" name="format" value="bmp"><span class="conversion-options__indicator">bmp</span></label>
|
||||
<label class="conversion-options__option"><input class="conversion-options__control" type="radio" name="format" value="rtf"><span class="conversion-options__indicator">rtf</span></label>
|
||||
<label class="conversion-options__option"><input class="conversion-options__control" type="radio" name="format" value="ebub"><span class="conversion-options__indicator">ebub</span></label>
|
||||
<label class="conversion-options__option"><input class="conversion-options__control" type="radio" name="format" value="fb2"><span class="conversion-options__indicator">fb2</span></label>
|
||||
<label class="conversion-options__option"><input class="conversion-options__control" type="radio" name="format" value="html"><span class="conversion-options__indicator">html</span></label>
|
||||
<label class="conversion-options__option"><input class="conversion-options__control" type="radio" name="format" value="docm"><span class="conversion-options__indicator">docm</span></label>
|
||||
<label class="conversion-options__option"><input class="conversion-options__control" type="radio" name="format" value="dotm"><span class="conversion-options__indicator">dotm</span></label>
|
||||
<label class="conversion-options__option"><input class="conversion-options__control" type="radio" name="format" value="odt"><span class="conversion-options__indicator">odt</span></label>
|
||||
<label class="conversion-options__option"><input class="conversion-options__control" type="radio" name="format" value="ott"><span class="conversion-options__indicator">ott</span></label>
|
||||
<label class="conversion-options__option"><input class="conversion-options__control" type="radio" name="format" value="dotx"><span class="conversion-options__indicator">dotx</span></label>
|
||||
</fieldset>
|
||||
</div>
|
||||
</li>
|
||||
<li class="conversion-steps__step conversion-steps__step_skipped">
|
||||
<p class="conversion-steps__title"><span aria-hidden="true">2.</span> File conversion</p>
|
||||
<span class="conversion-steps__status">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="conversion-loading" aria-hidden="true" viewBox="0 0 24 24">
|
||||
<circle cx="12.5" cy="5.5" r="1.5" fill="#D9D9D9"/>
|
||||
<circle cx="16.5" cy="7.5" r="1.5" fill="#A4A4A4"/>
|
||||
<circle cx="18.5" cy="11.5" r="1.5" fill="#727272"/>
|
||||
<circle cx="16.5" cy="15.5" r="1.5" fill="#505050"/>
|
||||
<circle cx="12.5" cy="17.5" r="1.5" fill="#505050"/>
|
||||
<circle cx="8.5" cy="15.5" r="1.5" fill="#333333"/>
|
||||
</svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="conversion-succeeded" aria-hidden="true" viewBox="0 0 24 24">
|
||||
<path d="M10.3765 15.128C9.98789 15.5187 9.35642 15.5214 8.96449 15.134L6.14517 12.3473C5.75561 11.9622 5.12876 11.9622 4.7392 12.3473L4.72038 12.3659C4.32403 12.7576 4.32441 13.3978 4.72124 13.7891L8.96526 17.974C9.35702 18.3603 9.98726 18.3576 10.3757 17.9679L20.2877 8.02322C20.6801 7.62959 20.67 6.98549 20.2729 6.59667V6.59667C19.8804 6.21243 19.2454 6.21063 18.8581 6.60004L10.3765 15.128Z"/>
|
||||
</svg>
|
||||
</span>
|
||||
<div class="conversion-steps__contents">
|
||||
<legend class="conversion-progress">The file is converted <progress class="sr-only" max="100" value="0">0%</progress><span class="conversion-progress__indicator" aria-hidden="true">0%</span></legend>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
<p class="conversion-note">Note the speed of all operations depends on your connection quality and server location.</p>
|
||||
<div class="conversion-error" hidden>
|
||||
<p class="conversion-error__message"><strong class="conversion-error__type">Upload error.</strong> Please select another file and try again.</p>
|
||||
<span class="conversion-error__icon">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="conversion-failed" aria-hidden="true" viewBox="0 0 16 16">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M7.99857 1.6C4.46508 1.6 1.6 4.46548 1.6 8.00029C1.6 9.70508 2.26458 11.2515 3.35202 12.3999C4.52033 13.6337 6.16874 14.4 7.99857 14.4C11.5348 14.4 14.4 11.5335 14.4 8.00029C14.4 4.46592 11.5348 1.6 7.99857 1.6ZM0 8.00029C0 3.58219 3.58105 0 7.99857 0C12.4184 0 16 3.58219 16 8.00029C16 12.4172 12.4184 16 7.99857 16C5.71117 16 3.64805 15.0395 2.19023 13.5C0.83265 12.0663 0 10.1304 0 8.00029ZM7 4H9V9H7V4ZM9 10H7V12H9V10Z"/>
|
||||
</svg>
|
||||
</span>
|
||||
</div>
|
||||
<div class="conversion-actions">
|
||||
<a class="conversion-actions__action conversion-actions__action_style_accent" type="button" disabled>Download</a>
|
||||
<a class="conversion-actions__action conversion-actions__action_style_neutral" disabled>View</a>
|
||||
<a class="conversion-actions__action conversion-actions__action_style_neutral" disabled>Edit</a>
|
||||
<button class="conversion-actions__action conversion-actions__action_style_neutral" type="button">Cancel</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<span id="loadScripts" data-docs="{{ preloadurl }}"></span>
|
||||
|
||||
<footer>
|
||||
|
||||
23
web/documentserver-example/ruby/Dockerfile
Normal file
23
web/documentserver-example/ruby/Dockerfile
Normal file
@ -0,0 +1,23 @@
|
||||
FROM ruby:3.2.2-alpine3.18 AS example-base
|
||||
WORKDIR /srv
|
||||
COPY . .
|
||||
RUN \
|
||||
apk update && \
|
||||
apk add --no-cache \
|
||||
build-base \
|
||||
gcompat \
|
||||
git \
|
||||
make \
|
||||
nodejs && \
|
||||
gem install bundler -v 2.3.7
|
||||
|
||||
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
|
||||
@ -17,39 +17,60 @@ else
|
||||
endif
|
||||
|
||||
.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 --dictionary-order | \
|
||||
awk 'BEGIN {FS = ": # "}; {printf "%s: %s\n", $$1, $$2}'
|
||||
|
||||
.PHONY: dev
|
||||
dev: # Install development dependencies and initialize the project.
|
||||
dev: # Install development dependencies and initialize the project.
|
||||
@bundle install
|
||||
@bundle exec rake app:update:bin
|
||||
ifeq ($(SORBET_SUPPORTED),1)
|
||||
@bundle exec tapioca init
|
||||
endif
|
||||
|
||||
.PHONY: dev-server
|
||||
dev-server: # Start the development server on localhost at $PORT (default: 3000).
|
||||
.PHONY: prod
|
||||
prod: # Install production dependencies.
|
||||
@bundle install --without development doc test
|
||||
@bundle exec rake app:update:bin
|
||||
|
||||
.PHONY: server-dev
|
||||
server-dev: # Start the development server on localhost at $PORT (default: 3000).
|
||||
@bundle exec rails server
|
||||
|
||||
.PHONY: server-prod
|
||||
server-prod: # Start the poruction server on 0.0.0.0 at $PORT (default: 3000).
|
||||
@bundle exec rails server --environment production
|
||||
|
||||
.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.
|
||||
lint: # Lint the source code for style and check for types.
|
||||
@bundle exec rubocop
|
||||
ifeq ($(SORBET_SUPPORTED),1)
|
||||
@bundle exec srb tc
|
||||
endif
|
||||
|
||||
.PHONY: prod
|
||||
prod: # Install production dependencies.
|
||||
@bundle install --without development doc test
|
||||
@bundle exec rake app:update:bin
|
||||
|
||||
.PHONY: prod-server
|
||||
prod-server: # Start the poruction server on 0.0.0.0 at $PORT (default: 3000).
|
||||
@bundle exec rails server --environment production
|
||||
|
||||
.PHONY: test
|
||||
test: # Recursively run the tests.
|
||||
test: # Recursively run the tests.
|
||||
@bundle exec rake test
|
||||
|
||||
33
web/documentserver-example/ruby/compose-base.yml
Normal file
33
web/documentserver-example/ruby/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: .
|
||||
target: example
|
||||
expose:
|
||||
- "80"
|
||||
environment:
|
||||
- BINDING=0.0.0.0
|
||||
- DOCUMENT_SERVER_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/ruby/compose-dev.yml
Normal file
6
web/documentserver-example/ruby/compose-dev.yml
Normal file
@ -0,0 +1,6 @@
|
||||
version: "3.8"
|
||||
|
||||
services:
|
||||
example:
|
||||
build:
|
||||
target: example-dev
|
||||
6
web/documentserver-example/ruby/compose-prod.yml
Normal file
6
web/documentserver-example/ruby/compose-prod.yml
Normal file
@ -0,0 +1,6 @@
|
||||
version: "3.8"
|
||||
|
||||
services:
|
||||
example:
|
||||
build:
|
||||
target: example-prod
|
||||
@ -20,6 +20,7 @@ class Application < Rails::Application
|
||||
config.assets.debug = true
|
||||
config.assets.digest = false
|
||||
config.eager_load = false
|
||||
config.hosts << /.*/
|
||||
config.require_master_key = false
|
||||
config.secret_key_base = SecureRandom.uuid
|
||||
|
||||
|
||||
38
web/documentserver-example/ruby/proxy/nginx.conf
Normal file
38
web/documentserver-example/ruby/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;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user