Compare commits
57 Commits
v5.3.99.28
...
v5.5.0.6
| Author | SHA1 | Date | |
|---|---|---|---|
| 710d4f4059 | |||
| bd4c3543d7 | |||
| 8770526316 | |||
| 51ecf3afeb | |||
| 8887edefb3 | |||
| 7ab292bc13 | |||
| 6ab006e409 | |||
| 582ed3f61b | |||
| d06cffabfb | |||
| 178477f9fb | |||
| b9dd792672 | |||
| 13c3164ca1 | |||
| ceed4ac712 | |||
| 6a16a9392a | |||
| 48043e5d70 | |||
| d7809b848e | |||
| d5466f1070 | |||
| f639971861 | |||
| 95ee0bf128 | |||
| 03efbf468e | |||
| 60cb77136a | |||
| d1d7d1e416 | |||
| a60e7b9b6b | |||
| 79d5682a02 | |||
| 96994fd0dc | |||
| 668a0e323a | |||
| 057d38d063 | |||
| 1ecf16085e | |||
| 945c09f5d4 | |||
| b642053bc3 | |||
| fef0179c7e | |||
| c0366c0134 | |||
| 584fb155b7 | |||
| 95a15661d0 | |||
| ca17dd1128 | |||
| e375404e25 | |||
| a58c1483b3 | |||
| 9b6e90718a | |||
| 14f8419f00 | |||
| 0899644f32 | |||
| 036c0fb19a | |||
| 5382c43ec5 | |||
| 8af7c45e7d | |||
| aa289a6d85 | |||
| b93aeebe3c | |||
| fe38ca4a08 | |||
| df74cdeb66 | |||
| 1f022f12a1 | |||
| 1217de89b3 | |||
| cd94eb0401 | |||
| 31c23fbf49 | |||
| 95b4556884 | |||
| 96bfe3c58a | |||
| 0f549db065 | |||
| c064b8fa57 | |||
| 490a6cd8b6 | |||
| 097a99b947 |
BIN
web/documentserver-example/csharp-mvc/App_Data/new.docx
Normal file
BIN
web/documentserver-example/csharp-mvc/App_Data/new.pptx
Normal file
BIN
web/documentserver-example/csharp-mvc/App_Data/new.xlsx
Normal file
|
After Width: | Height: | Size: 452 B |
|
After Width: | Height: | Size: 127 B |
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 1.0 KiB |
|
After Width: | Height: | Size: 1.2 KiB |
|
After Width: | Height: | Size: 1.2 KiB |
|
After Width: | Height: | Size: 1.7 KiB |
|
After Width: | Height: | Size: 152 B |
|
After Width: | Height: | Size: 118 B |
|
After Width: | Height: | Size: 1.2 KiB |
|
After Width: | Height: | Size: 1.2 KiB |
|
After Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 4.0 KiB After Width: | Height: | Size: 5.4 KiB |
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 145 B |
@ -113,13 +113,14 @@ label .checkbox {
|
||||
|
||||
.try-editor-list {
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
margin: 0 0 16px;
|
||||
padding: 0;
|
||||
}
|
||||
.try-editor-list li {
|
||||
float: left;
|
||||
margin: 25px;
|
||||
width: 150px;
|
||||
margin: 0 15px;
|
||||
width: 100px;
|
||||
cursor: pointer;
|
||||
}
|
||||
.try-editor {
|
||||
background-color: transparent;
|
||||
@ -143,6 +144,11 @@ label .checkbox {
|
||||
background-image: url("images/file_pptx.png");
|
||||
}
|
||||
|
||||
.create-sample {
|
||||
display: inline-block;
|
||||
margin-left: 75px;
|
||||
}
|
||||
|
||||
.button, .button:visited, .button:hover, .button:active {
|
||||
display: inline-block;
|
||||
font-weight: normal;
|
||||
@ -185,25 +191,43 @@ label .checkbox {
|
||||
border: 1px solid #E9EAEA;
|
||||
}
|
||||
|
||||
.upload-panel {
|
||||
border-right: 1px solid #D1D1D1;
|
||||
float: left;
|
||||
margin-right: 25px;
|
||||
}
|
||||
|
||||
.file-upload {
|
||||
background: url("images/file_upload.png") no-repeat center 0 transparent;
|
||||
cursor: pointer;
|
||||
margin-bottom: 8px;
|
||||
padding: 0 !important;
|
||||
display: inline-block;
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
height: 45px;
|
||||
margin: 0 40px 16px;
|
||||
overflow: hidden;
|
||||
padding-top: 100px;
|
||||
position: relative;
|
||||
text-align: center;
|
||||
width: 100px;
|
||||
}
|
||||
.file-upload span {
|
||||
line-height: 21px;
|
||||
margin: 2px 12px;
|
||||
|
||||
.file-upload input {
|
||||
cursor: pointer;
|
||||
opacity: 0;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0;
|
||||
transform: translate(555px, 60px) scale(8);
|
||||
}
|
||||
|
||||
.create-panel {
|
||||
float: left;
|
||||
}
|
||||
.file-upload input {
|
||||
cursor: pointer;
|
||||
font-size: 23px;
|
||||
opacity: 0;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0;
|
||||
transform: translate(-300px, 0) scale(4);
|
||||
|
||||
.upload-panel,
|
||||
.create-panel {
|
||||
padding: 10px 0;
|
||||
}
|
||||
|
||||
#mainProgress {
|
||||
@ -281,7 +305,54 @@ label .checkbox {
|
||||
line-height: 26px;
|
||||
}
|
||||
|
||||
.stored-list {
|
||||
border-top: 1px solid #D1D1D1;
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.stored-list li {
|
||||
border-bottom: 1px solid #D1D1D1;
|
||||
line-height: 28px;
|
||||
padding: 0 8px;
|
||||
}
|
||||
|
||||
.stored-edit {
|
||||
background-color: transparent;
|
||||
background-position: left center;
|
||||
background-repeat: no-repeat;
|
||||
display: inline-block;
|
||||
line-height: 16px;
|
||||
max-width: 450px;
|
||||
margin-bottom: -6px;
|
||||
overflow: hidden;
|
||||
padding: 4px 0 1px 34px;
|
||||
text-decoration: none;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.stored-edit.text {
|
||||
background-image: url("images/icon_docx.png");
|
||||
}
|
||||
|
||||
.stored-edit.spreadsheet {
|
||||
background-image: url("images/icon_xlsx.png");
|
||||
}
|
||||
|
||||
.stored-edit.presentation {
|
||||
background-image: url("images/icon_pptx.png");
|
||||
}
|
||||
|
||||
.stored-edit span {
|
||||
font-size: 12px;
|
||||
line-height: 12px;
|
||||
}
|
||||
|
||||
.stored-edit:hover span {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
|
||||
.blockTitle {
|
||||
@ -312,4 +383,121 @@ label .checkbox {
|
||||
-moz-box-shadow: 0 2px 4px rgba(0, 0, 0, 0.5);
|
||||
-webkit-box-shadow:0 2px 4px rgba(0, 0, 0, 0.5);
|
||||
padding: 0 !important;
|
||||
}
|
||||
}
|
||||
|
||||
.clearFix:after {
|
||||
content: ".";
|
||||
display: block;
|
||||
height: 0;
|
||||
clear: both;
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
/*Icon table*/
|
||||
#tableRow {
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
.tableRow {
|
||||
background: transparent;
|
||||
-moz-transition: all 0.2s ease-in-out;
|
||||
-webkit-transition: all 0.2s ease-in-out;
|
||||
-o-transition: all 0.2s ease-in-out;
|
||||
-ms-transition: all 0.2s ease-in-out;
|
||||
transition: all 0.2s ease-in-out;
|
||||
}
|
||||
|
||||
.tableRow:hover {
|
||||
background-color: #ebebeb;
|
||||
}
|
||||
|
||||
.tableHeader {
|
||||
background: transparent;
|
||||
color: #333;
|
||||
cursor: default;
|
||||
font-family: 'Open Sans', sans-serif;
|
||||
font-size: 13px;
|
||||
height: 40px;
|
||||
-khtml-user-select: none;
|
||||
user-select: none;
|
||||
-moz-user-select: none;
|
||||
-webkit-user-select: none;
|
||||
}
|
||||
|
||||
.tableHeaderCell {
|
||||
padding: 2px 1px 2px 5px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.tableHeaderCellFileName {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.contentCells {
|
||||
padding: 4px 1px 4px 5px;
|
||||
font-family: 'Open Sans', sans-serif;
|
||||
font-size: 16px;
|
||||
border-bottom: 1px solid #e5e5e5;
|
||||
white-space: nowrap;
|
||||
-khtml-user-select: none;
|
||||
user-select: none;
|
||||
-moz-user-select: none;
|
||||
-webkit-user-select: none;
|
||||
}
|
||||
|
||||
.contentCells a {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.contentCells-shift {
|
||||
padding-right: 30px;
|
||||
}
|
||||
|
||||
.contentCells-icon {
|
||||
width: 6%;
|
||||
}
|
||||
|
||||
.contentCellsSmall {
|
||||
padding: 5px 1px 5px 6px;
|
||||
font-family: 'Open Sans', sans-serif;
|
||||
font-size: 13px;
|
||||
border-bottom: 1px solid #e5e5e5;
|
||||
white-space: nowrap;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.primaryRow {
|
||||
background-color: #e9e9e9;
|
||||
}
|
||||
|
||||
.secondaryRow {
|
||||
background-color: #F9F9F9;
|
||||
}
|
||||
|
||||
.select-user {
|
||||
margin-left: 15px;
|
||||
}
|
||||
|
||||
.user-block-table {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.user-block-table td {
|
||||
background-color: #F4F4F4;
|
||||
border-bottom: 1px solid white;
|
||||
padding: 12px 0;
|
||||
}
|
||||
|
||||
#user, #language {
|
||||
width: 130px;
|
||||
}
|
||||
|
||||
.icon-download {
|
||||
margin-bottom: -5px;
|
||||
}
|
||||
|
||||
.icon-delete {
|
||||
cursor: pointer;
|
||||
margin-bottom: -6px;
|
||||
}
|
||||
@ -37,22 +37,22 @@ namespace OnlineEditorsExampleMVC.Controllers
|
||||
return View();
|
||||
}
|
||||
|
||||
public ActionResult Editor(string fileName, string mode)
|
||||
public ActionResult Editor(string fileName, string editorsMode, string editorsType)
|
||||
{
|
||||
mode = mode ?? string.Empty;
|
||||
|
||||
var file = new FileModel
|
||||
{
|
||||
TypeDesktop = mode != "embedded",
|
||||
Mode = editorsMode,
|
||||
Type = editorsType,
|
||||
FileName = fileName
|
||||
};
|
||||
|
||||
return View("Editor", file);
|
||||
}
|
||||
|
||||
public ActionResult Sample(string fileExt)
|
||||
public ActionResult Sample(string fileExt, bool? sample)
|
||||
{
|
||||
var fileName = DocManagerHelper.CreateDemo(fileExt);
|
||||
var fileName = DocManagerHelper.CreateDemo(fileExt, sample ?? false);
|
||||
DocManagerHelper.CreateMeta(fileName, Request.Cookies["uid"]?.Value, Request.Cookies["uname"]?.Value);
|
||||
Response.Redirect(Url.Action("Editor", "Home", new { fileName = fileName }));
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -28,11 +28,10 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Web;
|
||||
using System.Web.Caching;
|
||||
using System.Web.Configuration;
|
||||
using System.Web.Script.Serialization;
|
||||
using OnlineEditorsExampleMVC.Models;
|
||||
|
||||
namespace OnlineEditorsExampleMVC.Helpers
|
||||
@ -84,6 +83,32 @@ namespace OnlineEditorsExampleMVC.Helpers
|
||||
return directory + fileName;
|
||||
}
|
||||
|
||||
public static string HistoryDir(string storagePath)
|
||||
{
|
||||
return storagePath += "-hist";
|
||||
}
|
||||
|
||||
public static string VersionDir(string histPath, int version)
|
||||
{
|
||||
return Path.Combine(histPath, version.ToString());
|
||||
}
|
||||
|
||||
public static string VersionDir(string fileName, string userAddress, int version)
|
||||
{
|
||||
return VersionDir(HistoryDir(StoragePath(fileName, userAddress)), version);
|
||||
}
|
||||
|
||||
public static int GetFileVersion(string historyPath)
|
||||
{
|
||||
if (!Directory.Exists(historyPath)) return 0;
|
||||
return Directory.EnumerateDirectories(historyPath).Count();
|
||||
}
|
||||
|
||||
public static int GetFileVersion(string fileName, string userAddress)
|
||||
{
|
||||
return GetFileVersion(HistoryDir(StoragePath(fileName, userAddress)));
|
||||
}
|
||||
|
||||
public static string GetCorrectName(string fileName)
|
||||
{
|
||||
var baseName = Path.GetFileNameWithoutExtension(fileName);
|
||||
@ -97,9 +122,20 @@ namespace OnlineEditorsExampleMVC.Helpers
|
||||
return name;
|
||||
}
|
||||
|
||||
public static string CreateDemo(string fileExt)
|
||||
public static List<string> GetStoredFiles()
|
||||
{
|
||||
var demoName = "sample." + fileExt;
|
||||
var directory = HttpRuntime.AppDomainAppPath + WebConfigurationManager.AppSettings["storage-path"] + CurUserHostAddress(null) + "\\";
|
||||
if (!Directory.Exists(directory)) return new List<string>();
|
||||
|
||||
var directoryInfo = new DirectoryInfo(directory);
|
||||
|
||||
var storedFiles = directoryInfo.GetFiles("*.*", SearchOption.TopDirectoryOnly).Select(fileInfo => fileInfo.Name).ToList();
|
||||
return storedFiles;
|
||||
}
|
||||
|
||||
public static string CreateDemo(string fileExt, bool withContent)
|
||||
{
|
||||
var demoName = (withContent ? "sample." : "new.") + fileExt;
|
||||
|
||||
var fileName = GetCorrectName(demoName);
|
||||
|
||||
@ -108,6 +144,17 @@ namespace OnlineEditorsExampleMVC.Helpers
|
||||
return fileName;
|
||||
}
|
||||
|
||||
public static void CreateMeta(string fileName, string uid, string uname)
|
||||
{
|
||||
var histDir = HistoryDir(StoragePath(fileName, null));
|
||||
Directory.CreateDirectory(histDir);
|
||||
File.WriteAllText(Path.Combine(histDir, "createdInfo.json"), new JavaScriptSerializer().Serialize(new Dictionary<string, object> {
|
||||
{ "created", DateTime.Now.ToString() },
|
||||
{ "id", string.IsNullOrEmpty(uid) ? "uid-1" : uid },
|
||||
{ "name", string.IsNullOrEmpty(uname) ? "John Smith" : uname }
|
||||
}));
|
||||
}
|
||||
|
||||
public static string GetFileUri(string fileName)
|
||||
{
|
||||
var uri = new UriBuilder(HttpContext.Current.Request.Url)
|
||||
@ -121,6 +168,18 @@ namespace OnlineEditorsExampleMVC.Helpers
|
||||
return uri.ToString();
|
||||
}
|
||||
|
||||
public static string GetPathUri(string path)
|
||||
{
|
||||
var uri = new UriBuilder(HttpContext.Current.Request.Url)
|
||||
{
|
||||
Path = HttpRuntime.AppDomainAppVirtualPath + "/"
|
||||
+ path,
|
||||
Query = ""
|
||||
};
|
||||
|
||||
return uri.ToString();
|
||||
}
|
||||
|
||||
public static string GetCallback(string fileName)
|
||||
{
|
||||
var callbackUrl = new UriBuilder(HttpContext.Current.Request.Url)
|
||||
|
||||
@ -25,12 +25,14 @@
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Web.Configuration;
|
||||
using System.Web.Helpers;
|
||||
using System.Web.Script.Serialization;
|
||||
|
||||
namespace OnlineEditorsExampleMVC.Helpers
|
||||
{
|
||||
@ -107,15 +109,30 @@ namespace OnlineEditorsExampleMVC.Helpers
|
||||
request.Accept = "application/json";
|
||||
request.Timeout = ConvertTimeout;
|
||||
|
||||
var bodyString = string.Format("{{\"async\": {0},\"filetype\": \"{1}\",\"key\": \"{2}\",\"outputtype\": \"{3}\",\"title\": \"{4}\",\"url\": \"{5}\"}}",
|
||||
isAsync.ToString().ToLower(),
|
||||
fromExtension.Trim('.'),
|
||||
documentRevisionId,
|
||||
toExtension.Trim('.'),
|
||||
title,
|
||||
documentUri);
|
||||
var body = new Dictionary<string, object>() {
|
||||
{ "async", isAsync },
|
||||
{ "filetype", fromExtension.Trim('.') },
|
||||
{ "key", documentRevisionId },
|
||||
{ "outputtype", toExtension.Trim('.') },
|
||||
{ "title", title },
|
||||
{ "url", documentUri }
|
||||
};
|
||||
|
||||
var bytes = Encoding.UTF8.GetBytes(bodyString);
|
||||
if (JwtManager.Enabled)
|
||||
{
|
||||
var payload = new Dictionary<string, object>
|
||||
{
|
||||
{ "payload", body }
|
||||
};
|
||||
|
||||
var payloadToken = JwtManager.Encode(payload);
|
||||
var bodyToken = JwtManager.Encode(body);
|
||||
request.Headers.Add("Authorization", "Bearer " + payloadToken);
|
||||
|
||||
body.Add("token", bodyToken);
|
||||
}
|
||||
|
||||
var bytes = Encoding.UTF8.GetBytes(new JavaScriptSerializer().Serialize(body));
|
||||
request.ContentLength = bytes.Length;
|
||||
using (var requestStream = request.GetRequestStream())
|
||||
{
|
||||
|
||||
113
web/documentserver-example/csharp-mvc/Helpers/JwtManager.cs
Normal file
@ -0,0 +1,113 @@
|
||||
/*
|
||||
*
|
||||
* (c) Copyright Ascensio System SIA 2019
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using System.Web.Configuration;
|
||||
using System.Web.Script.Serialization;
|
||||
|
||||
namespace OnlineEditorsExampleMVC.Helpers
|
||||
{
|
||||
public static class JwtManager
|
||||
{
|
||||
private static readonly string Secret;
|
||||
public static readonly bool Enabled;
|
||||
|
||||
private static readonly JavaScriptSerializer Serializer;
|
||||
|
||||
static JwtManager()
|
||||
{
|
||||
Secret = WebConfigurationManager.AppSettings["files.docservice.secret"] ?? "";
|
||||
Enabled = !string.IsNullOrEmpty(Secret);
|
||||
Serializer = new JavaScriptSerializer();
|
||||
}
|
||||
|
||||
public static string Encode(IDictionary<string, object> payload)
|
||||
{
|
||||
var header = new Dictionary<string, object>
|
||||
{
|
||||
{ "alg", "HS256" },
|
||||
{ "typ", "JWT" }
|
||||
};
|
||||
|
||||
var encHeader = Base64UrlEncode(Serializer.Serialize(header));
|
||||
var encPayload = Base64UrlEncode(Serializer.Serialize(payload));
|
||||
var hashSum = Base64UrlEncode(CalculateHash(encHeader, encPayload));
|
||||
|
||||
return string.Format("{0}.{1}.{2}", encHeader, encPayload, hashSum);
|
||||
}
|
||||
|
||||
public static string Decode(string token)
|
||||
{
|
||||
if (!Enabled || string.IsNullOrEmpty(token)) return "";
|
||||
|
||||
var split = token.Split('.');
|
||||
if (split.Length != 3) return "";
|
||||
|
||||
var hashSum = Base64UrlEncode(CalculateHash(split[0], split[1]));
|
||||
if (hashSum != split[2]) return "";
|
||||
return Base64UrlDecode(split[1]);
|
||||
}
|
||||
|
||||
private static byte[] CalculateHash(string encHeader, string encPayload)
|
||||
{
|
||||
using (var hasher = new HMACSHA256(Encoding.UTF8.GetBytes(Secret)))
|
||||
{
|
||||
var bytes = Encoding.UTF8.GetBytes(string.Format("{0}.{1}", encHeader, encPayload));
|
||||
return hasher.ComputeHash(bytes);
|
||||
}
|
||||
}
|
||||
|
||||
private static string Base64UrlEncode(string str)
|
||||
{
|
||||
return Base64UrlEncode(Encoding.UTF8.GetBytes(str));
|
||||
}
|
||||
|
||||
private static string Base64UrlEncode(byte[] bytes)
|
||||
{
|
||||
return Convert.ToBase64String(bytes)
|
||||
.TrimEnd('=').Replace('+', '-').Replace('/', '_');
|
||||
}
|
||||
|
||||
private static string Base64UrlDecode(string payload)
|
||||
{
|
||||
var b64 = payload.Replace('_', '/').Replace('-', '+');
|
||||
switch (b64.Length%4)
|
||||
{
|
||||
case 2:
|
||||
b64 += "==";
|
||||
break;
|
||||
case 3:
|
||||
b64 += "=";
|
||||
break;
|
||||
}
|
||||
var bytes = Convert.FromBase64String(b64);
|
||||
return Encoding.UTF8.GetString(bytes);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -24,13 +24,21 @@
|
||||
*
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Web;
|
||||
using System.Web.Mvc;
|
||||
using System.Web.Script.Serialization;
|
||||
using OnlineEditorsExampleMVC.Helpers;
|
||||
|
||||
namespace OnlineEditorsExampleMVC.Models
|
||||
{
|
||||
public class FileModel
|
||||
{
|
||||
public bool TypeDesktop { get; set; }
|
||||
public string Mode { get; set; }
|
||||
public string Type { get; set; }
|
||||
|
||||
public string FileUri
|
||||
{
|
||||
@ -46,14 +54,173 @@ namespace OnlineEditorsExampleMVC.Models
|
||||
|
||||
public string Key
|
||||
{
|
||||
get { return ServiceConverter.GenerateRevisionId(DocManagerHelper.CurUserHostAddress() + "/" + FileName); }
|
||||
get { return ServiceConverter.GenerateRevisionId(DocManagerHelper.CurUserHostAddress() + "/" + FileName + "/" + File.GetLastWriteTime(DocManagerHelper.StoragePath(FileName, null)).GetHashCode()); }
|
||||
}
|
||||
|
||||
public string CallbackUrl
|
||||
{
|
||||
get
|
||||
get { return DocManagerHelper.GetCallback(FileName); }
|
||||
}
|
||||
|
||||
public string GetDocConfig(HttpRequest request, UrlHelper url)
|
||||
{
|
||||
var ext = Path.GetExtension(FileName);
|
||||
var editorsMode = Mode ?? "edit";
|
||||
|
||||
var canEdit = DocManagerHelper.EditedExts.Contains(ext);
|
||||
var mode = canEdit && editorsMode != "view" ? "edit" : "view";
|
||||
|
||||
var config = new Dictionary<string, object>
|
||||
{
|
||||
{ "type", Type ?? "desktop" },
|
||||
{ "documentType", DocumentType },
|
||||
{
|
||||
"document", new Dictionary<string, object>
|
||||
{
|
||||
{ "title", FileName },
|
||||
{ "url", FileUri },
|
||||
{ "fileType", ext.Trim('.') },
|
||||
{ "key", Key },
|
||||
{
|
||||
"info", new Dictionary<string, object>
|
||||
{
|
||||
{ "author", "Me" },
|
||||
{ "created", DateTime.Now.ToShortDateString() }
|
||||
}
|
||||
},
|
||||
{
|
||||
"permissions", new Dictionary<string, object>
|
||||
{
|
||||
{ "comment", editorsMode != "view" && editorsMode != "fillForms" && editorsMode != "embedded" && editorsMode != "blockcontent" },
|
||||
{ "download", true },
|
||||
{ "edit", canEdit && (editorsMode == "edit" || editorsMode == "filter") || editorsMode == "blockcontent" },
|
||||
{ "fillForms", editorsMode != "view" && editorsMode != "comment" && editorsMode != "embedded" && editorsMode != "blockcontent" },
|
||||
{ "modifyFilter", editorsMode != "filter" },
|
||||
{ "modifyContentControl", editorsMode != "blockcontent" },
|
||||
{ "review", editorsMode == "edit" || editorsMode == "review" }
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"editorConfig", new Dictionary<string, object>
|
||||
{
|
||||
{ "mode", mode },
|
||||
{ "lang", request.Cookies["ulang"]?.Value ?? "en" },
|
||||
{ "callbackUrl", CallbackUrl },
|
||||
{
|
||||
"user", new Dictionary<string, object>
|
||||
{
|
||||
{ "id", request.Cookies["uid"]?.Value ?? "uid-1" },
|
||||
{ "name", request.Cookies["uname"]?.Value ?? "John Smith" }
|
||||
}
|
||||
},
|
||||
{
|
||||
"embedded", new Dictionary<string, object>
|
||||
{
|
||||
{ "saveUrl", FileUri },
|
||||
{ "embedUrl", FileUri },
|
||||
{ "shareUrl", FileUri },
|
||||
{ "toolbarDocked", "top" }
|
||||
}
|
||||
},
|
||||
{
|
||||
"customization", new Dictionary<string, object>
|
||||
{
|
||||
{ "about", true },
|
||||
{ "feedback", true },
|
||||
{
|
||||
"goback", new Dictionary<string, object>
|
||||
{
|
||||
{ "url", url.Action("Index", "Home") }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if (JwtManager.Enabled)
|
||||
{
|
||||
return DocManagerHelper.GetCallback(FileName);
|
||||
var token = JwtManager.Encode(config);
|
||||
config.Add("token", token);
|
||||
}
|
||||
|
||||
return new JavaScriptSerializer().Serialize(config);
|
||||
}
|
||||
|
||||
public void GetHistory(out string history, out string historyData)
|
||||
{
|
||||
var jss = new JavaScriptSerializer();
|
||||
var histDir = DocManagerHelper.HistoryDir(DocManagerHelper.StoragePath(FileName, null));
|
||||
|
||||
history = null;
|
||||
historyData = null;
|
||||
|
||||
if (DocManagerHelper.GetFileVersion(histDir) > 0)
|
||||
{
|
||||
var currentVersion = DocManagerHelper.GetFileVersion(histDir);
|
||||
var hist = new List<Dictionary<string, object>>();
|
||||
var histData = new Dictionary<string, object>();
|
||||
|
||||
for (var i = 0; i <= currentVersion; i++)
|
||||
{
|
||||
var obj = new Dictionary<string, object>();
|
||||
var dataObj = new Dictionary<string, object>();
|
||||
var verDir = DocManagerHelper.VersionDir(histDir, i + 1);
|
||||
|
||||
var key = i == currentVersion ? Key : File.ReadAllText(Path.Combine(verDir, "key.txt"));
|
||||
|
||||
obj.Add("key", key);
|
||||
obj.Add("version", i);
|
||||
|
||||
if (i == 0)
|
||||
{
|
||||
var infoPath = Path.Combine(histDir, "createdInfo.json");
|
||||
|
||||
if (File.Exists(infoPath))
|
||||
{
|
||||
var info = jss.Deserialize<Dictionary<string, object>>(File.ReadAllText(infoPath));
|
||||
obj.Add("created", info["created"]);
|
||||
obj.Add("user", new Dictionary<string, object>() {
|
||||
{ "id", info["id"] },
|
||||
{ "name", info["name"] },
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
dataObj.Add("key", key);
|
||||
dataObj.Add("url", i == currentVersion ? FileUri : DocManagerHelper.GetPathUri(Directory.GetFiles(verDir, "prev.*")[0].Substring(HttpRuntime.AppDomainAppPath.Length)));
|
||||
dataObj.Add("version", i);
|
||||
if (i > 0)
|
||||
{
|
||||
var changes = jss.Deserialize<Dictionary<string, object>>(File.ReadAllText(Path.Combine(DocManagerHelper.VersionDir(histDir, i), "changes.json")));
|
||||
var change = ((Dictionary<string, object>)((ArrayList)changes["changes"])[0]);
|
||||
|
||||
obj.Add("changes", changes["changes"]);
|
||||
obj.Add("serverVersion", changes["serverVersion"]);
|
||||
obj.Add("created", change["created"]);
|
||||
obj.Add("user", change["user"]);
|
||||
|
||||
var prev = (Dictionary<string, object>)histData[(i - 1).ToString()];
|
||||
dataObj.Add("previous", new Dictionary<string, object>() {
|
||||
{ "key", prev["key"] },
|
||||
{ "url", prev["url"] },
|
||||
});
|
||||
dataObj.Add("changesUrl", DocManagerHelper.GetPathUri(Path.Combine(DocManagerHelper.VersionDir(histDir, i), "diff.zip").Substring(HttpRuntime.AppDomainAppPath.Length)));
|
||||
}
|
||||
|
||||
hist.Add(obj);
|
||||
histData.Add(i.ToString(), dataObj);
|
||||
}
|
||||
|
||||
history = jss.Serialize(new Dictionary<string, object>()
|
||||
{
|
||||
{ "currentVersion", currentVersion },
|
||||
{ "history", hist }
|
||||
});
|
||||
historyData = jss.Serialize(histData);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -136,6 +136,7 @@
|
||||
</Compile>
|
||||
<Compile Include="Helpers\DocManagerHelper.cs" />
|
||||
<Compile Include="Helpers\DocumentConverter.cs" />
|
||||
<Compile Include="Helpers\JwtManager.cs" />
|
||||
<Compile Include="Models\FileModel.cs" />
|
||||
<Compile Include="Models\FileUtility.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
@ -146,15 +147,26 @@
|
||||
<ItemGroup>
|
||||
<Content Include="Content\editor.css" />
|
||||
<Content Include="Content\images\alert.png" />
|
||||
<Content Include="Content\images\block-content-24.png" />
|
||||
<Content Include="Content\images\close.png" />
|
||||
<Content Include="Content\images\comment-24.png" />
|
||||
<Content Include="Content\images\corner.png" />
|
||||
<Content Include="Content\images\delete-24.png" />
|
||||
<Content Include="Content\images\desktop-24.png" />
|
||||
<Content Include="Content\images\done.png" />
|
||||
<Content Include="Content\images\download-24.png" />
|
||||
<Content Include="Content\images\embeded-24.png" />
|
||||
<Content Include="Content\images\file_docx.png" />
|
||||
<Content Include="Content\images\file_pptx.png" />
|
||||
<Content Include="Content\images\file_upload.png" />
|
||||
<Content Include="Content\images\file_xlsx.png" />
|
||||
<Content Include="Content\images\fill-forms-24.png" />
|
||||
<Content Include="Content\images\filter-24.png" />
|
||||
<Content Include="Content\images\loader16.gif" />
|
||||
<Content Include="Content\images\logo.png" />
|
||||
<Content Include="Content\images\mobile-24.png" />
|
||||
<Content Include="Content\images\question_small.png" />
|
||||
<Content Include="Content\images\review-24.png" />
|
||||
<Content Include="Content\jquery-ui.css" />
|
||||
<Content Include="Content\stylesheet.css" />
|
||||
<Content Include="favicon.ico" />
|
||||
|
||||
@ -70,6 +70,8 @@ if (typeof jQuery != "undefined") {
|
||||
checkConvert();
|
||||
}
|
||||
});
|
||||
|
||||
initSelectors();
|
||||
});
|
||||
|
||||
var timer = null;
|
||||
@ -91,11 +93,6 @@ if (typeof jQuery != "undefined") {
|
||||
return;
|
||||
}
|
||||
|
||||
if (jq("#checkOriginalFormat").is(":checked")) {
|
||||
loadScripts();
|
||||
return;
|
||||
}
|
||||
|
||||
timer = setTimeout(function () {
|
||||
var requestAddress = UrlConverter
|
||||
+ "&filename=" + encodeURIComponent(jq("#hiddenFileName").val());
|
||||
@ -162,6 +159,34 @@ if (typeof jQuery != "undefined") {
|
||||
}
|
||||
};
|
||||
|
||||
var initSelectors = function () {
|
||||
var userSel = jq("#user");
|
||||
var langSel = jq("#language");
|
||||
|
||||
function getCookie(name) {
|
||||
let matches = document.cookie.match(new RegExp(
|
||||
"(?:^|; )" + name.replace(/([\.$?*|{}\(\)\[\]\\\/\+^])/g, '\\$1') + "=([^;]*)"
|
||||
));
|
||||
return matches ? decodeURIComponent(matches[1]) : null;
|
||||
}
|
||||
function setCookie(name, value) {
|
||||
document.cookie = name + "=" + value + "; expires=" + new Date(Date.now() + 1000 * 60 * 60 * 24 * 7).toUTCString(); //week
|
||||
}
|
||||
|
||||
var userId = getCookie("uid");
|
||||
if (userId) userSel.val(userId);
|
||||
var langId = getCookie("ulang");
|
||||
if (langId) langSel.val(langId);
|
||||
|
||||
userSel.on("change", function () {
|
||||
setCookie("uid", userSel.val());
|
||||
setCookie("uname", userSel.find("option:selected").text())
|
||||
});
|
||||
langSel.on("change", function () {
|
||||
setCookie("ulang", langSel.val());
|
||||
});
|
||||
};
|
||||
|
||||
jq(document).on("click", "#beginEdit:not(.disable)", function () {
|
||||
var fileId = encodeURIComponent(jq('#hiddenFileName').val());
|
||||
var url = UrlEditor + "?fileName=" + fileId;
|
||||
@ -194,6 +219,33 @@ if (typeof jQuery != "undefined") {
|
||||
jq.unblockUI();
|
||||
});
|
||||
|
||||
jq(document).on("click", ".try-editor", function (e) {
|
||||
var url = jq(".try-editor-list")[0].attributes["data-link"].value;
|
||||
url += "?fileExt=" + e.target.attributes["data-type"].value;
|
||||
if (jq("#createSample").is(":checked")) {
|
||||
url += "&sample=true";
|
||||
}
|
||||
var w = window.open(url, "_blank");
|
||||
w.onload = function () {
|
||||
window.location.reload();
|
||||
}
|
||||
});
|
||||
|
||||
jq(document).on("click", ".delete-file", function () {
|
||||
var requestAddress = "webeditor.ashx"
|
||||
+ "?type=remove"
|
||||
+ "&filename=" + encodeURIComponent(jq(this).attr("data-filename"));
|
||||
|
||||
jq.ajax({
|
||||
async: true,
|
||||
contentType: "text/xml",
|
||||
url: requestAddress,
|
||||
complete: function (data) {
|
||||
document.location.reload();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
jq.dropdownToggle({
|
||||
switcherSelector: ".question",
|
||||
dropdownID: "hint"
|
||||
|
||||
@ -35,7 +35,9 @@
|
||||
<head runat="server">
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
<meta name="viewport" content="width=device-width" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no, minimal-ui" />
|
||||
<meta name="apple-mobile-web-app-capable" content="yes" />
|
||||
<meta name="mobile-web-app-capable" content="yes" />
|
||||
<link rel="icon" href="~/favicon.ico" type="image/x-icon" />
|
||||
<title><%= Model.FileName + " - ONLYOFFICE" %></title>
|
||||
|
||||
@ -53,8 +55,6 @@
|
||||
<script type="text/javascript" language="javascript">
|
||||
|
||||
var docEditor;
|
||||
var fileName = "<%= Model.FileName %>";
|
||||
var fileType = "<%= Path.GetExtension(Model.FileName).Trim('.') %>";
|
||||
|
||||
var innerAlert = function (message) {
|
||||
if (console && console.log)
|
||||
@ -83,66 +83,38 @@
|
||||
location.reload(true);
|
||||
};
|
||||
|
||||
var config = <%= Model.GetDocConfig(Request, Url) %>;
|
||||
|
||||
config.width = "100%";
|
||||
config.height = "100%";
|
||||
|
||||
config.events = {
|
||||
'onAppReady': onAppReady,
|
||||
'onDocumentStateChange': onDocumentStateChange,
|
||||
'onRequestEditRights': onRequestEditRights,
|
||||
'onError': onError,
|
||||
'onOutdatedVersion': onOutdatedVersion,
|
||||
};
|
||||
|
||||
<% string hist, histData; %>
|
||||
<% Model.GetHistory(out hist, out histData); %>
|
||||
<% if (!string.IsNullOrEmpty(hist) && !string.IsNullOrEmpty(histData))
|
||||
{ %>
|
||||
config.events['onRequestHistory'] = function () {
|
||||
docEditor.refreshHistory(<%= hist %>);
|
||||
};
|
||||
config.events['onRequestHistoryData'] = function (event) {
|
||||
var ver = event.data;
|
||||
var histData = <%= histData %>;
|
||||
docEditor.setHistoryData(histData[ver]);
|
||||
};
|
||||
config.events['onRequestHistoryClose '] = function () {
|
||||
document.location.reload();
|
||||
};
|
||||
<% } %>
|
||||
|
||||
var сonnectEditor = function () {
|
||||
|
||||
docEditor = new DocsAPI.DocEditor("iframeEditor",
|
||||
{
|
||||
width: "100%",
|
||||
height: "100%",
|
||||
|
||||
type: '<%= Request["mode"] != "embedded" ? "desktop" : "embedded" %>',
|
||||
documentType: "<%= Model.DocumentType %>",
|
||||
document: {
|
||||
title: fileName,
|
||||
url: "<%= Model.FileUri %>",
|
||||
fileType: fileType,
|
||||
key: "<%= Model.Key %>",
|
||||
|
||||
info: {
|
||||
author: "Me",
|
||||
created: "<%= DateTime.Now.ToShortDateString() %>",
|
||||
},
|
||||
|
||||
permissions: {
|
||||
edit: "<%= DocManagerHelper.EditedExts.Contains(Path.GetExtension(Model.FileName)) %>" == "True",
|
||||
download: true,
|
||||
}
|
||||
},
|
||||
editorConfig: {
|
||||
mode: '<%= DocManagerHelper.EditedExts.Contains(Path.GetExtension(Model.FileName)) && Request["mode"] != "view" ? "edit" : "view" %>',
|
||||
|
||||
lang: "en",
|
||||
|
||||
callbackUrl: "<%= Model.CallbackUrl %>",
|
||||
|
||||
user: {
|
||||
id: "<%= DocManagerHelper.CurUserHostAddress() %>",
|
||||
name: "John Smith",
|
||||
},
|
||||
|
||||
embedded: {
|
||||
saveUrl: "<%= Model.FileUri %>",
|
||||
embedUrl: "<%= Model.FileUri %>",
|
||||
shareUrl: "<%= Model.FileUri %>",
|
||||
toolbarDocked: "top",
|
||||
},
|
||||
|
||||
customization: {
|
||||
about: true,
|
||||
feedback: true,
|
||||
goback: {
|
||||
url: "<%= Url.Action("Index", "Home") %>",
|
||||
},
|
||||
},
|
||||
},
|
||||
events: {
|
||||
'onAppReady': onAppReady,
|
||||
'onDocumentStateChange': onDocumentStateChange,
|
||||
'onRequestEditRights': onRequestEditRights,
|
||||
'onError': onError,
|
||||
'onOutdatedVersion': onOutdatedVersion,
|
||||
}
|
||||
});
|
||||
docEditor = new DocsAPI.DocEditor("iframeEditor", config);
|
||||
};
|
||||
|
||||
if (window.addEventListener) {
|
||||
|
||||
@ -28,6 +28,7 @@
|
||||
|
||||
<%@ Import Namespace="System.Web.Configuration" %>
|
||||
<%@ Import Namespace="OnlineEditorsExampleMVC.Helpers" %>
|
||||
<%@ Import Namespace="OnlineEditorsExampleMVC.Models" %>
|
||||
|
||||
<!DOCTYPE html>
|
||||
|
||||
@ -50,26 +51,181 @@
|
||||
<span class="portal-name">ONLYOFFICE Document Editors</span>
|
||||
<br />
|
||||
<br />
|
||||
<span class="portal-descr">Get started with a demo-sample of ONLYOFFICE Document Editors, the first html5-based editors. You may upload your own documents for testing using the "Choose file" button and selecting the necessary files on your PC.</span>
|
||||
<span class="portal-descr">Get started with a demo-sample of ONLYOFFICE Document Editors, the first html5-based editors. You may upload your own documents for testing using the "Upload file" button and selecting the necessary files on your PC.</span>
|
||||
|
||||
<div class="file-upload button gray">
|
||||
<span>Choose file</span>
|
||||
<input type="file" id="fileupload" name="files[]" data-url="<%= Url.Content("~/webeditor.ashx?type=upload") %>" />
|
||||
<table class="user-block-table" cellspacing="0" cellpadding="0">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td width="30%" valign="middle">
|
||||
<span class="select-user">Username:</span>
|
||||
<select class="select-user" id="user">
|
||||
<option value="uid-1">Jonn Smith</option>
|
||||
<option value="uid-2">Mark Pottato</option>
|
||||
<option value="uid-3">Hamish Mitchell</option>
|
||||
</select>
|
||||
</td>
|
||||
<td width="70%" valign="middle">Select user name before opening the document; you can open the same document using different users in different Web browser sessions, so you can check out multi-user editing functions.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="30%" valign="middle">
|
||||
<select class="select-user" id="language">
|
||||
<option value="en">English</option>
|
||||
<option value="bg">Bulgarian</option>
|
||||
<option value="zh">Chinese</option>
|
||||
<option value="cs">Czech</option>
|
||||
<option value="nl">Dutch</option>
|
||||
<option value="fr">French</option>
|
||||
<option value="de">German</option>
|
||||
<option value="hu">Hungarian</option>
|
||||
<option value="it">Italian</option>
|
||||
<option value="ja">Japanese</option>
|
||||
<option value="ko">Korean</option>
|
||||
<option value="lv">Latvian</option>
|
||||
<option value="pl">Polish</option>
|
||||
<option value="pt">Portuguese</option>
|
||||
<option value="ru">Russian</option>
|
||||
<option value="sk">Slovak</option>
|
||||
<option value="sl">Slovenian</option>
|
||||
<option value="es">Spanish</option>
|
||||
<option value="tr">Turkish</option>
|
||||
<option value="uk">Ukrainian</option>
|
||||
<option value="vi">Vietnamese</option>
|
||||
</select>
|
||||
</td>
|
||||
<td width="70%" valign="middle">Choose the language for ONLYOFFICE™ editors interface.</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<br />
|
||||
<br />
|
||||
|
||||
|
||||
<div class="help-block">
|
||||
<span class="try-descr">Upload your file or create new file</span>
|
||||
<br />
|
||||
<br />
|
||||
<div class="clearFix">
|
||||
<div class="upload-panel clearFix">
|
||||
<a class="file-upload">
|
||||
Upload
|
||||
<br />
|
||||
File
|
||||
<input type="file" id="fileupload" name="files[]" data-url="<%= Url.Content("~/webeditor.ashx?type=upload") %>" />
|
||||
</a>
|
||||
</div>
|
||||
<div class="create-panel">
|
||||
<ul class="try-editor-list clearFix" data-link="<%= Url.Action("sample", "Home") %>">
|
||||
<li><a class="try-editor document" data-type="docx">Create<br />Document</a></li>
|
||||
<li><a class="try-editor spreadsheet" data-type="xlsx">Create<br />Spreadsheet</a></li>
|
||||
<li><a class="try-editor presentation" data-type="pptx">Create<br />Presentation</a></li>
|
||||
</ul>
|
||||
<label class="create-sample">
|
||||
<input id="createSample" class="checkbox" type="checkbox" />
|
||||
Create a file filled with sample content
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<label class="save-original">
|
||||
<input type="checkbox" id="checkOriginalFormat" class="checkbox" />Save document in original format
|
||||
</label>
|
||||
<span class="question"></span>
|
||||
<br />
|
||||
<br />
|
||||
<br />
|
||||
<span class="try-descr">You are also enabled to view and edit documents pre-uploaded to the portal.</span>
|
||||
|
||||
<ul class="try-editor-list">
|
||||
<li><a class="try-editor document" href="<%= Url.Action("sample", "Home", new { fileExt = "docx" }) %>" target="_blank">Create<br />Sample Document</a></li>
|
||||
<li><a class="try-editor spreadsheet" href="<%= Url.Action("sample", "Home", new { fileExt = "xlsx" }) %>" target="_blank">Create<br />Sample Spreadsheet</a></li>
|
||||
<li><a class="try-editor presentation" href="<%= Url.Action("sample", "Home", new { fileExt = "pptx" }) %>" target="_blank">Create<br />Sample Presentation</a></li>
|
||||
</ul>
|
||||
<% var storedFiles = DocManagerHelper.GetStoredFiles();
|
||||
if (storedFiles.Any())
|
||||
{ %>
|
||||
<div class="help-block">
|
||||
<span>Your documents</span>
|
||||
<br />
|
||||
<br />
|
||||
<div class="stored-list">
|
||||
<table width="100%" cellspacing="0" cellpadding="0">
|
||||
<thead>
|
||||
<tr class="tableHeader">
|
||||
<td class="tableHeaderCell tableHeaderCellFileName">Filename</td>
|
||||
<td colspan="6" class="tableHeaderCell contentCells-shift">Editors</td>
|
||||
<td colspan="3" class="tableHeaderCell">Viewers</td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<% foreach (var storedFile in storedFiles)
|
||||
{ %>
|
||||
<%
|
||||
var editUrl = "doceditor.aspx?fileID=" + HttpUtility.UrlEncode(storedFile);
|
||||
var docType = FileUtility.GetFileType(storedFile).ToString().ToLower();
|
||||
%>
|
||||
<tr class="tableRow" title="<%= storedFile %>">
|
||||
<td class="contentCells">
|
||||
<a class="stored-edit <%= docType %>" href="<%= Url.Action("Editor", "Home", new { fileName = storedFile }) %>" target="_blank">
|
||||
<span title="<%= storedFile %>"><%= storedFile %></span>
|
||||
</a>
|
||||
<a href="<%= Url.Content(DocManagerHelper.CurUserHostAddress() + "/" + storedFile) %>">
|
||||
<img class="icon-download" src="content/images/download-24.png" alt="Download" title="Download" />
|
||||
</a>
|
||||
<a class="delete-file" data-filename="<%= storedFile %>">
|
||||
<img class="icon-delete" src="content/images/delete-24.png" alt="Delete" title="Delete" />
|
||||
</a>
|
||||
</td>
|
||||
|
||||
<td class="contentCells contentCells-icon">
|
||||
<a href="<%= Url.Action("Editor", "Home", new { fileName = storedFile, editorsType = "desktop", editorsMode = "edit" }) %>" target="_blank">
|
||||
<img src="content/images/desktop-24.png" alt="Open in editor for full size screens" title="Open in editor for full size screens"/>
|
||||
</a>
|
||||
</td>
|
||||
<td class="contentCells contentCells-icon">
|
||||
<a href="<%= Url.Action("Editor", "Home", new { fileName = storedFile, editorsType = "mobile", editorsMode = "edit" }) %>" target="_blank">
|
||||
<img src="content/images/mobile-24.png" alt="Open in editor for mobile devices" title="Open in editor for mobile devices"/>
|
||||
</a>
|
||||
</td>
|
||||
<td class="contentCells contentCells-icon">
|
||||
<% if (docType == "text") { %>
|
||||
<a href="<%= Url.Action("Editor", "Home", new { fileName = storedFile, editorsType = "desktop", editorsMode = "review" }) %>" target="_blank">
|
||||
<img src="content/images/review-24.png" alt="Open in editor for review" title="Open in editor for review"/>
|
||||
</a>
|
||||
<% } else if (docType == "spreadsheet") { %>
|
||||
<a href="<%= Url.Action("Editor", "Home", new { fileName = storedFile, editorsType = "desktop", editorsMode = "filter" }) %>" target="_blank">
|
||||
<img src="content/images/filter-24.png" alt="Open in editor without access to change the filter" title="Open in editor without access to change the filter" />
|
||||
</a>
|
||||
<% } %>
|
||||
</td>
|
||||
<td class="contentCells contentCells-icon">
|
||||
<a href="<%= Url.Action("Editor", "Home", new { fileName = storedFile, editorsType = "desktop", editorsMode = "comment" }) %>" target="_blank">
|
||||
<img src="content/images/comment-24.png" alt="Open in editor for comment" title="Open in editor for comment"/>
|
||||
</a>
|
||||
</td>
|
||||
<td class="contentCells contentCells-icon">
|
||||
<% if (docType == "text") { %>
|
||||
<a href="<%= Url.Action("Editor", "Home", new { fileName = storedFile, editorsType = "desktop", editorsMode = "fillForms" }) %>" target="_blank">
|
||||
<img src="content/images/fill-forms-24.png" alt="Open in editor for filling in forms" title="Open in editor for filling in forms"/>
|
||||
</a>
|
||||
<% } %>
|
||||
</td>
|
||||
<td class="contentCells contentCells-shift contentCells-icon">
|
||||
<% if (docType == "text") { %>
|
||||
<a href="<%= Url.Action("Editor", "Home", new { fileName = storedFile, editorsType = "desktop", editorsMode = "blockcontent" }) %>" target="_blank">
|
||||
<img src="content/images/block-content-24.png" alt="Open in editor without content control modification" title="Open in editor without content control modification"/>
|
||||
</a>
|
||||
<% } %>
|
||||
</td>
|
||||
|
||||
<td class="contentCells contentCells-icon">
|
||||
<a href="<%= Url.Action("Editor", "Home", new { fileName = storedFile, editorsType = "desktop", editorsMode = "view" }) %>" target="_blank">
|
||||
<img src="content/images/desktop-24.png" alt="Open in viewer for full size screens" title="Open in viewer for full size screens"/>
|
||||
</a>
|
||||
</td>
|
||||
<td class="contentCells contentCells-icon">
|
||||
<a href="<%= Url.Action("Editor", "Home", new { fileName = storedFile, editorsType = "mobile", editorsMode = "view" }) %>" target="_blank">
|
||||
<img src="content/images/mobile-24.png" alt="Open in viewer for mobile devices" title="Open in viewer for mobile devices"/>
|
||||
</a>
|
||||
</td>
|
||||
<td class="contentCells contentCells-icon">
|
||||
<a href="<%= Url.Action("Editor", "Home", new { fileName = storedFile, editorsType = "embedded", editorsMode = "embedded" }) %>" target="_blank">
|
||||
<img src="content/images/embeded-24.png" alt="Open in embedded mode" title="Open in embedded mode"/>
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
<% } %>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<% } %>
|
||||
|
||||
<br />
|
||||
<br />
|
||||
|
||||
@ -27,8 +27,10 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Web;
|
||||
using System.Web.Configuration;
|
||||
using System.Web.Script.Serialization;
|
||||
using System.Web.Services;
|
||||
using OnlineEditorsExampleMVC.Helpers;
|
||||
@ -53,6 +55,9 @@ namespace OnlineEditorsExampleMVC
|
||||
case "track":
|
||||
Track(context);
|
||||
break;
|
||||
case "remove":
|
||||
Remove(context);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -90,6 +95,7 @@ namespace OnlineEditorsExampleMVC
|
||||
|
||||
var savedFileName = DocManagerHelper.StoragePath(fileName);
|
||||
httpPostedFile.SaveAs(savedFileName);
|
||||
DocManagerHelper.CreateMeta(fileName, context.Request.Cookies["uid"]?.Value, context.Request.Cookies["uname"]?.Value);
|
||||
|
||||
context.Response.Write("{ \"filename\": \"" + fileName + "\"}");
|
||||
}
|
||||
@ -143,8 +149,9 @@ namespace OnlineEditorsExampleMVC
|
||||
}
|
||||
}
|
||||
|
||||
File.Delete(DocManagerHelper.StoragePath(fileName));
|
||||
Remove(fileName);
|
||||
fileName = correctName;
|
||||
DocManagerHelper.CreateMeta(fileName, context.Request.Cookies["uid"]?.Value, context.Request.Cookies["uname"]?.Value);
|
||||
}
|
||||
|
||||
context.Response.Write("{ \"filename\" : \"" + fileName + "\"}");
|
||||
@ -169,8 +176,6 @@ namespace OnlineEditorsExampleMVC
|
||||
var userAddress = context.Request["userAddress"];
|
||||
var fileName = context.Request["fileName"];
|
||||
|
||||
var storagePath = DocManagerHelper.StoragePath(fileName, userAddress);
|
||||
|
||||
string body;
|
||||
try
|
||||
{
|
||||
@ -188,6 +193,24 @@ namespace OnlineEditorsExampleMVC
|
||||
var jss = new JavaScriptSerializer();
|
||||
if (string.IsNullOrEmpty(body)) return;
|
||||
var fileData = jss.Deserialize<Dictionary<string, object>>(body);
|
||||
|
||||
if (JwtManager.Enabled)
|
||||
{
|
||||
if (fileData.ContainsKey("token"))
|
||||
{
|
||||
fileData = jss.Deserialize<Dictionary<string, object>>(JwtManager.Decode(fileData["token"].ToString()));
|
||||
}
|
||||
else if (context.Request.Headers.AllKeys.Contains("Authorization", StringComparer.InvariantCultureIgnoreCase))
|
||||
{
|
||||
var headerToken = context.Request.Headers.Get("Authorization").Substring("Bearer ".Length);
|
||||
fileData = (Dictionary<string, object>)jss.Deserialize<Dictionary<string, object>>(JwtManager.Decode(headerToken))["payload"];
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception("Expected JWT");
|
||||
}
|
||||
}
|
||||
|
||||
var status = (TrackerStatus) (int) fileData["status"];
|
||||
|
||||
switch (status)
|
||||
@ -196,26 +219,32 @@ namespace OnlineEditorsExampleMVC
|
||||
case TrackerStatus.Corrupted:
|
||||
var downloadUri = (string) fileData["url"];
|
||||
|
||||
var req = (HttpWebRequest) WebRequest.Create(downloadUri);
|
||||
|
||||
var saved = 1;
|
||||
try
|
||||
{
|
||||
using (var stream = req.GetResponse().GetResponseStream())
|
||||
{
|
||||
if (stream == null) throw new Exception("stream is null");
|
||||
const int bufferSize = 4096;
|
||||
var storagePath = DocManagerHelper.StoragePath(fileName, userAddress);
|
||||
var histDir = DocManagerHelper.HistoryDir(storagePath);
|
||||
var versionDir = DocManagerHelper.VersionDir(histDir, DocManagerHelper.GetFileVersion(histDir) + 1);
|
||||
|
||||
using (var fs = File.Open(storagePath, FileMode.Create))
|
||||
{
|
||||
var buffer = new byte[bufferSize];
|
||||
int readed;
|
||||
while ((readed = stream.Read(buffer, 0, bufferSize)) != 0)
|
||||
{
|
||||
fs.Write(buffer, 0, readed);
|
||||
}
|
||||
}
|
||||
if (!Directory.Exists(versionDir)) Directory.CreateDirectory(versionDir);
|
||||
|
||||
File.Copy(storagePath, Path.Combine(versionDir, "prev" + Path.GetExtension(fileName)));
|
||||
|
||||
DownloadToFile(downloadUri, DocManagerHelper.StoragePath(fileName, userAddress));
|
||||
DownloadToFile((string)fileData["changesurl"], Path.Combine(versionDir, "diff.zip"));
|
||||
|
||||
var hist = fileData.ContainsKey("changeshistory") ? (string)fileData["changeshistory"] : null;
|
||||
if (string.IsNullOrEmpty(hist) && fileData.ContainsKey("history"))
|
||||
{
|
||||
hist = jss.Serialize(fileData["history"]);
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(hist))
|
||||
{
|
||||
File.WriteAllText(Path.Combine(versionDir, "changes.json"), hist);
|
||||
}
|
||||
|
||||
File.WriteAllText(Path.Combine(versionDir, "key.txt"), (string)fileData["key"]);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
@ -227,6 +256,54 @@ namespace OnlineEditorsExampleMVC
|
||||
context.Response.Write("{\"error\":0}");
|
||||
}
|
||||
|
||||
private static void Remove(HttpContext context)
|
||||
{
|
||||
context.Response.ContentType = "text/plain";
|
||||
try
|
||||
{
|
||||
var fileName = context.Request["fileName"];
|
||||
Remove(fileName);
|
||||
|
||||
context.Response.Write("{ \"success\": true }");
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
context.Response.Write("{ \"error\": \"" + e.Message + "\"}");
|
||||
}
|
||||
}
|
||||
|
||||
private static void Remove(string fileName)
|
||||
{
|
||||
var path = DocManagerHelper.StoragePath(fileName, null);
|
||||
var histDir = DocManagerHelper.HistoryDir(path);
|
||||
|
||||
if (File.Exists(path)) File.Delete(path);
|
||||
if (Directory.Exists(histDir)) Directory.Delete(histDir, true);
|
||||
}
|
||||
|
||||
private static void DownloadToFile(string url, string path)
|
||||
{
|
||||
if (string.IsNullOrEmpty(url)) throw new ArgumentException("url");
|
||||
if (string.IsNullOrEmpty(path)) throw new ArgumentException("path");
|
||||
|
||||
var req = (HttpWebRequest)WebRequest.Create(url);
|
||||
using (var stream = req.GetResponse().GetResponseStream())
|
||||
{
|
||||
if (stream == null) throw new Exception("stream is null");
|
||||
const int bufferSize = 4096;
|
||||
|
||||
using (var fs = File.Open(path, FileMode.Create))
|
||||
{
|
||||
var buffer = new byte[bufferSize];
|
||||
int readed;
|
||||
while ((readed = stream.Read(buffer, 0, bufferSize)) != 0)
|
||||
{
|
||||
fs.Write(buffer, 0, readed);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsReusable
|
||||
{
|
||||
get { return false; }
|
||||
|
||||
|
Before Width: | Height: | Size: 466 B After Width: | Height: | Size: 144 KiB |
@ -13,6 +13,7 @@
|
||||
<add key="files.docservice.edited-docs" value=".docx|.xlsx|.csv|.pptx|.txt"/>
|
||||
<add key="files.docservice.convert-docs" value=".docm|.dotx|.dotm|.dot|.doc|.odt|.fodt|.ott|.xlsm|.xltx|.xltm|.xlt|.xls|.ods|.fods|.ots|.pptm|.ppt|.ppsx|.ppsm|.pps|.potx|.potm|.pot|.odp|.fodp|.otp|.rtf|.mht|.html|.htm|.epub"/>
|
||||
<add key="files.docservice.timeout" value="120000" />
|
||||
<add key="files.docservice.secret" value="" />
|
||||
|
||||
<add key="files.docservice.url.converter" value="https://documentserver/ConvertService.ashx"/>
|
||||
<add key="files.docservice.url.api" value="https://documentserver/web-apps/apps/api/documents/api.js"/>
|
||||
|
||||
BIN
web/documentserver-example/csharp/App_Data/new.docx
Normal file
BIN
web/documentserver-example/csharp/App_Data/new.pptx
Normal file
BIN
web/documentserver-example/csharp/App_Data/new.xlsx
Normal file
|
After Width: | Height: | Size: 452 B |
|
After Width: | Height: | Size: 127 B |
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 1.0 KiB |
|
After Width: | Height: | Size: 1.2 KiB |
|
After Width: | Height: | Size: 1.2 KiB |
|
After Width: | Height: | Size: 1.7 KiB |
|
After Width: | Height: | Size: 152 B |
|
After Width: | Height: | Size: 118 B |
|
Before Width: | Height: | Size: 4.0 KiB After Width: | Height: | Size: 5.4 KiB |
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 145 B |
@ -112,14 +112,17 @@ label .checkbox {
|
||||
|
||||
.try-editor-list {
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
margin: 0 0 16px;
|
||||
padding: 0;
|
||||
}
|
||||
.try-editor-list li {
|
||||
float: left;
|
||||
margin: 25px;
|
||||
width: 150px;
|
||||
}
|
||||
|
||||
.try-editor-list li {
|
||||
float: left;
|
||||
margin: 0 15px;
|
||||
width: 100px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.try-editor {
|
||||
background-color: transparent;
|
||||
background-position: center 0;
|
||||
@ -142,6 +145,11 @@ label .checkbox {
|
||||
background-image: url("images/file_pptx.png");
|
||||
}
|
||||
|
||||
.create-sample {
|
||||
display: inline-block;
|
||||
margin-left: 75px;
|
||||
}
|
||||
|
||||
.button, .button:visited, .button:hover, .button:active {
|
||||
display: inline-block;
|
||||
font-weight: normal;
|
||||
@ -184,25 +192,43 @@ label .checkbox {
|
||||
border: 1px solid #E9EAEA;
|
||||
}
|
||||
|
||||
.upload-panel {
|
||||
border-right: 1px solid #D1D1D1;
|
||||
float: left;
|
||||
margin-right: 25px;
|
||||
}
|
||||
|
||||
.file-upload {
|
||||
background: url("images/file_upload.png") no-repeat center 0 transparent;
|
||||
cursor: pointer;
|
||||
margin-bottom: 8px;
|
||||
padding: 0 !important;
|
||||
display: inline-block;
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
height: 45px;
|
||||
margin: 0 40px 16px;
|
||||
overflow: hidden;
|
||||
padding-top: 100px;
|
||||
position: relative;
|
||||
text-align: center;
|
||||
width: 100px;
|
||||
}
|
||||
.file-upload span {
|
||||
line-height: 21px;
|
||||
margin: 2px 12px;
|
||||
|
||||
.file-upload input {
|
||||
cursor: pointer;
|
||||
opacity: 0;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0;
|
||||
transform: translate(555px, 60px) scale(8);
|
||||
}
|
||||
|
||||
.create-panel {
|
||||
float: left;
|
||||
}
|
||||
.file-upload input {
|
||||
cursor: pointer;
|
||||
font-size: 23px;
|
||||
opacity: 0;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0;
|
||||
transform: translate(-300px, 0) scale(4);
|
||||
|
||||
.upload-panel,
|
||||
.create-panel {
|
||||
padding: 10px 0;
|
||||
}
|
||||
|
||||
#mainProgress {
|
||||
@ -320,16 +346,6 @@ label .checkbox {
|
||||
.stored-edit:hover span {
|
||||
text-decoration: underline;
|
||||
}
|
||||
.stored-download {
|
||||
color: #787878;
|
||||
float: right;
|
||||
text-decoration: none;
|
||||
}
|
||||
.stored-download:hover {
|
||||
color: #787878;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
|
||||
|
||||
.blockTitle {
|
||||
@ -369,3 +385,112 @@ label .checkbox {
|
||||
clear: both;
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
/*Icon table*/
|
||||
#tableRow {
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
.tableRow {
|
||||
background: transparent;
|
||||
-moz-transition: all 0.2s ease-in-out;
|
||||
-webkit-transition: all 0.2s ease-in-out;
|
||||
-o-transition: all 0.2s ease-in-out;
|
||||
-ms-transition: all 0.2s ease-in-out;
|
||||
transition: all 0.2s ease-in-out;
|
||||
}
|
||||
|
||||
.tableRow:hover {
|
||||
background-color: #ebebeb;
|
||||
}
|
||||
|
||||
.tableHeader {
|
||||
background: transparent;
|
||||
color: #333;
|
||||
cursor: default;
|
||||
font-family: 'Open Sans', sans-serif;
|
||||
font-size: 13px;
|
||||
height: 40px;
|
||||
-khtml-user-select: none;
|
||||
user-select: none;
|
||||
-moz-user-select: none;
|
||||
-webkit-user-select: none;
|
||||
}
|
||||
|
||||
.tableHeaderCell {
|
||||
padding: 2px 1px 2px 5px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.tableHeaderCellFileName {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.contentCells {
|
||||
padding: 4px 1px 4px 5px;
|
||||
font-family: 'Open Sans', sans-serif;
|
||||
font-size: 16px;
|
||||
border-bottom: 1px solid #e5e5e5;
|
||||
white-space: nowrap;
|
||||
-khtml-user-select: none;
|
||||
user-select: none;
|
||||
-moz-user-select: none;
|
||||
-webkit-user-select: none;
|
||||
}
|
||||
|
||||
.contentCells a {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.contentCells-shift {
|
||||
padding-right: 30px;
|
||||
}
|
||||
|
||||
.contentCells-icon {
|
||||
width: 6%;
|
||||
}
|
||||
|
||||
.contentCellsSmall {
|
||||
padding: 5px 1px 5px 6px;
|
||||
font-family: 'Open Sans', sans-serif;
|
||||
font-size: 13px;
|
||||
border-bottom: 1px solid #e5e5e5;
|
||||
white-space: nowrap;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.primaryRow {
|
||||
background-color: #e9e9e9;
|
||||
}
|
||||
|
||||
.secondaryRow {
|
||||
background-color: #F9F9F9;
|
||||
}
|
||||
|
||||
.select-user {
|
||||
margin-left: 15px;
|
||||
}
|
||||
|
||||
.user-block-table {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.user-block-table td {
|
||||
background-color: #F4F4F4;
|
||||
border-bottom: 1px solid white;
|
||||
padding: 12px 0;
|
||||
}
|
||||
|
||||
#user, #language {
|
||||
width: 130px;
|
||||
}
|
||||
|
||||
.icon-download {
|
||||
margin-bottom: -5px;
|
||||
}
|
||||
|
||||
.icon-delete {
|
||||
cursor: pointer;
|
||||
margin-bottom: -6px;
|
||||
}
|
||||
@ -46,25 +46,81 @@
|
||||
<span class="portal-name">ONLYOFFICE Document Editors</span>
|
||||
<br />
|
||||
<br />
|
||||
<span class="portal-descr">Get started with a demo-sample of ONLYOFFICE Document Editors, the first html5-based editors. You may upload your own documents for testing using the "Choose file" button and selecting the necessary files on your PC.</span>
|
||||
<span class="portal-descr">Get started with a demo-sample of ONLYOFFICE Document Editors, the first html5-based editors. You may upload your own documents for testing using the "Upload file" button and selecting the necessary files on your PC.</span>
|
||||
|
||||
<div class="file-upload button gray">
|
||||
<span>Choose file</span>
|
||||
<input type="file" id="fileupload" name="files[]" data-url="webeditor.ashx?type=upload" />
|
||||
<table class="user-block-table" cellspacing="0" cellpadding="0">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td width="30%" valign="middle">
|
||||
<span class="select-user">Username:</span>
|
||||
<select class="select-user" id="user">
|
||||
<option value="uid-1">Jonn Smith</option>
|
||||
<option value="uid-2">Mark Pottato</option>
|
||||
<option value="uid-3">Hamish Mitchell</option>
|
||||
</select>
|
||||
</td>
|
||||
<td width="70%" valign="middle">Select user name before opening the document; you can open the same document using different users in different Web browser sessions, so you can check out multi-user editing functions.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="30%" valign="middle">
|
||||
<select class="select-user" id="language">
|
||||
<option value="en">English</option>
|
||||
<option value="bg">Bulgarian</option>
|
||||
<option value="zh">Chinese</option>
|
||||
<option value="cs">Czech</option>
|
||||
<option value="nl">Dutch</option>
|
||||
<option value="fr">French</option>
|
||||
<option value="de">German</option>
|
||||
<option value="hu">Hungarian</option>
|
||||
<option value="it">Italian</option>
|
||||
<option value="ja">Japanese</option>
|
||||
<option value="ko">Korean</option>
|
||||
<option value="lv">Latvian</option>
|
||||
<option value="pl">Polish</option>
|
||||
<option value="pt">Portuguese</option>
|
||||
<option value="ru">Russian</option>
|
||||
<option value="sk">Slovak</option>
|
||||
<option value="sl">Slovenian</option>
|
||||
<option value="es">Spanish</option>
|
||||
<option value="tr">Turkish</option>
|
||||
<option value="uk">Ukrainian</option>
|
||||
<option value="vi">Vietnamese</option>
|
||||
</select>
|
||||
</td>
|
||||
<td width="70%" valign="middle">Choose the language for ONLYOFFICE™ editors interface.</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<br />
|
||||
<br />
|
||||
|
||||
<div class="help-block">
|
||||
<span class="try-descr">Upload your file or create new file</span>
|
||||
<br />
|
||||
<br />
|
||||
<div class="clearFix">
|
||||
<div class="upload-panel clearFix">
|
||||
<a class="file-upload">
|
||||
Upload
|
||||
<br />
|
||||
File
|
||||
<input type="file" id="fileupload" name="files[]" data-url="webeditor.ashx?type=upload" />
|
||||
</a>
|
||||
</div>
|
||||
<div class="create-panel">
|
||||
<ul class="try-editor-list clearFix">
|
||||
<li><a class="try-editor document" data-type="document">Create<br />Document</a></li>
|
||||
<li><a class="try-editor spreadsheet" data-type="spreadsheet">Create<br />Spreadsheet</a></li>
|
||||
<li><a class="try-editor presentation" data-type="presentation">Create<br />Presentation</a></li>
|
||||
</ul>
|
||||
<label class="create-sample">
|
||||
<input id="createSample" class="checkbox" type="checkbox" />
|
||||
Create a file filled with sample content
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<label class="save-original">
|
||||
<input type="checkbox" id="checkOriginalFormat" class="checkbox" />Save document in original format
|
||||
</label>
|
||||
<span class="question"></span>
|
||||
<br />
|
||||
<br />
|
||||
<br />
|
||||
<span class="try-descr">You are also enabled to view and edit documents pre-uploaded to the portal.</span>
|
||||
<ul class="try-editor-list">
|
||||
<li><a class="try-editor document" href="doceditor.aspx?type=document" target="_blank">Create<br />Sample Document</a></li>
|
||||
<li><a class="try-editor spreadsheet" href="doceditor.aspx?type=spreadsheet" target="_blank">Create<br />Sample Spreadsheet</a></li>
|
||||
<li><a class="try-editor presentation" href="doceditor.aspx?type=presentation" target="_blank">Create<br />Sample Presentation</a></li>
|
||||
</ul>
|
||||
|
||||
|
||||
<% var storedFiles = GetStoredFiles();
|
||||
if (storedFiles.Any())
|
||||
@ -73,17 +129,96 @@
|
||||
<span>Your documents</span>
|
||||
<br />
|
||||
<br />
|
||||
<ul class="stored-list">
|
||||
<% foreach (var storedFile in storedFiles)
|
||||
{ %>
|
||||
<li class="clearFix">
|
||||
<a class="stored-edit <%= DocumentType(storedFile) %>" href="doceditor.aspx?fileID=<%= HttpUtility.UrlEncode(storedFile) %>" target="_blank">
|
||||
<span title="<%= storedFile %>"><%= storedFile %></span>
|
||||
</a>
|
||||
<a class="stored-download" href="<%= VirtualPath + WebConfigurationManager.AppSettings["storage-path"] + storedFile %>">Download</a>
|
||||
</li>
|
||||
<% } %>
|
||||
</ul>
|
||||
<div class="stored-list">
|
||||
<table width="100%" cellspacing="0" cellpadding="0">
|
||||
<thead>
|
||||
<tr class="tableHeader">
|
||||
<td class="tableHeaderCell tableHeaderCellFileName">Filename</td>
|
||||
<td colspan="6" class="tableHeaderCell contentCells-shift">Editors</td>
|
||||
<td colspan="3" class="tableHeaderCell">Viewers</td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<% foreach (var storedFile in storedFiles)
|
||||
{ %>
|
||||
<%
|
||||
var editUrl = "doceditor.aspx?fileID=" + HttpUtility.UrlEncode(storedFile);
|
||||
var docType = DocumentType(storedFile);
|
||||
%>
|
||||
<tr class="tableRow" title="<%= storedFile %>">
|
||||
<td class="contentCells">
|
||||
<a class="stored-edit <%= docType %>" href="<%= editUrl %>" target="_blank">
|
||||
<span title="<%= storedFile %>"><%= storedFile %></span>
|
||||
</a>
|
||||
<a href="<%= VirtualPath + WebConfigurationManager.AppSettings["storage-path"] + storedFile %>">
|
||||
<img class="icon-download" src="app_themes/images/download-24.png" alt="Download" title="Download" />
|
||||
</a>
|
||||
<a class="delete-file" data-filename="<%= storedFile %>">
|
||||
<img class="icon-delete" src="app_themes/images/delete-24.png" alt="Delete" title="Delete" />
|
||||
</a>
|
||||
</td>
|
||||
|
||||
<td class="contentCells contentCells-icon">
|
||||
<a href="<%= editUrl + "&editorsType=desktop&editorsMode=edit" %>" target="_blank">
|
||||
<img src="app_themes/images/desktop-24.png" alt="Open in editor for full size screens" title="Open in editor for full size screens"/>
|
||||
</a>
|
||||
</td>
|
||||
<td class="contentCells contentCells-icon">
|
||||
<a href="<%= editUrl + "&editorsType=mobile&editorsMode=edit" %>" target="_blank">
|
||||
<img src="app_themes/images/mobile-24.png" alt="Open in editor for mobile devices" title="Open in editor for mobile devices"/>
|
||||
</a>
|
||||
</td>
|
||||
<td class="contentCells contentCells-icon">
|
||||
<% if (docType == "text") { %>
|
||||
<a href="<%= editUrl + "&editorsType=desktop&editorsMode=review" %>" target="_blank">
|
||||
<img src="app_themes/images/review-24.png" alt="Open in editor for review" title="Open in editor for review"/>
|
||||
</a>
|
||||
<% } else if (docType == "spreadsheet") { %>
|
||||
<a href="<%= editUrl + "&editorsType=desktop&editorsMode=filter" %>" target="_blank">
|
||||
<img src="app_themes/images/filter-24.png" alt="Open in editor without access to change the filter" title="Open in editor without access to change the filter" />
|
||||
</a>
|
||||
<% } %>
|
||||
</td>
|
||||
<td class="contentCells contentCells-icon">
|
||||
<a href="<%= editUrl + "&editorsType=desktop&editorsMode=comment" %>" target="_blank">
|
||||
<img src="app_themes/images/comment-24.png" alt="Open in editor for comment" title="Open in editor for comment"/>
|
||||
</a>
|
||||
</td>
|
||||
<td class="contentCells contentCells-icon">
|
||||
<% if (docType == "text") { %>
|
||||
<a href="<%= editUrl + "&editorsType=desktop&editorsMode=fillForms" %>" target="_blank">
|
||||
<img src="app_themes/images/fill-forms-24.png" alt="Open in editor for filling in forms" title="Open in editor for filling in forms"/>
|
||||
</a>
|
||||
<% } %>
|
||||
</td>
|
||||
<td class="contentCells contentCells-icon contentCells-shift">
|
||||
<% if (docType == "text") { %>
|
||||
<a href="<%= editUrl + "&editorsType=desktop&editorsMode=blockcontent" %>" target="_blank">
|
||||
<img src="app_themes/images/block-content-24.png" alt="Open in editor without content control modification" title="Open in editor without content control modification"/>
|
||||
</a>
|
||||
<% } %>
|
||||
</td>
|
||||
|
||||
<td class="contentCells contentCells-icon">
|
||||
<a href="<%= editUrl + "&editorsType=desktop&editorsMode=view" %>" target="_blank">
|
||||
<img src="app_themes/images/desktop-24.png" alt="Open in viewer for full size screens" title="Open in viewer for full size screens"/>
|
||||
</a>
|
||||
</td>
|
||||
<td class="contentCells contentCells-icon">
|
||||
<a href="<%= editUrl + "&editorsType=mobile&editorsMode=view" %>" target="_blank">
|
||||
<img src="app_themes/images/mobile-24.png" alt="Open in viewer for mobile devices" title="Open in viewer for mobile devices"/>
|
||||
</a>
|
||||
</td>
|
||||
<td class="contentCells contentCells-icon">
|
||||
<a href="<%= editUrl + "&editorsType=embedded&editorsMode=embedded" %>" target="_blank">
|
||||
<img src="app_themes/images/embeded-24.png" alt="Open in embedded mode" title="Open in embedded mode"/>
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
<% } %>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<% } %>
|
||||
|
||||
@ -156,10 +291,7 @@
|
||||
<br />
|
||||
<div id="beginEmbedded" class="button disable">Embedded view</div>
|
||||
<div id="beginView" class="button disable">View</div>
|
||||
<% if (EditMode)
|
||||
{ %>
|
||||
<div id="beginEdit" class="button disable">Edit</div>
|
||||
<% } %>
|
||||
<div id="cancelEdit" class="button gray">Cancel</div>
|
||||
</div>
|
||||
|
||||
|
||||
@ -31,8 +31,8 @@ using System.Linq;
|
||||
using System.Net;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Web;
|
||||
using System.Web.Caching;
|
||||
using System.Web.Configuration;
|
||||
using System.Web.Script.Serialization;
|
||||
using System.Web.UI;
|
||||
using ASC.Api.DocumentConverter;
|
||||
|
||||
@ -102,12 +102,10 @@ namespace OnlineEditorsExample
|
||||
}
|
||||
|
||||
private static bool? _ismono;
|
||||
|
||||
public static bool IsMono
|
||||
{
|
||||
get
|
||||
{
|
||||
return _ismono.HasValue ? _ismono.Value : (_ismono = (bool?)(Type.GetType("Mono.Runtime") != null)).Value;
|
||||
}
|
||||
get { return _ismono.HasValue ? _ismono.Value : (_ismono = (bool?)(Type.GetType("Mono.Runtime") != null)).Value; }
|
||||
}
|
||||
|
||||
private static long MaxFileSize
|
||||
@ -140,11 +138,6 @@ namespace OnlineEditorsExample
|
||||
get { return (WebConfigurationManager.AppSettings["files.docservice.convert-docs"] ?? "").Split(new char[] { '|', ',' }, StringSplitOptions.RemoveEmptyEntries).ToList(); }
|
||||
}
|
||||
|
||||
public static bool EditMode
|
||||
{
|
||||
get { return (WebConfigurationManager.AppSettings["mode"] ?? "") != "view"; }
|
||||
}
|
||||
|
||||
private static string _fileName;
|
||||
|
||||
public static string CurUserHostAddress(string userAddress)
|
||||
@ -162,6 +155,32 @@ namespace OnlineEditorsExample
|
||||
return directory + fileName;
|
||||
}
|
||||
|
||||
public static string HistoryDir(string storagePath)
|
||||
{
|
||||
return storagePath += "-hist";
|
||||
}
|
||||
|
||||
public static string VersionDir(string histPath, int version)
|
||||
{
|
||||
return Path.Combine(histPath, version.ToString());
|
||||
}
|
||||
|
||||
public static string VersionDir(string fileName, string userAddress, int version)
|
||||
{
|
||||
return VersionDir(HistoryDir(StoragePath(fileName, userAddress)), version);
|
||||
}
|
||||
|
||||
public static int GetFileVersion(string historyPath)
|
||||
{
|
||||
if (!Directory.Exists(historyPath)) return 0;
|
||||
return Directory.EnumerateDirectories(historyPath).Count();
|
||||
}
|
||||
|
||||
public static int GetFileVersion(string fileName, string userAddress)
|
||||
{
|
||||
return GetFileVersion(HistoryDir(StoragePath(fileName, userAddress)));
|
||||
}
|
||||
|
||||
public static string FileUri(string fileName)
|
||||
{
|
||||
var uri = Host;
|
||||
@ -218,10 +237,18 @@ namespace OnlineEditorsExample
|
||||
var savedFileName = StoragePath(_fileName, null);
|
||||
httpPostedFile.SaveAs(savedFileName);
|
||||
|
||||
var histDir = HistoryDir(savedFileName);
|
||||
Directory.CreateDirectory(histDir);
|
||||
File.WriteAllText(Path.Combine(histDir, "createdInfo.json"), new JavaScriptSerializer().Serialize(new Dictionary<string, object> {
|
||||
{ "created", DateTime.Now.ToString() },
|
||||
{ "id", context.Request.Cookies["uid"]?.Value ?? "uid-1" },
|
||||
{ "name", context.Request.Cookies["uname"]?.Value ?? "John Smith" }
|
||||
}));
|
||||
|
||||
return _fileName;
|
||||
}
|
||||
|
||||
public static string DoUpload(string fileUri)
|
||||
public static string DoUpload(string fileUri, HttpRequest request)
|
||||
{
|
||||
_fileName = GetCorrectName(Path.GetFileName(fileUri));
|
||||
|
||||
@ -256,6 +283,14 @@ namespace OnlineEditorsExample
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var histDir = HistoryDir(StoragePath(_fileName, null));
|
||||
Directory.CreateDirectory(histDir);
|
||||
File.WriteAllText(Path.Combine(histDir, "createdInfo.json"), new JavaScriptSerializer().Serialize(new Dictionary<string, object> {
|
||||
{ "created", DateTime.Now.ToString() },
|
||||
{ "id", request.Cookies["uid"]?.Value ?? "uid-1" },
|
||||
{ "name", request.Cookies["uname"]?.Value ?? "John Smith" }
|
||||
}));
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
@ -309,8 +344,19 @@ namespace OnlineEditorsExample
|
||||
}
|
||||
}
|
||||
|
||||
File.Delete(StoragePath(_fileName, null));
|
||||
var storagePath = StoragePath(_fileName, null);
|
||||
var histDir = HistoryDir(storagePath);
|
||||
File.Delete(storagePath);
|
||||
if (Directory.Exists(histDir)) Directory.Delete(histDir, true);
|
||||
|
||||
_fileName = fileName;
|
||||
histDir = HistoryDir(StoragePath(_fileName, null));
|
||||
Directory.CreateDirectory(histDir);
|
||||
File.WriteAllText(Path.Combine(histDir, "createdInfo.json"), new JavaScriptSerializer().Serialize(new Dictionary<string, object> {
|
||||
{ "created", DateTime.Now.ToString() },
|
||||
{ "id", context.Request.Cookies["uid"]?.Value ?? "uid-1" },
|
||||
{ "name", context.Request.Cookies["uname"]?.Value ?? "John Smith" }
|
||||
}));
|
||||
}
|
||||
|
||||
return "{ \"filename\" : \"" + _fileName + "\"}";
|
||||
|
||||
@ -8,6 +8,9 @@
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head runat="server">
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no, minimal-ui" />
|
||||
<meta name="apple-mobile-web-app-capable" content="yes" />
|
||||
<meta name="mobile-web-app-capable" content="yes" />
|
||||
<link rel="icon" href="~/favicon.ico" type="image/x-icon" />
|
||||
<title>ONLYOFFICE</title>
|
||||
|
||||
@ -45,8 +48,6 @@
|
||||
<script type="text/javascript" language="javascript">
|
||||
|
||||
var docEditor;
|
||||
var fileName = "<%= FileName %>";
|
||||
var fileType = "<%= Path.GetExtension(FileName).Trim('.') %>";
|
||||
|
||||
var innerAlert = function (message) {
|
||||
if (console && console.log)
|
||||
@ -75,66 +76,36 @@
|
||||
location.reload(true);
|
||||
};
|
||||
|
||||
var config = <%= DocConfig %>;
|
||||
|
||||
config.width = "100%";
|
||||
config.height = "100%";
|
||||
|
||||
config.events = {
|
||||
'onAppReady': onAppReady,
|
||||
'onDocumentStateChange': onDocumentStateChange,
|
||||
'onRequestEditRights': onRequestEditRights,
|
||||
'onError': onError,
|
||||
'onOutdatedVersion': onOutdatedVersion,
|
||||
};
|
||||
|
||||
<% if (!string.IsNullOrEmpty(History) && !string.IsNullOrEmpty(HistoryData))
|
||||
{ %>
|
||||
config.events['onRequestHistory'] = function () {
|
||||
docEditor.refreshHistory(<%= History %>);
|
||||
};
|
||||
config.events['onRequestHistoryData'] = function (event) {
|
||||
var ver = event.data;
|
||||
var histData = <%= HistoryData %>;
|
||||
docEditor.setHistoryData(histData[ver]);
|
||||
};
|
||||
config.events['onRequestHistoryClose '] = function () {
|
||||
document.location.reload();
|
||||
};
|
||||
<% } %>
|
||||
|
||||
var сonnectEditor = function () {
|
||||
|
||||
docEditor = new DocsAPI.DocEditor("iframeEditor",
|
||||
{
|
||||
width: "100%",
|
||||
height: "100%",
|
||||
|
||||
type: '<%= Request["action"] != "embedded" ? "desktop" : "embedded" %>',
|
||||
documentType: "<%=_Default.DocumentType(FileName) %>",
|
||||
document: {
|
||||
title: fileName,
|
||||
url: "<%= FileUri %>",
|
||||
fileType: fileType,
|
||||
key: "<%= Key %>",
|
||||
|
||||
info: {
|
||||
author: "Me",
|
||||
created: "<%= DateTime.Now.ToShortDateString() %>",
|
||||
},
|
||||
|
||||
permissions: {
|
||||
edit: "<%= _Default.EditedExts.Contains(Path.GetExtension(FileName)) %>" == "True",
|
||||
download: true,
|
||||
}
|
||||
},
|
||||
editorConfig: {
|
||||
mode: '<%= _Default.EditMode && _Default.EditedExts.Contains(Path.GetExtension(FileName)) && Request["action"] != "view" ? "edit" : "view" %>',
|
||||
|
||||
lang: "en",
|
||||
|
||||
callbackUrl: "<%= CallbackUrl %>",
|
||||
|
||||
user: {
|
||||
id: "<%= _Default.CurUserHostAddress(null) %>",
|
||||
name: "John Smith",
|
||||
},
|
||||
|
||||
embedded: {
|
||||
saveUrl: "<%= FileUri %>",
|
||||
embedUrl: "<%= FileUri %>",
|
||||
shareUrl: "<%= FileUri %>",
|
||||
toolbarDocked: "top",
|
||||
},
|
||||
|
||||
customization: {
|
||||
about: true,
|
||||
feedback: true,
|
||||
goback: {
|
||||
url: "<%= _Default.Host %>default.aspx",
|
||||
},
|
||||
},
|
||||
},
|
||||
events: {
|
||||
'onAppReady': onAppReady,
|
||||
'onDocumentStateChange': onDocumentStateChange,
|
||||
'onRequestEditRights': onRequestEditRights,
|
||||
'onError': onError,
|
||||
'onOutdatedVersion': onOutdatedVersion,
|
||||
}
|
||||
});
|
||||
docEditor = new DocsAPI.DocEditor("iframeEditor", config);
|
||||
};
|
||||
|
||||
if (window.addEventListener) {
|
||||
|
||||
@ -25,9 +25,12 @@
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Web;
|
||||
using System.Web.Configuration;
|
||||
using System.Web.Script.Serialization;
|
||||
using System.Web.UI;
|
||||
using ASC.Api.DocumentConverter;
|
||||
|
||||
@ -44,7 +47,12 @@ namespace OnlineEditorsExample
|
||||
|
||||
protected string Key
|
||||
{
|
||||
get { return ServiceConverter.GenerateRevisionId(_Default.CurUserHostAddress(null) + "/" + Path.GetFileName(FileUri) + "/" + File.GetLastWriteTime(_Default.StoragePath(FileName, null)).GetHashCode()); }
|
||||
get
|
||||
{
|
||||
return ServiceConverter.GenerateRevisionId(_Default.CurUserHostAddress(null)
|
||||
+ "/" + Path.GetFileName(FileUri)
|
||||
+ "/" + File.GetLastWriteTime(_Default.StoragePath(FileName, null)).GetHashCode());
|
||||
}
|
||||
}
|
||||
|
||||
protected string DocServiceApiUri
|
||||
@ -52,6 +60,10 @@ namespace OnlineEditorsExample
|
||||
get { return WebConfigurationManager.AppSettings["files.docservice.url.api"] ?? string.Empty; }
|
||||
}
|
||||
|
||||
protected string DocConfig { get; private set; }
|
||||
protected string History { get; private set; }
|
||||
protected string HistoryData { get; private set; }
|
||||
|
||||
public static string CallbackUrl
|
||||
{
|
||||
get
|
||||
@ -73,7 +85,7 @@ namespace OnlineEditorsExample
|
||||
var externalUrl = Request["fileUrl"];
|
||||
if (!string.IsNullOrEmpty(externalUrl))
|
||||
{
|
||||
FileName = _Default.DoUpload(externalUrl);
|
||||
FileName = _Default.DoUpload(externalUrl, Request);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -83,12 +95,190 @@ namespace OnlineEditorsExample
|
||||
var type = Request["type"];
|
||||
if (!string.IsNullOrEmpty(type))
|
||||
{
|
||||
Try(type);
|
||||
Try(type, Request["sample"], Request);
|
||||
Response.Redirect("doceditor.aspx?fileID=" + HttpUtility.UrlEncode(FileName));
|
||||
}
|
||||
|
||||
var ext = Path.GetExtension(FileName);
|
||||
|
||||
var editorsMode = Request["editorsMode"] ?? "edit";
|
||||
|
||||
var canEdit = _Default.EditedExts.Contains(ext);
|
||||
var mode = canEdit && editorsMode != "view" ? "edit" : "view";
|
||||
|
||||
var config = new Dictionary<string, object>
|
||||
{
|
||||
{ "type", Request["editorsType"] ?? "desktop" },
|
||||
{ "documentType", _Default.DocumentType(FileName) },
|
||||
{
|
||||
"document", new Dictionary<string, object>
|
||||
{
|
||||
{ "title", FileName },
|
||||
{ "url", FileUri },
|
||||
{ "fileType", ext.Trim('.') },
|
||||
{ "key", Key },
|
||||
{
|
||||
"info", new Dictionary<string, object>
|
||||
{
|
||||
{ "author", "Me" },
|
||||
{ "created", DateTime.Now.ToShortDateString() }
|
||||
}
|
||||
},
|
||||
{
|
||||
"permissions", new Dictionary<string, object>
|
||||
{
|
||||
{ "comment", editorsMode != "view" && editorsMode != "fillForms" && editorsMode != "embedded" && editorsMode != "blockcontent"},
|
||||
{ "download", true },
|
||||
{ "edit", canEdit && (editorsMode == "edit" || editorsMode == "filter") || editorsMode == "blockcontent" },
|
||||
{ "fillForms", editorsMode != "view" && editorsMode != "comment" && editorsMode != "embedded" && editorsMode != "blockcontent" },
|
||||
{ "modifyFilter", editorsMode != "filter" },
|
||||
{ "modifyContentControl", editorsMode != "blockcontent" },
|
||||
{ "review", editorsMode == "edit" || editorsMode == "review" }
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"editorConfig", new Dictionary<string, object>
|
||||
{
|
||||
{ "mode", mode },
|
||||
{ "lang", Request.Cookies["ulang"]?.Value ?? "en" },
|
||||
{ "callbackUrl", CallbackUrl },
|
||||
{
|
||||
"user", new Dictionary<string, object>
|
||||
{
|
||||
{ "id", Request.Cookies["uid"]?.Value ?? "uid-1" },
|
||||
{ "name", Request.Cookies["uname"]?.Value ?? "John Smith" }
|
||||
}
|
||||
},
|
||||
{
|
||||
"embedded", new Dictionary<string, object>
|
||||
{
|
||||
{ "saveUrl", FileUri },
|
||||
{ "embedUrl", FileUri },
|
||||
{ "shareUrl", FileUri },
|
||||
{ "toolbarDocked", "top" }
|
||||
}
|
||||
},
|
||||
{
|
||||
"customization", new Dictionary<string, object>
|
||||
{
|
||||
{ "about", true },
|
||||
{ "feedback", true },
|
||||
{
|
||||
"goback", new Dictionary<string, object>
|
||||
{
|
||||
{ "url", _Default.Host + "default.aspx" }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if (JwtManager.Enabled)
|
||||
{
|
||||
var token = JwtManager.Encode(config);
|
||||
config.Add("token", token);
|
||||
}
|
||||
|
||||
var jss = new JavaScriptSerializer();
|
||||
|
||||
DocConfig = jss.Serialize(config);
|
||||
|
||||
try
|
||||
{
|
||||
GetHistory(out var hist, out var histData);
|
||||
if (hist != null && histData != null)
|
||||
{
|
||||
History = jss.Serialize(hist);
|
||||
HistoryData = jss.Serialize(histData);
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
||||
private void GetHistory(out Dictionary<string, object> history, out Dictionary<string, object> historyData)
|
||||
{
|
||||
var jss = new JavaScriptSerializer();
|
||||
var histDir = _Default.HistoryDir(_Default.StoragePath(FileName, null));
|
||||
|
||||
history = null;
|
||||
historyData = null;
|
||||
|
||||
if (_Default.GetFileVersion(histDir) > 0)
|
||||
{
|
||||
var currentVersion = _Default.GetFileVersion(histDir);
|
||||
var hist = new List<Dictionary<string, object>>();
|
||||
var histData = new Dictionary<string, object>();
|
||||
|
||||
for (var i = 0; i <= currentVersion; i++)
|
||||
{
|
||||
var obj = new Dictionary<string, object>();
|
||||
var dataObj = new Dictionary<string, object>();
|
||||
var verDir = _Default.VersionDir(histDir, i + 1);
|
||||
|
||||
var key = i == currentVersion ? Key : File.ReadAllText(Path.Combine(verDir, "key.txt"));
|
||||
|
||||
obj.Add("key", key);
|
||||
obj.Add("version", i);
|
||||
|
||||
if (i == 0)
|
||||
{
|
||||
var infoPath = Path.Combine(histDir, "createdInfo.json");
|
||||
|
||||
if (File.Exists(infoPath)) {
|
||||
var info = jss.Deserialize<Dictionary<string, object>>(File.ReadAllText(infoPath));
|
||||
obj.Add("created", info["created"]);
|
||||
obj.Add("user", new Dictionary<string, object>() {
|
||||
{ "id", info["id"] },
|
||||
{ "name", info["name"] },
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
dataObj.Add("key", key);
|
||||
dataObj.Add("url", i == currentVersion ? FileUri : MakePublicUrl(Directory.GetFiles(verDir, "prev.*")[0]));
|
||||
dataObj.Add("version", i);
|
||||
if (i > 0)
|
||||
{
|
||||
var changes = jss.Deserialize<Dictionary<string, object>>(File.ReadAllText(Path.Combine(_Default.VersionDir(histDir, i), "changes.json")));
|
||||
var change = ((Dictionary<string, object>)((ArrayList)changes["changes"])[0]);
|
||||
|
||||
obj.Add("changes", changes["changes"]);
|
||||
obj.Add("serverVersion", changes["serverVersion"]);
|
||||
obj.Add("created", change["created"]);
|
||||
obj.Add("user", change["user"]);
|
||||
|
||||
var prev = (Dictionary<string, object>)histData[(i - 1).ToString()];
|
||||
dataObj.Add("previous", new Dictionary<string, object>() {
|
||||
{ "key", prev["key"] },
|
||||
{ "url", prev["url"] },
|
||||
});
|
||||
dataObj.Add("changesUrl", MakePublicUrl(Path.Combine(_Default.VersionDir(histDir, i), "diff.zip")));
|
||||
}
|
||||
|
||||
hist.Add(obj);
|
||||
histData.Add(i.ToString(), dataObj);
|
||||
}
|
||||
|
||||
history = new Dictionary<string, object>()
|
||||
{
|
||||
{ "currentVersion", currentVersion },
|
||||
{ "history", hist }
|
||||
};
|
||||
historyData = histData;
|
||||
}
|
||||
}
|
||||
|
||||
private static void Try(string type)
|
||||
private string MakePublicUrl(string fullPath)
|
||||
{
|
||||
var root = HttpRuntime.AppDomainAppPath + WebConfigurationManager.AppSettings["storage-path"];
|
||||
return _Default.Host + fullPath.Substring(root.Length).Replace(Path.DirectorySeparatorChar, '/');
|
||||
}
|
||||
|
||||
private static void Try(string type, string sample, HttpRequest request)
|
||||
{
|
||||
string ext;
|
||||
switch (type)
|
||||
@ -105,10 +295,19 @@ namespace OnlineEditorsExample
|
||||
default:
|
||||
return;
|
||||
}
|
||||
var demoName = "demo" + ext;
|
||||
var demoName = (string.IsNullOrEmpty(sample) ? "new" : "demo") + ext;
|
||||
FileName = _Default.GetCorrectName(demoName);
|
||||
|
||||
File.Copy(HttpRuntime.AppDomainAppPath + "app_data/" + demoName, _Default.StoragePath(FileName, null));
|
||||
var filePath = _Default.StoragePath(FileName, null);
|
||||
File.Copy(HttpRuntime.AppDomainAppPath + "app_data/" + demoName, filePath);
|
||||
|
||||
var histDir = _Default.HistoryDir(filePath);
|
||||
Directory.CreateDirectory(histDir);
|
||||
File.WriteAllText(Path.Combine(histDir, "createdInfo.json"), new JavaScriptSerializer().Serialize(new Dictionary<string, object> {
|
||||
{ "created", DateTime.Now.ToString() },
|
||||
{ "id", request.Cookies["uid"]?.Value ?? "uid-1" },
|
||||
{ "name", request.Cookies["uname"]?.Value ?? "John Smith" }
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -24,14 +24,16 @@
|
||||
*
|
||||
*/
|
||||
|
||||
using OnlineEditorsExample;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Web.Configuration;
|
||||
using System.Web.Helpers;
|
||||
using OnlineEditorsExample;
|
||||
using System.Web.Script.Serialization;
|
||||
|
||||
namespace ASC.Api.DocumentConverter
|
||||
{
|
||||
@ -108,15 +110,30 @@ namespace ASC.Api.DocumentConverter
|
||||
request.Accept = "application/json";
|
||||
request.Timeout = ConvertTimeout;
|
||||
|
||||
var bodyString = string.Format("{{\"async\": {0},\"filetype\": \"{1}\",\"key\": \"{2}\",\"outputtype\": \"{3}\",\"title\": \"{4}\",\"url\": \"{5}\"}}",
|
||||
isAsync.ToString().ToLower(),
|
||||
fromExtension.Trim('.'),
|
||||
documentRevisionId,
|
||||
toExtension.Trim('.'),
|
||||
title,
|
||||
documentUri);
|
||||
var body = new Dictionary<string, object>() {
|
||||
{ "async", isAsync },
|
||||
{ "filetype", fromExtension.Trim('.') },
|
||||
{ "key", documentRevisionId },
|
||||
{ "outputtype", toExtension.Trim('.') },
|
||||
{ "title", title },
|
||||
{ "url", documentUri }
|
||||
};
|
||||
|
||||
var bytes = Encoding.UTF8.GetBytes(bodyString);
|
||||
if (JwtManager.Enabled)
|
||||
{
|
||||
var payload = new Dictionary<string, object>
|
||||
{
|
||||
{ "payload", body }
|
||||
};
|
||||
|
||||
var payloadToken = JwtManager.Encode(payload);
|
||||
var bodyToken = JwtManager.Encode(body);
|
||||
request.Headers.Add("Authorization", "Bearer " + payloadToken);
|
||||
|
||||
body.Add("token", bodyToken);
|
||||
}
|
||||
|
||||
var bytes = Encoding.UTF8.GetBytes(new JavaScriptSerializer().Serialize(body));
|
||||
request.ContentLength = bytes.Length;
|
||||
using (var requestStream = request.GetRequestStream())
|
||||
{
|
||||
|
||||
113
web/documentserver-example/csharp/JwtManager.cs
Normal file
@ -0,0 +1,113 @@
|
||||
/*
|
||||
*
|
||||
* (c) Copyright Ascensio System SIA 2019
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using System.Web.Configuration;
|
||||
using System.Web.Script.Serialization;
|
||||
|
||||
namespace OnlineEditorsExample
|
||||
{
|
||||
public static class JwtManager
|
||||
{
|
||||
private static readonly string Secret;
|
||||
public static readonly bool Enabled;
|
||||
|
||||
private static readonly JavaScriptSerializer Serializer;
|
||||
|
||||
static JwtManager()
|
||||
{
|
||||
Secret = WebConfigurationManager.AppSettings["files.docservice.secret"] ?? "";
|
||||
Enabled = !string.IsNullOrEmpty(Secret);
|
||||
Serializer = new JavaScriptSerializer();
|
||||
}
|
||||
|
||||
public static string Encode(IDictionary<string, object> payload)
|
||||
{
|
||||
var header = new Dictionary<string, object>
|
||||
{
|
||||
{ "alg", "HS256" },
|
||||
{ "typ", "JWT" }
|
||||
};
|
||||
|
||||
var encHeader = Base64UrlEncode(Serializer.Serialize(header));
|
||||
var encPayload = Base64UrlEncode(Serializer.Serialize(payload));
|
||||
var hashSum = Base64UrlEncode(CalculateHash(encHeader, encPayload));
|
||||
|
||||
return string.Format("{0}.{1}.{2}", encHeader, encPayload, hashSum);
|
||||
}
|
||||
|
||||
public static string Decode(string token)
|
||||
{
|
||||
if (!Enabled || string.IsNullOrEmpty(token)) return "";
|
||||
|
||||
var split = token.Split('.');
|
||||
if (split.Length != 3) return "";
|
||||
|
||||
var hashSum = Base64UrlEncode(CalculateHash(split[0], split[1]));
|
||||
if (hashSum != split[2]) return "";
|
||||
return Base64UrlDecode(split[1]);
|
||||
}
|
||||
|
||||
private static byte[] CalculateHash(string encHeader, string encPayload)
|
||||
{
|
||||
using (var hasher = new HMACSHA256(Encoding.UTF8.GetBytes(Secret)))
|
||||
{
|
||||
var bytes = Encoding.UTF8.GetBytes(string.Format("{0}.{1}", encHeader, encPayload));
|
||||
return hasher.ComputeHash(bytes);
|
||||
}
|
||||
}
|
||||
|
||||
private static string Base64UrlEncode(string str)
|
||||
{
|
||||
return Base64UrlEncode(Encoding.UTF8.GetBytes(str));
|
||||
}
|
||||
|
||||
private static string Base64UrlEncode(byte[] bytes)
|
||||
{
|
||||
return Convert.ToBase64String(bytes)
|
||||
.TrimEnd('=').Replace('+', '-').Replace('/', '_');
|
||||
}
|
||||
|
||||
private static string Base64UrlDecode(string payload)
|
||||
{
|
||||
var b64 = payload.Replace('_', '/').Replace('-', '+');
|
||||
switch (b64.Length%4)
|
||||
{
|
||||
case 2:
|
||||
b64 += "==";
|
||||
break;
|
||||
case 3:
|
||||
b64 += "=";
|
||||
break;
|
||||
}
|
||||
var bytes = Convert.FromBase64String(b64);
|
||||
return Encoding.UTF8.GetString(bytes);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -52,12 +52,23 @@
|
||||
<Reference Include="System.Web.Services" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="App_Themes\images\block-content-24.png" />
|
||||
<Content Include="App_Themes\images\comment-24.png" />
|
||||
<Content Include="App_Themes\images\delete-24.png" />
|
||||
<Content Include="App_Themes\images\desktop-24.png" />
|
||||
<Content Include="App_Themes\images\download-24.png" />
|
||||
<Content Include="App_Themes\images\embeded-24.png" />
|
||||
<Content Include="App_Themes\images\file_docx.png" />
|
||||
<Content Include="App_Themes\images\file_pptx.png" />
|
||||
<Content Include="App_Themes\images\file_upload.png" />
|
||||
<Content Include="App_Themes\images\file_xlsx.png" />
|
||||
<Content Include="App_Themes\images\fill-forms-24.png" />
|
||||
<Content Include="App_Themes\images\filter-24.png" />
|
||||
<Content Include="App_Themes\images\icon_docx.png" />
|
||||
<Content Include="App_Themes\images\icon_pptx.png" />
|
||||
<Content Include="App_Themes\images\icon_xlsx.png" />
|
||||
<Content Include="App_Themes\images\mobile-24.png" />
|
||||
<Content Include="App_Themes\images\review-24.png" />
|
||||
<Content Include="LICENSE.txt" />
|
||||
<Content Include="licenses\MIT-LICENSE.txt" />
|
||||
<Content Include="ReadMe.txt" />
|
||||
@ -72,6 +83,7 @@
|
||||
<DependentUpon>DocEditor.aspx</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="DocumentConverter.cs" />
|
||||
<Compile Include="JwtManager.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Default.aspx.cs">
|
||||
<DependentUpon>Default.aspx</DependentUpon>
|
||||
@ -116,6 +128,11 @@
|
||||
<Content Include="App_Data\demo.pptx" />
|
||||
<Content Include="App_Data\demo.xlsx" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="App_Data\new.docx" />
|
||||
<Content Include="App_Data\new.pptx" />
|
||||
<Content Include="App_Data\new.xlsx" />
|
||||
</ItemGroup>
|
||||
<PropertyGroup>
|
||||
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">10.0</VisualStudioVersion>
|
||||
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
|
||||
|
||||
@ -24,14 +24,15 @@
|
||||
*
|
||||
*/
|
||||
|
||||
using ASC.Api.DocumentConverter;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Web;
|
||||
using System.Web.Script.Serialization;
|
||||
using System.Web.Services;
|
||||
using ASC.Api.DocumentConverter;
|
||||
|
||||
namespace OnlineEditorsExample
|
||||
{
|
||||
@ -52,6 +53,9 @@ namespace OnlineEditorsExample
|
||||
case "track":
|
||||
Track(context);
|
||||
break;
|
||||
case "remove":
|
||||
Remove(context);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -112,6 +116,24 @@ namespace OnlineEditorsExample
|
||||
var jss = new JavaScriptSerializer();
|
||||
if (string.IsNullOrEmpty(body)) return;
|
||||
var fileData = jss.Deserialize<Dictionary<string, object>>(body);
|
||||
|
||||
if (JwtManager.Enabled)
|
||||
{
|
||||
if (fileData.ContainsKey("token"))
|
||||
{
|
||||
fileData = jss.Deserialize<Dictionary<string, object>>(JwtManager.Decode(fileData["token"].ToString()));
|
||||
}
|
||||
else if (context.Request.Headers.AllKeys.Contains("Authorization", StringComparer.InvariantCultureIgnoreCase))
|
||||
{
|
||||
var headerToken = context.Request.Headers.Get("Authorization").Substring("Bearer ".Length);
|
||||
fileData = (Dictionary<string, object>)jss.Deserialize<Dictionary<string, object>>(JwtManager.Decode(headerToken))["payload"];
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception("Expected JWT");
|
||||
}
|
||||
}
|
||||
|
||||
var status = (TrackerStatus) (int) fileData["status"];
|
||||
|
||||
switch (status)
|
||||
@ -138,8 +160,6 @@ namespace OnlineEditorsExample
|
||||
}
|
||||
}
|
||||
|
||||
var req = (HttpWebRequest) WebRequest.Create(downloadUri);
|
||||
|
||||
// hack. http://ubuntuforums.org/showthread.php?t=1841740
|
||||
if (_Default.IsMono)
|
||||
{
|
||||
@ -149,22 +169,29 @@ namespace OnlineEditorsExample
|
||||
var saved = 1;
|
||||
try
|
||||
{
|
||||
using (var stream = req.GetResponse().GetResponseStream())
|
||||
{
|
||||
if (stream == null) throw new Exception("stream is null");
|
||||
const int bufferSize = 4096;
|
||||
var storagePath = _Default.StoragePath(fileName, userAddress);
|
||||
var histDir = _Default.HistoryDir(storagePath);
|
||||
var versionDir = _Default.VersionDir(histDir, _Default.GetFileVersion(histDir) + 1);
|
||||
|
||||
var storagePath = _Default.StoragePath(fileName, userAddress);
|
||||
using (var fs = File.Open(storagePath, FileMode.Create))
|
||||
{
|
||||
var buffer = new byte[bufferSize];
|
||||
int readed;
|
||||
while ((readed = stream.Read(buffer, 0, bufferSize)) != 0)
|
||||
{
|
||||
fs.Write(buffer, 0, readed);
|
||||
}
|
||||
}
|
||||
if (!Directory.Exists(versionDir)) Directory.CreateDirectory(versionDir);
|
||||
|
||||
File.Copy(storagePath, Path.Combine(versionDir, "prev" + curExt));
|
||||
|
||||
DownloadToFile(downloadUri, _Default.StoragePath(fileName, userAddress));
|
||||
DownloadToFile((string)fileData["changesurl"], Path.Combine(versionDir, "diff.zip"));
|
||||
|
||||
var hist = fileData.ContainsKey("changeshistory") ? (string)fileData["changeshistory"] : null;
|
||||
if (string.IsNullOrEmpty(hist) && fileData.ContainsKey("history"))
|
||||
{
|
||||
hist = jss.Serialize(fileData["history"]);
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(hist))
|
||||
{
|
||||
File.WriteAllText(Path.Combine(versionDir, "changes.json"), hist);
|
||||
}
|
||||
|
||||
File.WriteAllText(Path.Combine(versionDir, "key.txt"), (string)fileData["key"]);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
@ -176,6 +203,49 @@ namespace OnlineEditorsExample
|
||||
context.Response.Write("{\"error\":0}");
|
||||
}
|
||||
|
||||
private static void Remove(HttpContext context)
|
||||
{
|
||||
context.Response.ContentType = "text/plain";
|
||||
try
|
||||
{
|
||||
var fileName = context.Request["fileName"];
|
||||
var path = _Default.StoragePath(fileName, HttpUtility.UrlEncode(HttpContext.Current.Request.UserHostAddress));
|
||||
var histDir = _Default.HistoryDir(path);
|
||||
|
||||
if (File.Exists(path)) File.Delete(path);
|
||||
if (Directory.Exists(histDir)) Directory.Delete(histDir, true);
|
||||
|
||||
context.Response.Write("{ \"success\": true }");
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
context.Response.Write("{ \"error\": \"" + e.Message + "\"}");
|
||||
}
|
||||
}
|
||||
|
||||
private static void DownloadToFile(string url, string path)
|
||||
{
|
||||
if (string.IsNullOrEmpty(url)) throw new ArgumentException("url");
|
||||
if (string.IsNullOrEmpty(path)) throw new ArgumentException("path");
|
||||
|
||||
var req = (HttpWebRequest)WebRequest.Create(url);
|
||||
using (var stream = req.GetResponse().GetResponseStream())
|
||||
{
|
||||
if (stream == null) throw new Exception("stream is null");
|
||||
const int bufferSize = 4096;
|
||||
|
||||
using (var fs = File.Open(path, FileMode.Create))
|
||||
{
|
||||
var buffer = new byte[bufferSize];
|
||||
int readed;
|
||||
while ((readed = stream.Read(buffer, 0, bufferSize)) != 0)
|
||||
{
|
||||
fs.Write(buffer, 0, readed);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsReusable
|
||||
{
|
||||
get { return false; }
|
||||
|
||||
|
Before Width: | Height: | Size: 466 B After Width: | Height: | Size: 144 KiB |
@ -70,6 +70,8 @@ if (typeof jQuery != "undefined") {
|
||||
checkConvert();
|
||||
}
|
||||
});
|
||||
|
||||
initSelectors();
|
||||
});
|
||||
|
||||
var timer = null;
|
||||
@ -91,11 +93,6 @@ if (typeof jQuery != "undefined") {
|
||||
return;
|
||||
}
|
||||
|
||||
if (jq("#checkOriginalFormat").is(":checked")) {
|
||||
loadScripts();
|
||||
return;
|
||||
}
|
||||
|
||||
timer = setTimeout(function () {
|
||||
var requestAddress = "webeditor.ashx"
|
||||
+ "?type=convert"
|
||||
@ -163,6 +160,34 @@ if (typeof jQuery != "undefined") {
|
||||
}
|
||||
};
|
||||
|
||||
var initSelectors = function () {
|
||||
var userSel = jq("#user");
|
||||
var langSel = jq("#language");
|
||||
|
||||
function getCookie(name) {
|
||||
let matches = document.cookie.match(new RegExp(
|
||||
"(?:^|; )" + name.replace(/([\.$?*|{}\(\)\[\]\\\/\+^])/g, '\\$1') + "=([^;]*)"
|
||||
));
|
||||
return matches ? decodeURIComponent(matches[1]) : null;
|
||||
}
|
||||
function setCookie(name, value) {
|
||||
document.cookie = name + "=" + value + "; expires=" + new Date(Date.now() + 1000 * 60 * 60 * 24 * 7).toUTCString(); //week
|
||||
}
|
||||
|
||||
var userId = getCookie("uid");
|
||||
if (userId) userSel.val(userId);
|
||||
var langId = getCookie("ulang");
|
||||
if (langId) langSel.val(langId);
|
||||
|
||||
userSel.on("change", function () {
|
||||
setCookie("uid", userSel.val());
|
||||
setCookie("uname", userSel.find("option:selected").text())
|
||||
});
|
||||
langSel.on("change", function () {
|
||||
setCookie("ulang", langSel.val());
|
||||
});
|
||||
};
|
||||
|
||||
jq(document).on("click", "#beginEdit:not(.disable)", function () {
|
||||
var fileId = encodeURIComponent(jq('#hiddenFileName').val());
|
||||
var url = "doceditor.aspx?fileID=" + fileId;
|
||||
@ -195,6 +220,32 @@ if (typeof jQuery != "undefined") {
|
||||
jq.unblockUI();
|
||||
});
|
||||
|
||||
jq(document).on("click", ".try-editor", function (e) {
|
||||
var url = "doceditor.aspx?type=" + e.target.attributes["data-type"].value;
|
||||
if (jq("#createSample").is(":checked")) {
|
||||
url += "&sample=true";
|
||||
}
|
||||
var w = window.open(url, "_blank");
|
||||
w.onload = function () {
|
||||
window.location.reload();
|
||||
}
|
||||
});
|
||||
|
||||
jq(document).on("click", ".delete-file", function () {
|
||||
var requestAddress = "webeditor.ashx"
|
||||
+ "?type=remove"
|
||||
+ "&filename=" + encodeURIComponent(jq(this).attr("data-filename"));
|
||||
|
||||
jq.ajax({
|
||||
async: true,
|
||||
contentType: "text/xml",
|
||||
url: requestAddress,
|
||||
complete: function (data) {
|
||||
document.location.reload();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
jq.dropdownToggle({
|
||||
switcherSelector: ".question",
|
||||
dropdownID: "hint"
|
||||
|
||||
@ -9,6 +9,7 @@
|
||||
<add key="files.docservice.edited-docs" value=".docx|.xlsx|.csv|.pptx|.txt"/>
|
||||
<add key="files.docservice.convert-docs" value=".docm|.dotx|.dotm|.dot|.doc|.odt|.fodt|.ott|.xlsm|.xltx|.xltm|.xlt|.xls|.ods|.fods|.ots|.pptm|.ppt|.ppsx|.ppsm|.pps|.potx|.potm|.pot|.odp|.fodp|.otp|.rtf|.mht|.html|.htm|.epub"/>
|
||||
<add key="files.docservice.timeout" value="120000" />
|
||||
<add key="files.docservice.secret" value="" />
|
||||
|
||||
<add key="files.docservice.url.converter" value="https://documentserver/ConvertService.ashx"/>
|
||||
<add key="files.docservice.url.api" value="https://documentserver/web-apps/apps/api/documents/api.js"/>
|
||||
|
||||
@ -24,12 +24,14 @@
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
package controllers;
|
||||
|
||||
import helpers.ConfigManager;
|
||||
import helpers.CookieManager;
|
||||
import helpers.DocumentManager;
|
||||
import java.io.IOException;
|
||||
import java.net.URLEncoder;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.annotation.WebServlet;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
@ -47,12 +49,19 @@ public class EditorServlet extends HttpServlet
|
||||
|
||||
String fileName = request.getParameter("fileName");
|
||||
String fileExt = request.getParameter("fileExt");
|
||||
String sample = request.getParameter("sample");
|
||||
|
||||
Boolean sampleData = (sample == null || sample.isEmpty()) ? false : sample.toLowerCase().equals("true");
|
||||
|
||||
CookieManager cm = new CookieManager(request);
|
||||
|
||||
if (fileExt != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
fileName = DocumentManager.CreateDemo(fileExt);
|
||||
fileName = DocumentManager.CreateDemo(fileExt, sampleData, cm.getCookie("uid"), cm.getCookie("uname"));
|
||||
response.sendRedirect("EditorServlet?fileName=" + URLEncoder.encode(fileName, "UTF-8"));
|
||||
return;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@ -60,11 +69,8 @@ public class EditorServlet extends HttpServlet
|
||||
}
|
||||
}
|
||||
|
||||
FileModel file = new FileModel(fileName);
|
||||
if ("embedded".equals(request.getParameter("mode")))
|
||||
file.InitDesktop();
|
||||
if ("view".equals(request.getParameter("mode")))
|
||||
file.editorConfig.mode = "view";
|
||||
FileModel file = new FileModel(fileName, cm.getCookie("ulang"), cm.getCookie("uid"), cm.getCookie("uname"));
|
||||
file.changeType(request.getParameter("mode"), request.getParameter("type"));
|
||||
|
||||
if (DocumentManager.TokenEnabled())
|
||||
{
|
||||
|
||||
@ -24,14 +24,15 @@
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
package controllers;
|
||||
|
||||
import helpers.ConfigManager;
|
||||
import helpers.CookieManager;
|
||||
import helpers.DocumentManager;
|
||||
import helpers.ServiceConverter;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.PrintWriter;
|
||||
@ -82,6 +83,9 @@ public class IndexServlet extends HttpServlet
|
||||
case "track":
|
||||
Track(request, response, writer);
|
||||
break;
|
||||
case "remove":
|
||||
Remove(request, response, writer);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -136,10 +140,13 @@ public class IndexServlet extends HttpServlet
|
||||
out.flush();
|
||||
}
|
||||
|
||||
CookieManager cm = new CookieManager(request);
|
||||
DocumentManager.CreateMeta(fileName, cm.getCookie("uid"), cm.getCookie("uname"));
|
||||
|
||||
writer.write("{ \"filename\": \"" + fileName + "\"}");
|
||||
|
||||
}
|
||||
catch (IOException | ServletException e)
|
||||
catch (Exception e)
|
||||
{
|
||||
writer.write("{ \"error\": \"" + e.getMessage() + "\"}");
|
||||
}
|
||||
@ -200,6 +207,9 @@ public class IndexServlet extends HttpServlet
|
||||
//sourceFile.delete();
|
||||
|
||||
fileName = correctName;
|
||||
|
||||
CookieManager cm = new CookieManager(request);
|
||||
DocumentManager.CreateMeta(fileName, cm.getCookie("uid"), cm.getCookie("uname"));
|
||||
}
|
||||
|
||||
writer.write("{ \"filename\" : \"" + fileName + "\"}");
|
||||
@ -254,20 +264,29 @@ public class IndexServlet extends HttpServlet
|
||||
|
||||
int status;
|
||||
String downloadUri;
|
||||
String changesUri;
|
||||
String key;
|
||||
|
||||
if (DocumentManager.TokenEnabled())
|
||||
{
|
||||
String token = (String) jsonObj.get("token");
|
||||
|
||||
if (token == null) {
|
||||
String header = (String) request.getHeader(DocumentJwtHeader == "" ? "Authorization" : DocumentJwtHeader);
|
||||
token = header.startsWith("Bearer ") ? header.substring(7) : header;
|
||||
String header = (String) request.getHeader(DocumentJwtHeader == null || DocumentJwtHeader.isEmpty() ? "Authorization" : DocumentJwtHeader);
|
||||
if (header != null && !header.isEmpty()) {
|
||||
token = header.startsWith("Bearer ") ? header.substring(7) : header;
|
||||
}
|
||||
}
|
||||
|
||||
if (token == null || token.isEmpty()) {
|
||||
writer.write("{\"error\":1,\"message\":\"JWT expected\"}");
|
||||
return;
|
||||
}
|
||||
|
||||
JWT jwt = DocumentManager.ReadToken(token);
|
||||
if (jwt == null)
|
||||
{
|
||||
writer.write("JWT.parse error");
|
||||
writer.write("{\"error\":1,\"message\":\"JWT validation failed\"}");
|
||||
return;
|
||||
}
|
||||
|
||||
@ -279,18 +298,22 @@ public class IndexServlet extends HttpServlet
|
||||
jwt.claims = payload;
|
||||
}
|
||||
catch (Exception ex) {
|
||||
writer.write("Wrong payload");
|
||||
writer.write("{\"error\":1,\"message\":\"Wrong payload\"}");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
status = jwt.getInteger("status");
|
||||
downloadUri = jwt.getString("url");
|
||||
changesUri = jwt.getString("changesurl");
|
||||
key = jwt.getString("key");
|
||||
}
|
||||
else
|
||||
{
|
||||
status = (int) jsonObj.get("status");
|
||||
status = Math.toIntExact((long) jsonObj.get("status"));
|
||||
downloadUri = (String) jsonObj.get("url");
|
||||
changesUri = (String) jsonObj.get("changesurl");
|
||||
key = (String) jsonObj.get("key");
|
||||
}
|
||||
|
||||
int saved = 0;
|
||||
@ -298,30 +321,31 @@ public class IndexServlet extends HttpServlet
|
||||
{
|
||||
try
|
||||
{
|
||||
URL url = new URL(downloadUri);
|
||||
java.net.HttpURLConnection connection = (java.net.HttpURLConnection) url.openConnection();
|
||||
InputStream stream = connection.getInputStream();
|
||||
String histDir = DocumentManager.HistoryDir(storagePath);
|
||||
String versionDir = DocumentManager.VersionDir(histDir, DocumentManager.GetFileVersion(histDir) + 1);
|
||||
File ver = new File(versionDir);
|
||||
File toSave = new File(storagePath);
|
||||
|
||||
if (stream == null)
|
||||
{
|
||||
throw new Exception("Stream is null");
|
||||
if (!ver.exists()) ver.mkdirs();
|
||||
|
||||
toSave.renameTo(new File(versionDir + File.separator + "prev" + FileUtility.GetFileExtension(fileName)));
|
||||
|
||||
downloadToFile(downloadUri, toSave);
|
||||
downloadToFile(changesUri, new File(versionDir + File.separator + "diff.zip"));
|
||||
|
||||
String history = (String) jsonObj.get("changeshistory");
|
||||
if (history == null && jsonObj.containsKey("history")) {
|
||||
history = ((JSONObject) jsonObj.get("history")).toJSONString();
|
||||
}
|
||||
if (history != null && !history.isEmpty()) {
|
||||
FileWriter fw = new FileWriter(new File(versionDir + File.separator + "changes.json"));
|
||||
fw.write(history);
|
||||
fw.close();
|
||||
}
|
||||
|
||||
File savedFile = new File(storagePath);
|
||||
try (FileOutputStream out = new FileOutputStream(savedFile))
|
||||
{
|
||||
int read;
|
||||
final byte[] bytes = new byte[1024];
|
||||
while ((read = stream.read(bytes)) != -1)
|
||||
{
|
||||
out.write(bytes, 0, read);
|
||||
}
|
||||
|
||||
out.flush();
|
||||
}
|
||||
|
||||
connection.disconnect();
|
||||
|
||||
FileWriter fw = new FileWriter(new File(versionDir + File.separator + "key.txt"));
|
||||
fw.write(key);
|
||||
fw.close();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@ -332,6 +356,63 @@ public class IndexServlet extends HttpServlet
|
||||
writer.write("{\"error\":" + saved + "}");
|
||||
}
|
||||
|
||||
private static void Remove(HttpServletRequest request, HttpServletResponse response, PrintWriter writer)
|
||||
{
|
||||
try
|
||||
{
|
||||
String fileName = request.getParameter("filename");
|
||||
String path = DocumentManager.StoragePath(fileName, null);
|
||||
|
||||
File f = new File(path);
|
||||
delete(f);
|
||||
|
||||
File hist = new File(DocumentManager.HistoryDir(path));
|
||||
delete(hist);
|
||||
|
||||
writer.write("{ \"success\": true }");
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
writer.write("{ \"error\": \"" + e.getMessage() + "\"}");
|
||||
}
|
||||
}
|
||||
|
||||
private static void delete(File f) throws Exception {
|
||||
if (f.isDirectory()) {
|
||||
for (File c : f.listFiles())
|
||||
delete(c);
|
||||
}
|
||||
if (!f.delete())
|
||||
throw new Exception("Failed to delete file: " + f);
|
||||
}
|
||||
|
||||
private static void downloadToFile(String url, File file) throws Exception {
|
||||
if (url == null || url.isEmpty()) throw new Exception("argument url");
|
||||
if (file == null) throw new Exception("argument path");
|
||||
|
||||
URL uri = new URL(url);
|
||||
java.net.HttpURLConnection connection = (java.net.HttpURLConnection) uri.openConnection();
|
||||
InputStream stream = connection.getInputStream();
|
||||
|
||||
if (stream == null)
|
||||
{
|
||||
throw new Exception("Stream is null");
|
||||
}
|
||||
|
||||
try (FileOutputStream out = new FileOutputStream(file))
|
||||
{
|
||||
int read;
|
||||
final byte[] bytes = new byte[1024];
|
||||
while ((read = stream.read(bytes)) != -1)
|
||||
{
|
||||
out.write(bytes, 0, read);
|
||||
}
|
||||
|
||||
out.flush();
|
||||
}
|
||||
|
||||
connection.disconnect();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
|
||||
|
||||
@ -24,25 +24,35 @@
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
package entities;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Scanner;
|
||||
import java.util.Set;
|
||||
|
||||
import helpers.DocumentManager;
|
||||
import helpers.ServiceConverter;
|
||||
import helpers.FileUtility;
|
||||
import com.google.gson.Gson;
|
||||
|
||||
import org.json.simple.JSONArray;
|
||||
import org.json.simple.JSONObject;
|
||||
import org.json.simple.parser.JSONParser;
|
||||
|
||||
public class FileModel
|
||||
{
|
||||
public String type = "desktop";
|
||||
public String mode = "edit";
|
||||
public String documentType;
|
||||
public Document document;
|
||||
public EditorConfig editorConfig;
|
||||
public String token;
|
||||
|
||||
public FileModel(String fileName)
|
||||
public FileModel(String fileName, String lang, String uid, String uname)
|
||||
{
|
||||
if (fileName == null) fileName = "";
|
||||
fileName = fileName.trim();
|
||||
@ -53,21 +63,36 @@ public class FileModel
|
||||
document.title = fileName;
|
||||
document.url = DocumentManager.GetFileUri(fileName);
|
||||
document.fileType = FileUtility.GetFileExtension(fileName).replace(".", "");
|
||||
String userId = DocumentManager.CurUserHostAddress(null);
|
||||
document.key = ServiceConverter.GenerateRevisionId(userId + "/" + fileName);
|
||||
document.key = ServiceConverter.GenerateRevisionId(DocumentManager.CurUserHostAddress(null) + "/" + fileName + "/" + Long.toString(new File(DocumentManager.StoragePath(fileName, null)).lastModified()));
|
||||
|
||||
editorConfig = new EditorConfig();
|
||||
if (!DocumentManager.GetEditedExts().contains(FileUtility.GetFileExtension(fileName)))
|
||||
editorConfig.mode = "view";
|
||||
editorConfig.callbackUrl = DocumentManager.GetCallback(fileName);
|
||||
editorConfig.user.id = userId;
|
||||
if (lang != null) editorConfig.lang = lang;
|
||||
|
||||
if (uid != null) editorConfig.user.id = uid;
|
||||
if (uname != null) editorConfig.user.name = uname;
|
||||
|
||||
editorConfig.customization.goback.url = DocumentManager.GetServerUrl() + "/IndexServlet";
|
||||
|
||||
changeType(mode, type);
|
||||
}
|
||||
|
||||
public void changeType(String _mode, String _type)
|
||||
{
|
||||
if (_mode != null) mode = _mode;
|
||||
if (_type != null) type = _type;
|
||||
|
||||
Boolean canEdit = DocumentManager.GetEditedExts().contains(FileUtility.GetFileExtension(document.title));
|
||||
|
||||
editorConfig.mode = canEdit && !mode.equals("view") ? "edit" : "view";
|
||||
|
||||
document.permissions = new Permissions(mode, type, canEdit);
|
||||
|
||||
if (type.equals("embedded")) InitDesktop();
|
||||
}
|
||||
|
||||
public void InitDesktop()
|
||||
{
|
||||
type = "embedded";
|
||||
editorConfig.InitDesktop(document.url);
|
||||
}
|
||||
|
||||
@ -82,18 +107,129 @@ public class FileModel
|
||||
token = DocumentManager.CreateToken(map);
|
||||
}
|
||||
|
||||
public String[] GetHistory()
|
||||
{
|
||||
JSONParser parser = new JSONParser();
|
||||
String histDir = DocumentManager.HistoryDir(DocumentManager.StoragePath(document.title, null));
|
||||
if (DocumentManager.GetFileVersion(histDir) > 0) {
|
||||
Integer curVer = DocumentManager.GetFileVersion(histDir);
|
||||
|
||||
Set<Object> hist = new HashSet<Object>();
|
||||
Map<String, Object> histData = new HashMap<String, Object>();
|
||||
|
||||
for (Integer i = 0; i <= curVer; i++) {
|
||||
Map<String, Object> obj = new HashMap<String, Object>();
|
||||
Map<String, Object> dataObj = new HashMap<String, Object>();
|
||||
String verDir = DocumentManager.VersionDir(histDir, i + 1);
|
||||
|
||||
try {
|
||||
String key = null;
|
||||
|
||||
key = i == curVer ? document.key : readFileToEnd(new File(verDir + File.separator + "key.txt"));
|
||||
|
||||
obj.put("key", key);
|
||||
obj.put("version", i);
|
||||
|
||||
if (i == 0) {
|
||||
String createdInfo = readFileToEnd(new File(histDir + File.separator + "createdInfo.json"));
|
||||
JSONObject json = (JSONObject) parser.parse(createdInfo);
|
||||
|
||||
obj.put("created", json.get("created"));
|
||||
Map<String, Object> user = new HashMap<String, Object>();
|
||||
user.put("id", json.get("id"));
|
||||
user.put("name", json.get("name"));
|
||||
obj.put("user", user);
|
||||
}
|
||||
|
||||
dataObj.put("key", key);
|
||||
dataObj.put("url", i == curVer ? document.url : DocumentManager.GetPathUri(verDir + File.separator + "prev" + FileUtility.GetFileExtension(document.title)));
|
||||
dataObj.put("version", i);
|
||||
|
||||
if (i > 0) {
|
||||
JSONObject changes = (JSONObject) parser.parse(readFileToEnd(new File(DocumentManager.VersionDir(histDir, i) + File.separator + "changes.json")));
|
||||
JSONObject change = (JSONObject) ((JSONArray) changes.get("changes")).get(0);
|
||||
|
||||
obj.put("changes", changes.get("changes"));
|
||||
obj.put("serverVersion", changes.get("serverVersion"));
|
||||
obj.put("created", change.get("created"));
|
||||
obj.put("user", change.get("user"));
|
||||
|
||||
Map<String, Object> prev = (Map<String, Object>) histData.get(Integer.toString(i - 1));
|
||||
Map<String, Object> prevInfo = new HashMap<String, Object>();
|
||||
prevInfo.put("key", prev.get("key"));
|
||||
prevInfo.put("url", prev.get("url"));
|
||||
dataObj.put("previous", prevInfo);
|
||||
dataObj.put("changesUrl", DocumentManager.GetPathUri(DocumentManager.VersionDir(histDir, i) + File.separator + "diff.zip"));
|
||||
}
|
||||
|
||||
hist.add(obj);
|
||||
histData.put(Integer.toString(i), dataObj);
|
||||
|
||||
} catch (Exception ex) { }
|
||||
}
|
||||
|
||||
Map<String, Object> histObj = new HashMap<String, Object>();
|
||||
histObj.put("currentVersion", curVer);
|
||||
histObj.put("history", hist);
|
||||
|
||||
Gson gson = new Gson();
|
||||
return new String[] { gson.toJson(histObj), gson.toJson(histData) };
|
||||
}
|
||||
return new String[] { "", "" };
|
||||
}
|
||||
|
||||
private String readFileToEnd(File file) {
|
||||
String output = "";
|
||||
try {
|
||||
try(FileInputStream is = new FileInputStream(file))
|
||||
{
|
||||
Scanner scanner = new Scanner(is);
|
||||
scanner.useDelimiter("\\A");
|
||||
while (scanner.hasNext()) {
|
||||
output += scanner.next();
|
||||
}
|
||||
scanner.close();
|
||||
}
|
||||
} catch (Exception e) { }
|
||||
return output;
|
||||
}
|
||||
|
||||
public class Document
|
||||
{
|
||||
public String title;
|
||||
public String url;
|
||||
public String fileType;
|
||||
public String key;
|
||||
public Permissions permissions;
|
||||
}
|
||||
|
||||
public class Permissions
|
||||
{
|
||||
public Boolean comment;
|
||||
public Boolean download;
|
||||
public Boolean edit;
|
||||
public Boolean fillForms;
|
||||
public Boolean modifyFilter;
|
||||
public Boolean modifyContentControl;
|
||||
public Boolean review;
|
||||
|
||||
public Permissions(String mode, String type, Boolean canEdit)
|
||||
{
|
||||
comment = !mode.equals("view") && !mode.equals("fillForms") && !mode.equals("embedded") && !mode.equals("blockcontent");
|
||||
download = true;
|
||||
edit = canEdit && (mode.equals("edit") || mode.equals("filter") || mode.equals("blockcontent"));
|
||||
fillForms = !mode.equals("view") && !mode.equals("comment") && !mode.equals("embedded") && !mode.equals("blockcontent");
|
||||
modifyFilter = !mode.equals("filter");
|
||||
modifyContentControl = !mode.equals("blockcontent");
|
||||
review = mode.equals("edit") || mode.equals("review");
|
||||
}
|
||||
}
|
||||
|
||||
public class EditorConfig
|
||||
{
|
||||
public String mode = "edit";
|
||||
public String callbackUrl;
|
||||
public String lang = "en";
|
||||
public User user;
|
||||
public Customization customization;
|
||||
public Embedded embedded;
|
||||
@ -115,7 +251,7 @@ public class FileModel
|
||||
|
||||
public class User
|
||||
{
|
||||
public String id;
|
||||
public String id = "uid-1";
|
||||
public String name = "John Smith";
|
||||
}
|
||||
|
||||
|
||||
@ -0,0 +1,27 @@
|
||||
package helpers;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URLDecoder;
|
||||
import java.util.HashMap;
|
||||
|
||||
import javax.servlet.http.Cookie;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
public class CookieManager {
|
||||
private HashMap<String, String> cookiesMap;
|
||||
|
||||
public CookieManager(HttpServletRequest request) throws UnsupportedEncodingException {
|
||||
cookiesMap = new HashMap<String, String>();
|
||||
|
||||
Cookie[] cookies = request.getCookies();
|
||||
if (cookies != null) {
|
||||
for (Cookie cookie : cookies) {
|
||||
cookiesMap.putIfAbsent(cookie.getName(), URLDecoder.decode(cookie.getValue(), "UTF-8"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public String getCookie(String name) {
|
||||
return cookiesMap.get(name);
|
||||
}
|
||||
}
|
||||
@ -27,13 +27,17 @@
|
||||
package helpers;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileFilter;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.FileWriter;
|
||||
import java.io.InputStream;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.InetAddress;
|
||||
import java.net.URLEncoder;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
@ -43,6 +47,7 @@ import entities.FileType;
|
||||
import org.primeframework.jwt.domain.JWT;
|
||||
import org.primeframework.jwt.hmac.HMACSigner;
|
||||
import org.primeframework.jwt.hmac.HMACVerifier;
|
||||
import org.json.simple.JSONObject;
|
||||
import org.primeframework.jwt.Signer;
|
||||
import org.primeframework.jwt.Verifier;
|
||||
|
||||
@ -117,31 +122,65 @@ public class DocumentManager
|
||||
return userAddress.replaceAll("[^0-9a-zA-Z.=]", "_");
|
||||
}
|
||||
|
||||
public static String StoragePath(String fileName, String userAddress)
|
||||
public static String FilesRootPath(String userAddress)
|
||||
{
|
||||
String hostAddress = CurUserHostAddress(userAddress);
|
||||
String serverPath = request.getSession().getServletContext().getRealPath("");
|
||||
String storagePath = ConfigManager.GetProperty("storage-folder");
|
||||
String hostAddress = CurUserHostAddress(userAddress);
|
||||
String directory = serverPath + File.separator + storagePath + File.separator;
|
||||
String directory = serverPath + storagePath + File.separator + hostAddress + File.separator;
|
||||
|
||||
File file = new File(directory);
|
||||
|
||||
if (!file.exists())
|
||||
{
|
||||
file.mkdir();
|
||||
file.mkdirs();
|
||||
}
|
||||
|
||||
directory = directory + hostAddress + File.separator;
|
||||
file = new File(directory);
|
||||
|
||||
if (!file.exists())
|
||||
{
|
||||
file.mkdir();
|
||||
}
|
||||
return directory;
|
||||
}
|
||||
|
||||
public static String StoragePath(String fileName, String userAddress)
|
||||
{
|
||||
String directory = FilesRootPath(userAddress);
|
||||
return directory + fileName;
|
||||
}
|
||||
|
||||
public static String HistoryDir(String storagePath)
|
||||
{
|
||||
return storagePath += "-hist";
|
||||
}
|
||||
|
||||
public static String VersionDir(String histPath, Integer version)
|
||||
{
|
||||
return histPath + File.separator + Integer.toString(version);
|
||||
}
|
||||
|
||||
public static String VersionDir(String fileName, String userAddress, Integer version)
|
||||
{
|
||||
return VersionDir(HistoryDir(StoragePath(fileName, userAddress)), version);
|
||||
}
|
||||
|
||||
public static Integer GetFileVersion(String historyPath)
|
||||
{
|
||||
File dir = new File(historyPath);
|
||||
|
||||
if (!dir.exists()) return 0;
|
||||
|
||||
File[] dirs = dir.listFiles(new FileFilter() {
|
||||
@Override
|
||||
public boolean accept(File pathname) {
|
||||
return pathname.isDirectory();
|
||||
}
|
||||
});
|
||||
|
||||
return dirs.length;
|
||||
}
|
||||
|
||||
public static int GetFileVersion(String fileName, String userAddress)
|
||||
{
|
||||
return GetFileVersion(HistoryDir(StoragePath(fileName, userAddress)));
|
||||
}
|
||||
|
||||
public static String GetCorrectName(String fileName)
|
||||
{
|
||||
String baseName = FileUtility.GetFileNameWithoutExtension(fileName);
|
||||
@ -159,9 +198,40 @@ public class DocumentManager
|
||||
return name;
|
||||
}
|
||||
|
||||
public static String CreateDemo(String fileExt) throws Exception
|
||||
public static void CreateMeta(String fileName, String uid, String uname) throws Exception
|
||||
{
|
||||
String demoName = "sample." + fileExt;
|
||||
String histDir = HistoryDir(StoragePath(fileName, null));
|
||||
|
||||
File dir = new File(histDir);
|
||||
dir.mkdir();
|
||||
|
||||
JSONObject json = new JSONObject();
|
||||
json.put("created", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
|
||||
json.put("id", (uid == null || uid.isEmpty()) ? "uid-1" : uid);
|
||||
json.put("name", (uname == null || uname.isEmpty()) ? "John Smith" : uname);
|
||||
|
||||
File meta = new File(histDir + File.separator + "createdInfo.json");
|
||||
try (FileWriter writer = new FileWriter(meta)) {
|
||||
json.writeJSONString(writer);
|
||||
}
|
||||
}
|
||||
|
||||
public static File[] GetStoredFiles(String userAddress)
|
||||
{
|
||||
String directory = FilesRootPath(userAddress);
|
||||
|
||||
File file = new File(directory);
|
||||
return file.listFiles(new FileFilter() {
|
||||
@Override
|
||||
public boolean accept(File pathname) {
|
||||
return pathname.isFile();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static String CreateDemo(String fileExt, Boolean sample, String uid, String uname) throws Exception
|
||||
{
|
||||
String demoName = (sample ? "sample." : "new.") + fileExt;
|
||||
String fileName = GetCorrectName(demoName);
|
||||
|
||||
InputStream stream = Thread.currentThread().getContextClassLoader().getResourceAsStream(demoName);
|
||||
@ -179,6 +249,8 @@ public class DocumentManager
|
||||
out.flush();
|
||||
}
|
||||
|
||||
CreateMeta(fileName, uid, uname);
|
||||
|
||||
return fileName;
|
||||
}
|
||||
|
||||
@ -200,6 +272,18 @@ public class DocumentManager
|
||||
}
|
||||
}
|
||||
|
||||
public static String GetPathUri(String path)
|
||||
{
|
||||
String serverPath = GetServerUrl();
|
||||
String storagePath = ConfigManager.GetProperty("storage-folder");
|
||||
String hostAddress = CurUserHostAddress(null);
|
||||
|
||||
String filePath = serverPath + "/" + storagePath + "/" + hostAddress + "/" + path.replace(File.separator, "/").substring(FilesRootPath(null).length()).replace(" ", "%20");
|
||||
|
||||
return filePath;
|
||||
}
|
||||
|
||||
|
||||
public static String GetServerUrl()
|
||||
{
|
||||
return request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + request.getContextPath();
|
||||
|
||||
BIN
web/documentserver-example/java/src/main/resources/new.docx
Normal file
BIN
web/documentserver-example/java/src/main/resources/new.pptx
Normal file
BIN
web/documentserver-example/java/src/main/resources/new.xlsx
Normal file
|
After Width: | Height: | Size: 452 B |
|
After Width: | Height: | Size: 127 B |
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 1.0 KiB |
|
After Width: | Height: | Size: 1.2 KiB |
|
After Width: | Height: | Size: 1.2 KiB |
|
After Width: | Height: | Size: 1.7 KiB |
|
After Width: | Height: | Size: 152 B |
|
After Width: | Height: | Size: 118 B |
|
After Width: | Height: | Size: 1.2 KiB |
|
After Width: | Height: | Size: 1.2 KiB |
|
After Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 4.0 KiB After Width: | Height: | Size: 5.4 KiB |
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 145 B |
@ -112,13 +112,14 @@ label .checkbox {
|
||||
|
||||
.try-editor-list {
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
margin: 0 0 16px;
|
||||
padding: 0;
|
||||
}
|
||||
.try-editor-list li {
|
||||
float: left;
|
||||
margin: 25px;
|
||||
width: 150px;
|
||||
margin: 0 15px;
|
||||
width: 100px;
|
||||
cursor: pointer;
|
||||
}
|
||||
.try-editor {
|
||||
background-color: transparent;
|
||||
@ -142,6 +143,11 @@ label .checkbox {
|
||||
background-image: url("img/file_pptx.png");
|
||||
}
|
||||
|
||||
.create-sample {
|
||||
display: inline-block;
|
||||
margin-left: 75px;
|
||||
}
|
||||
|
||||
.button, .button:visited, .button:hover, .button:active {
|
||||
display: inline-block;
|
||||
font-weight: normal;
|
||||
@ -184,27 +190,46 @@ label .checkbox {
|
||||
border: 1px solid #E9EAEA;
|
||||
}
|
||||
|
||||
.upload-panel {
|
||||
border-right: 1px solid #D1D1D1;
|
||||
float: left;
|
||||
margin-right: 25px;
|
||||
}
|
||||
|
||||
.file-upload {
|
||||
background: url("img/file_upload.png") no-repeat center 0 transparent;
|
||||
cursor: pointer;
|
||||
margin-bottom: 8px;
|
||||
padding: 0 !important;
|
||||
display: inline-block;
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
height: 45px;
|
||||
margin: 0 40px 16px;
|
||||
overflow: hidden;
|
||||
padding-top: 100px;
|
||||
position: relative;
|
||||
text-align: center;
|
||||
width: 100px;
|
||||
}
|
||||
.file-upload span {
|
||||
line-height: 21px;
|
||||
margin: 2px 12px;
|
||||
|
||||
.file-upload input {
|
||||
cursor: pointer;
|
||||
opacity: 0;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0;
|
||||
transform: translate(555px, 60px) scale(8);
|
||||
}
|
||||
|
||||
.create-panel {
|
||||
float: left;
|
||||
}
|
||||
.file-upload input {
|
||||
cursor: pointer;
|
||||
font-size: 23px;
|
||||
opacity: 0;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0;
|
||||
transform: translate(-300px, 0) scale(4);
|
||||
|
||||
.upload-panel,
|
||||
.create-panel {
|
||||
padding: 10px 0;
|
||||
}
|
||||
|
||||
|
||||
#mainProgress {
|
||||
color: #979b9f;
|
||||
display: none;
|
||||
@ -280,8 +305,53 @@ label .checkbox {
|
||||
line-height: 26px;
|
||||
}
|
||||
|
||||
.stored-edit {
|
||||
background-color: transparent;
|
||||
background-position: left center;
|
||||
background-repeat: no-repeat;
|
||||
display: inline-block;
|
||||
line-height: 16px;
|
||||
max-width: 450px;
|
||||
margin-bottom: -6px;
|
||||
overflow: hidden;
|
||||
padding: 4px 0 1px 34px;
|
||||
text-decoration: none;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.stored-edit.text {
|
||||
background-image: url("img/icon_docx.png");
|
||||
}
|
||||
|
||||
.stored-edit.spreadsheet {
|
||||
background-image: url("img/icon_xlsx.png");
|
||||
}
|
||||
|
||||
.stored-edit.presentation {
|
||||
background-image: url("img/icon_pptx.png");
|
||||
}
|
||||
|
||||
.stored-edit span {
|
||||
font-size: 12px;
|
||||
line-height: 12px;
|
||||
}
|
||||
|
||||
.stored-edit:hover span {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.stored-download {
|
||||
color: #787878;
|
||||
float: right;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
|
||||
.stored-download:hover {
|
||||
color: #787878;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.blockTitle {
|
||||
background-color: #E2E2E2 !important;
|
||||
@ -311,4 +381,120 @@ label .checkbox {
|
||||
-moz-box-shadow: 0 2px 4px rgba(0, 0, 0, 0.5);
|
||||
-webkit-box-shadow:0 2px 4px rgba(0, 0, 0, 0.5);
|
||||
padding: 0 !important;
|
||||
}
|
||||
.clearFix:after {
|
||||
content: ".";
|
||||
display: block;
|
||||
height: 0;
|
||||
clear: both;
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
/*Icon table*/
|
||||
.select-user {
|
||||
margin-left: 15px;
|
||||
}
|
||||
|
||||
.user-block-table {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.user-block-table td {
|
||||
background-color: #F4F4F4;
|
||||
border-bottom: 1px solid white;
|
||||
padding: 12px 0;
|
||||
}
|
||||
|
||||
#tableRow {
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
.tableRow {
|
||||
background: transparent;
|
||||
-moz-transition: all 0.2s ease-in-out;
|
||||
-webkit-transition: all 0.2s ease-in-out;
|
||||
-o-transition: all 0.2s ease-in-out;
|
||||
-ms-transition: all 0.2s ease-in-out;
|
||||
transition: all 0.2s ease-in-out;
|
||||
}
|
||||
|
||||
.tableRow:hover {
|
||||
background-color: #ebebeb;
|
||||
}
|
||||
|
||||
.tableHeader {
|
||||
background: transparent;
|
||||
color: #333;
|
||||
cursor: default;
|
||||
font-family: 'Open Sans', sans-serif;
|
||||
font-size: 13px;
|
||||
height: 40px;
|
||||
-khtml-user-select: none;
|
||||
user-select: none;
|
||||
-moz-user-select: none;
|
||||
-webkit-user-select: none;
|
||||
}
|
||||
|
||||
.tableHeaderCell {
|
||||
padding: 2px 1px 2px 5px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.tableHeaderCellFileName {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.contentCells {
|
||||
padding: 4px 1px 4px 5px;
|
||||
font-family: 'Open Sans', sans-serif;
|
||||
font-size: 16px;
|
||||
border-bottom: 1px solid #e5e5e5;
|
||||
white-space: nowrap;
|
||||
-khtml-user-select: none;
|
||||
user-select: none;
|
||||
-moz-user-select: none;
|
||||
-webkit-user-select: none;
|
||||
}
|
||||
|
||||
.contentCells a {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.contentCells-shift {
|
||||
padding-right: 30px;
|
||||
}
|
||||
|
||||
.contentCells-icon {
|
||||
width: 6%;
|
||||
}
|
||||
|
||||
.contentCellsSmall {
|
||||
padding: 5px 1px 5px 6px;
|
||||
font-family: 'Open Sans', sans-serif;
|
||||
font-size: 13px;
|
||||
border-bottom: 1px solid #e5e5e5;
|
||||
white-space: nowrap;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.primaryRow {
|
||||
background-color: #e9e9e9;
|
||||
}
|
||||
|
||||
.secondaryRow {
|
||||
background-color: #F9F9F9;
|
||||
}
|
||||
|
||||
#user, #language {
|
||||
width: 130px;
|
||||
}
|
||||
|
||||
.icon-download {
|
||||
margin-bottom: -5px;
|
||||
}
|
||||
|
||||
.icon-delete {
|
||||
cursor: pointer;
|
||||
margin-bottom: -6px;
|
||||
}
|
||||
@ -31,6 +31,9 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no, minimal-ui" />
|
||||
<meta name="apple-mobile-web-app-capable" content="yes" />
|
||||
<meta name="mobile-web-app-capable" content="yes" />
|
||||
<title>ONLYOFFICE</title>
|
||||
<link rel="icon" href="favicon.ico" type="image/x-icon" />
|
||||
<link rel="stylesheet" type="text/css" href="css/editor.css" />
|
||||
@ -70,18 +73,38 @@
|
||||
location.reload(true);
|
||||
};
|
||||
|
||||
var сonnectEditor = function () {
|
||||
var config = JSON.parse('<%= FileModel.Serialize(Model) %>');
|
||||
config.width = "100%";
|
||||
config.height = "100%";
|
||||
config.events = {
|
||||
"onAppReady": onAppReady,
|
||||
"onDocumentStateChange": onDocumentStateChange,
|
||||
'onRequestEditRights': onRequestEditRights,
|
||||
"onError": onError,
|
||||
"onOutdatedVersion": onOutdatedVersion,
|
||||
};
|
||||
var config = JSON.parse('<%= FileModel.Serialize(Model) %>');
|
||||
config.width = "100%";
|
||||
config.height = "100%";
|
||||
config.events = {
|
||||
"onAppReady": onAppReady,
|
||||
"onDocumentStateChange": onDocumentStateChange,
|
||||
'onRequestEditRights': onRequestEditRights,
|
||||
"onError": onError,
|
||||
"onOutdatedVersion": onOutdatedVersion,
|
||||
};
|
||||
|
||||
<%
|
||||
String[] histArray = Model.GetHistory();
|
||||
String history = histArray[0];
|
||||
String historyData = histArray[1];
|
||||
%>
|
||||
|
||||
<% if (!history.isEmpty() && !historyData.isEmpty()) { %>
|
||||
config.events['onRequestHistory'] = function () {
|
||||
docEditor.refreshHistory(<%= history %>);
|
||||
};
|
||||
config.events['onRequestHistoryData'] = function (event) {
|
||||
var ver = event.data;
|
||||
var histData = <%= historyData %>;
|
||||
docEditor.setHistoryData(histData[ver]);
|
||||
};
|
||||
config.events['onRequestHistoryClose'] = function () {
|
||||
document.location.reload();
|
||||
};
|
||||
<% } %>
|
||||
|
||||
var сonnectEditor = function () {
|
||||
docEditor = new DocsAPI.DocEditor("iframeEditor", config);
|
||||
};
|
||||
|
||||
|
||||
|
Before Width: | Height: | Size: 466 B After Width: | Height: | Size: 144 KiB |
@ -25,8 +25,11 @@
|
||||
*-->
|
||||
|
||||
<%@page import="helpers.DocumentManager"%>
|
||||
<%@page import="helpers.FileUtility"%>
|
||||
<%@page import="helpers.ConfigManager"%>
|
||||
<%@page import="java.util.Calendar"%>
|
||||
<%@page import="java.io.File"%>
|
||||
<%@page import="java.net.URLEncoder"%>
|
||||
<%@page contentType="text/html" pageEncoding="UTF-8"%>
|
||||
|
||||
<!DOCTYPE html>
|
||||
@ -47,41 +50,179 @@
|
||||
<span class="portal-name">ONLYOFFICE Document Editors</span>
|
||||
<br />
|
||||
<br />
|
||||
<span class="portal-descr">Get started with a demo-sample of ONLYOFFICE Document Editors, the first html5-based editors. You may upload your own documents for testing using the "Choose file" button and selecting the necessary files on your PC.</span>
|
||||
<span class="portal-descr">Get started with a demo-sample of ONLYOFFICE Document Editors, the first html5-based editors. You may upload your own documents for testing using the "Upload file" button and selecting the necessary files on your PC.</span>
|
||||
|
||||
<div class="file-upload button gray">
|
||||
<span>Choose file</span>
|
||||
<form class="fileupload" action="server/php/" method="POST" enctype="multipart/form-data">
|
||||
<table class="user-block-table" cellspacing="0" cellpadding="0">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td width="30%" valign="middle">
|
||||
<span class="select-user">Username:</span>
|
||||
<select class="select-user" id="user">
|
||||
<option value="uid-1">Jonn Smith</option>
|
||||
<option value="uid-2">Mark Pottato</option>
|
||||
<option value="uid-3">Hamish Mitchell</option>
|
||||
</select>
|
||||
</td>
|
||||
<td width="70%" valign="middle">Select user name before opening the document; you can open the same document using different users in different Web browser sessions, so you can check out multi-user editing functions.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="30%" valign="middle">
|
||||
<select class="select-user" id="language">
|
||||
<option value="en">English</option>
|
||||
<option value="bg">Bulgarian</option>
|
||||
<option value="zh">Chinese</option>
|
||||
<option value="cs">Czech</option>
|
||||
<option value="nl">Dutch</option>
|
||||
<option value="fr">French</option>
|
||||
<option value="de">German</option>
|
||||
<option value="hu">Hungarian</option>
|
||||
<option value="it">Italian</option>
|
||||
<option value="ja">Japanese</option>
|
||||
<option value="ko">Korean</option>
|
||||
<option value="lv">Latvian</option>
|
||||
<option value="pl">Polish</option>
|
||||
<option value="pt">Portuguese</option>
|
||||
<option value="ru">Russian</option>
|
||||
<option value="sk">Slovak</option>
|
||||
<option value="sl">Slovenian</option>
|
||||
<option value="es">Spanish</option>
|
||||
<option value="tr">Turkish</option>
|
||||
<option value="uk">Ukrainian</option>
|
||||
<option value="vi">Vietnamese</option>
|
||||
</select>
|
||||
</td>
|
||||
<td width="70%" valign="middle">Choose the language for ONLYOFFICE™ editors interface.</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<br />
|
||||
<br />
|
||||
|
||||
</form>
|
||||
<input type="file" id="fileupload" name="file" data-url="IndexServlet?type=upload" />
|
||||
<div class="help-block">
|
||||
<span class="try-descr">Upload your file or create new file</span>
|
||||
<br />
|
||||
<br />
|
||||
<div class="clearFix">
|
||||
<div class="upload-panel clearFix">
|
||||
<a class="file-upload">
|
||||
Upload
|
||||
<br />
|
||||
File
|
||||
<input type="file" id="fileupload" name="file" data-url="IndexServlet?type=upload" />
|
||||
</a>
|
||||
</div>
|
||||
<div class="create-panel">
|
||||
<ul class="try-editor-list clearFix">
|
||||
<li><a class="try-editor document" data-type="docx">Create<br />Document</a></li>
|
||||
<li><a class="try-editor spreadsheet" data-type="xlsx">Create<br />Spreadsheet</a></li>
|
||||
<li><a class="try-editor presentation" data-type="pptx">Create<br />Presentation</a></li>
|
||||
</ul>
|
||||
<label class="create-sample">
|
||||
<input id="createSample" class="checkbox" type="checkbox" />
|
||||
Create a file filled with sample content
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<label class="save-original">
|
||||
<input type="checkbox" id="checkOriginalFormat" class="checkbox" />Save document in original format
|
||||
</label>
|
||||
<span class="question"></span>
|
||||
<br />
|
||||
<br />
|
||||
<br />
|
||||
<span class="try-descr">You are also enabled to view and edit documents pre-uploaded to the portal.</span>
|
||||
|
||||
<ul class="try-editor-list">
|
||||
<li>
|
||||
<a href="EditorServlet?fileExt=docx" class="try-editor document" target="_blank">
|
||||
Create<br />Sample Document
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="EditorServlet?fileExt=xlsx" class="try-editor spreadsheet" target="_blank">
|
||||
Create<br />Sample Spreadsheet
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="EditorServlet?fileExt=pptx" class="try-editor presentation" target="_blank">
|
||||
Create<br />Sample Presentation
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
<% DocumentManager.Init(request, response); %>
|
||||
<% File[] files = DocumentManager.GetStoredFiles(null); %>
|
||||
<% if (files.length > 0) { %>
|
||||
|
||||
<div class="help-block">
|
||||
<span>Your documents</span>
|
||||
<br />
|
||||
<br />
|
||||
|
||||
<div class="stored-list">
|
||||
<table width="100%" cellspacing="0" cellpadding="0">
|
||||
<thead>
|
||||
<tr class="tableHeader">
|
||||
<td class="tableHeaderCell tableHeaderCellFileName">Filename</td>
|
||||
<td colspan="6" class="tableHeaderCell contentCells-shift">Editors</td>
|
||||
<td colspan="3" class="tableHeaderCell">Viewers</td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<% for (Integer i = 0; i < files.length; i++) { %>
|
||||
<% String docType = FileUtility.GetFileType(files[i].getName()).toString().toLowerCase(); %>
|
||||
<tr class="tableRow" title="<%= files[i].getName() %>">
|
||||
<td class="contentCells">
|
||||
<a class="stored-edit <%= docType %>" href="EditorServlet?fileName=<%= URLEncoder.encode(files[i].getName(), "UTF-8") %>" target="_blank">
|
||||
<span title="<%= files[i].getName() %>"><%= files[i].getName() %></span>
|
||||
</a>
|
||||
<a href="<%= DocumentManager.GetFileUri(files[i].getName()) %>">
|
||||
<img class="icon-download" src="css/img/download-24.png" alt="Download" title="Download" />
|
||||
</a>
|
||||
<a class="delete-file" data-filename="<%= files[i].getName() %>">
|
||||
<img class="icon-delete" src="css/img/delete-24.png" alt="Delete" title="Delete" />
|
||||
</a>
|
||||
</td>
|
||||
|
||||
<td class="contentCells contentCells-icon">
|
||||
<a href="EditorServlet?fileName=<%= URLEncoder.encode(files[i].getName(), "UTF-8") %>&type=desktop&mode=edit" target="_blank">
|
||||
<img src="css/img/desktop-24.png" alt="Open in editor for full size screens" title="Open in editor for full size screens"/>
|
||||
</a>
|
||||
</td>
|
||||
<td class="contentCells contentCells-icon">
|
||||
<a href="EditorServlet?fileName=<%= URLEncoder.encode(files[i].getName(), "UTF-8") %>&type=mobile&mode=edit" target="_blank">
|
||||
<img src="css/img/mobile-24.png" alt="Open in editor for mobile devices" title="Open in editor for mobile devices"/>
|
||||
</a>
|
||||
</td>
|
||||
<td class="contentCells contentCells-icon">
|
||||
<% if (docType.equals("text")) { %>
|
||||
<a href="EditorServlet?fileName=<%= URLEncoder.encode(files[i].getName(), "UTF-8") %>&type=desktop&mode=review" target="_blank">
|
||||
<img src="css/img/review-24.png" alt="Open in editor for review" title="Open in editor for review"/>
|
||||
</a>
|
||||
<% } else if (docType.equals("spreadsheet")) { %>
|
||||
<a href="EditorServlet?fileName=<%= URLEncoder.encode(files[i].getName(), "UTF-8") %>&type=desktop&mode=filter" target="_blank">
|
||||
<img src="css/img/filter-24.png" alt="Open in editor without access to change the filter" title="Open in editor without access to change the filter" />
|
||||
</a>
|
||||
<% } %>
|
||||
</td>
|
||||
<td class="contentCells contentCells-icon">
|
||||
<a href="EditorServlet?fileName=<%= URLEncoder.encode(files[i].getName(), "UTF-8") %>&type=desktop&mode=comment" target="_blank">
|
||||
<img src="css/img/comment-24.png" alt="Open in editor for comment" title="Open in editor for comment"/>
|
||||
</a>
|
||||
</td>
|
||||
<td class="contentCells contentCells-icon">
|
||||
<% if (docType.equals("text")) { %>
|
||||
<a href="EditorServlet?fileName=<%= URLEncoder.encode(files[i].getName(), "UTF-8") %>&type=desktop&mode=fillForms" target="_blank">
|
||||
<img src="css/img/fill-forms-24.png" alt="Open in editor for filling in forms" title="Open in editor for filling in forms"/>
|
||||
</a>
|
||||
<% } %>
|
||||
</td>
|
||||
<td class="contentCells contentCells-shift contentCells-icon">
|
||||
<% if (docType.equals("text")) { %>
|
||||
<a href="EditorServlet?fileName=<%= URLEncoder.encode(files[i].getName(), "UTF-8") %>&type=desktop&mode=blockcontent" target="_blank">
|
||||
<img src="css/img/block-content-24.png" alt="Open in editor without content control modification" title="Open in editor without content control modification"/>
|
||||
</a>
|
||||
<% } %>
|
||||
</td>
|
||||
|
||||
<td class="contentCells contentCells-icon">
|
||||
<a href="EditorServlet?fileName=<%= URLEncoder.encode(files[i].getName(), "UTF-8") %>&type=desktop&mode=view" target="_blank">
|
||||
<img src="css/img/desktop-24.png" alt="Open in viewer for full size screens" title="Open in viewer for full size screens"/>
|
||||
</a>
|
||||
</td>
|
||||
<td class="contentCells contentCells-icon">
|
||||
<a href="EditorServlet?fileName=<%= URLEncoder.encode(files[i].getName(), "UTF-8") %>&type=mobile&mode=view" target="_blank">
|
||||
<img src="css/img/mobile-24.png" alt="Open in viewer for mobile devices" title="Open in viewer for mobile devices"/>
|
||||
</a>
|
||||
</td>
|
||||
<td class="contentCells contentCells-icon">
|
||||
<a href="EditorServlet?fileName=<%= URLEncoder.encode(files[i].getName(), "UTF-8") %>&type=embedded&mode=embedded" target="_blank">
|
||||
<img src="css/img/embeded-24.png" alt="Open in embedded mode" title="Open in embedded mode"/>
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
<% } %>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<% } %>
|
||||
|
||||
<br />
|
||||
<br />
|
||||
|
||||
@ -70,6 +70,8 @@ if (typeof jQuery !== "undefined") {
|
||||
checkConvert();
|
||||
}
|
||||
});
|
||||
|
||||
initSelectors();
|
||||
});
|
||||
|
||||
var timer = null;
|
||||
@ -91,11 +93,6 @@ if (typeof jQuery !== "undefined") {
|
||||
return;
|
||||
}
|
||||
|
||||
if (jq("#checkOriginalFormat").is(":checked")) {
|
||||
loadScripts();
|
||||
return;
|
||||
}
|
||||
|
||||
timer = setTimeout(function () {
|
||||
var requestAddress = UrlConverter
|
||||
+ "&filename=" + encodeURIComponent(jq("#hiddenFileName").val());
|
||||
@ -162,6 +159,34 @@ if (typeof jQuery !== "undefined") {
|
||||
}
|
||||
};
|
||||
|
||||
var initSelectors = function () {
|
||||
var userSel = jq("#user");
|
||||
var langSel = jq("#language");
|
||||
|
||||
function getCookie(name) {
|
||||
let matches = document.cookie.match(new RegExp(
|
||||
"(?:^|; )" + name.replace(/([\.$?*|{}\(\)\[\]\\\/\+^])/g, '\\$1') + "=([^;]*)"
|
||||
));
|
||||
return matches ? decodeURIComponent(matches[1]) : null;
|
||||
}
|
||||
function setCookie(name, value) {
|
||||
document.cookie = name + "=" + value + "; expires=" + new Date(Date.now() + 1000 * 60 * 60 * 24 * 7).toUTCString(); //week
|
||||
}
|
||||
|
||||
var userId = getCookie("uid");
|
||||
if (userId) userSel.val(userId);
|
||||
var langId = getCookie("ulang");
|
||||
if (langId) langSel.val(langId);
|
||||
|
||||
userSel.on("change", function () {
|
||||
setCookie("uid", userSel.val());
|
||||
setCookie("uname", encodeURIComponent(userSel.find("option:selected").text()));
|
||||
});
|
||||
langSel.on("change", function () {
|
||||
setCookie("ulang", langSel.val());
|
||||
});
|
||||
};
|
||||
|
||||
jq(document).on("click", "#beginEdit:not(.disable)", function () {
|
||||
var fileId = encodeURIComponent(jq("#hiddenFileName").val());
|
||||
var url = UrlEditor + "?mode=edit&fileName=" + fileId;
|
||||
@ -194,6 +219,32 @@ if (typeof jQuery !== "undefined") {
|
||||
jq.unblockUI();
|
||||
});
|
||||
|
||||
jq(document).on("click", ".try-editor", function (e) {
|
||||
var url = "EditorServlet?fileExt=" + e.target.attributes["data-type"].value;
|
||||
if (jq("#createSample").is(":checked")) {
|
||||
url += "&sample=true";
|
||||
}
|
||||
var w = window.open(url, "_blank");
|
||||
w.onload = function () {
|
||||
window.location.reload();
|
||||
}
|
||||
});
|
||||
|
||||
jq(document).on("click", ".delete-file", function () {
|
||||
var requestAddress = "IndexServlet"
|
||||
+ "?type=remove"
|
||||
+ "&filename=" + encodeURIComponent(jq(this).attr("data-filename"));
|
||||
|
||||
jq.ajax({
|
||||
async: true,
|
||||
contentType: "text/xml",
|
||||
url: requestAddress,
|
||||
complete: function (data) {
|
||||
document.location.reload();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
jq.dropdownToggle({
|
||||
switcherSelector: ".question",
|
||||
dropdownID: "hint"
|
||||
|
||||
|
Before Width: | Height: | Size: 4.0 KiB After Width: | Height: | Size: 5.4 KiB |
@ -616,14 +616,15 @@ app.get("/editor", function (req, res) {
|
||||
key: key,
|
||||
token: "",
|
||||
callbackUrl: docManager.getCallback(fileName),
|
||||
isEdit: canEdit && (mode == "edit" || mode == "filter"),
|
||||
isEdit: canEdit && (mode == "edit" || mode == "filter" || mode == "blockcontent"),
|
||||
review: mode == "edit" || mode == "review",
|
||||
comment: mode != "view" && mode != "fillForms" && mode != "embedded",
|
||||
fillForms: mode != "view" && mode != "comment" && mode != "embedded",
|
||||
comment: mode != "view" && mode != "fillForms" && mode != "embedded" && mode != "blockcontent",
|
||||
fillForms: mode != "view" && mode != "comment" && mode != "embedded" && mode != "blockcontent",
|
||||
modifyFilter: mode != "filter",
|
||||
modifyContentControl: mode != "blockcontent",
|
||||
mode: canEdit && mode != "view" ? "edit" : "view",
|
||||
canBackToFolder: type != "embedded",
|
||||
backUrl: docManager.getServerUrl(),
|
||||
backUrl: docManager.getServerUrl() + "/",
|
||||
curUserHostAddress: docManager.curUserHostAddress(),
|
||||
lang: lang,
|
||||
userid: userid,
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
"server": {
|
||||
"port": 3000,
|
||||
"siteUrl": "http://127.0.0.1:8080/",
|
||||
"apiUrl": "web-apps-pro/apps/api/documents/api.js",
|
||||
"preloaderUrl": "web-apps-pro/apps/api/documents/cache-scripts.html"
|
||||
"apiUrl": "web-apps/apps/api/documents/api.js",
|
||||
"preloaderUrl": "web-apps/apps/api/documents/cache-scripts.html"
|
||||
}
|
||||
}
|
||||
@ -2,7 +2,7 @@
|
||||
"server": {
|
||||
"port": 80,
|
||||
"siteUrl": "http://127.0.0.1:8001/",
|
||||
"apiUrl": "web-apps-pro/apps/api/documents/api.js",
|
||||
"preloaderUrl": "web-apps-pro/apps/api/documents/cache-scripts.html"
|
||||
"apiUrl": "web-apps/apps/api/documents/api.js",
|
||||
"preloaderUrl": "web-apps/apps/api/documents/cache-scripts.html"
|
||||
}
|
||||
}
|
||||
@ -187,18 +187,11 @@
|
||||
"integrity": "sha512-vKQ9DTQPN1FLYiiEEOQ6IBGFqvjCa5rSK3cWMy/Nespm5d/x3dGFT9UBZnkLxCwua/IXBi2TYnwTEpsOvhC4UQ=="
|
||||
},
|
||||
"debug": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz",
|
||||
"integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=",
|
||||
"version": "2.6.9",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
|
||||
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
|
||||
"requires": {
|
||||
"ms": "0.7.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"ms": {
|
||||
"version": "0.7.1",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz",
|
||||
"integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg="
|
||||
}
|
||||
"ms": "2.0.0"
|
||||
}
|
||||
},
|
||||
"deep-is": {
|
||||
|
||||
@ -16,7 +16,7 @@
|
||||
"dependencies": {
|
||||
"body-parser": "^1.16.1",
|
||||
"config": "^1.21.0",
|
||||
"debug": "~2.2.0",
|
||||
"debug": "~2.6.9",
|
||||
"ejs": "~2.5.1",
|
||||
"express": "^4.14.1",
|
||||
"formidable": "^1.1.1",
|
||||
|
||||
|
After Width: | Height: | Size: 452 B |
|
Before Width: | Height: | Size: 466 B After Width: | Height: | Size: 144 KiB |
@ -290,7 +290,7 @@ footer {
|
||||
background-repeat: no-repeat;
|
||||
display: inline-block;
|
||||
height: 16px;
|
||||
max-width: 250px;
|
||||
max-width: 200px;
|
||||
margin-bottom: -6px;
|
||||
overflow: hidden;
|
||||
padding: 8px 0 1px 34px;
|
||||
|
||||
@ -18,6 +18,7 @@
|
||||
"edit": <%- editor.isEdit %>,
|
||||
"fillForms": <%- editor.fillForms %>,
|
||||
"modifyFilter": <%- editor.modifyFilter %>,
|
||||
"modifyContentControl": <%- editor.modifyContentControl %>,
|
||||
"review": <%- editor.review %>
|
||||
}
|
||||
},
|
||||
|
||||
@ -143,7 +143,7 @@
|
||||
<thead>
|
||||
<tr class="tableHeader">
|
||||
<td class="tableHeaderCell tableHeaderCellFileName">Filename</td>
|
||||
<td colspan="5" class="tableHeaderCell contentCells-shift">Editors</td>
|
||||
<td colspan="6" class="tableHeaderCell contentCells-shift">Editors</td>
|
||||
<td colspan="3" class="tableHeaderCell">Viewers</td>
|
||||
</tr>
|
||||
</thead>
|
||||
@ -180,12 +180,18 @@
|
||||
<a href="editor?type=desktop&mode=comment&fileName=<%= encodeURIComponent(storedFiles[i].name) + params %>" target="_blank">
|
||||
<img src="images/comment-24.png" alt="Open in editor for comment" title="Open in editor for comment" /></a>
|
||||
</td>
|
||||
<td class="contentCells contentCells-shift contentCells-icon">
|
||||
<td class="contentCells contentCells-icon">
|
||||
<% if (storedFiles[i].documentType == "text") { %>
|
||||
<a href="editor?type=desktop&mode=fillForms&fileName=<%= encodeURIComponent(storedFiles[i].name) + params %>" target="_blank">
|
||||
<img src="images/fill-forms-24.png" alt="Open in editor for filling in forms" title="Open in editor for filling in forms" /></a>
|
||||
<% } %>
|
||||
</td>
|
||||
<td class="contentCells contentCells-shift contentCells-icon">
|
||||
<% if (storedFiles[i].documentType == "text") { %>
|
||||
<a href="editor?type=desktop&mode=blockcontent&fileName=<%= encodeURIComponent(storedFiles[i].name) + params %>" target="_blank">
|
||||
<img src="images/block-content-24.png" alt="Open in editor without content control modification" title="Open in editor without content control modification" /></a>
|
||||
<% } %>
|
||||
</td>
|
||||
<% } else { %>
|
||||
<td class="contentCells contentCells-shift contentCells-icon" colspan="5"></td>
|
||||
<% } %>
|
||||
|
||||
@ -209,6 +209,33 @@ function getStoragePath($fileName, $userAddress = NULL) {
|
||||
return $directory . $fileName;
|
||||
}
|
||||
|
||||
function getHistoryDir($storagePath) {
|
||||
$directory = $storagePath . "-hist";
|
||||
if (!file_exists($directory) && !is_dir($directory)) {
|
||||
mkdir($directory);
|
||||
}
|
||||
return $directory;
|
||||
}
|
||||
|
||||
function getVersionDir($histDir, $version) {
|
||||
return $histDir . DIRECTORY_SEPARATOR . $version;
|
||||
}
|
||||
|
||||
function getFileVersion($histDir) {
|
||||
if (!file_exists($histDir) || !is_dir($histDir)) return 0;
|
||||
|
||||
$cdir = scandir($histDir);
|
||||
$ver = 0;
|
||||
foreach($cdir as $key => $fileName) {
|
||||
if (!in_array($fileName,array(".", ".."))) {
|
||||
if (is_dir($histDir . DIRECTORY_SEPARATOR . $fileName)) {
|
||||
$ver++;
|
||||
}
|
||||
}
|
||||
}
|
||||
return $ver;
|
||||
}
|
||||
|
||||
function getStoredFiles() {
|
||||
$storagePath = trim(str_replace(array('/','\\'), DIRECTORY_SEPARATOR, $GLOBALS['STORAGE_PATH']), DIRECTORY_SEPARATOR);
|
||||
$directory = __DIR__ . DIRECTORY_SEPARATOR . $storagePath;
|
||||
@ -256,6 +283,33 @@ function getVirtualPath($forDocumentServer) {
|
||||
return $virtPath;
|
||||
}
|
||||
|
||||
function createMeta($fileName, $uid = "0") {
|
||||
$histDir = getHistoryDir(getStoragePath($fileName));
|
||||
|
||||
if (empty($uid)) $uid = "0";
|
||||
|
||||
$name = "";
|
||||
switch ($uid) {
|
||||
case 0:
|
||||
$name = "Jonn Smith";
|
||||
break;
|
||||
case 1:
|
||||
$name = "Mark Pottato";
|
||||
break;
|
||||
case 2:
|
||||
$name = "Hamish Mitchell";
|
||||
break;
|
||||
}
|
||||
|
||||
$json = [
|
||||
"created" => date("Y-m-d H:i:s"),
|
||||
"uid" => $uid,
|
||||
"name" => $name,
|
||||
];
|
||||
|
||||
file_put_contents($histDir . DIRECTORY_SEPARATOR . "createdInfo.json", json_encode($json, JSON_PRETTY_PRINT));
|
||||
}
|
||||
|
||||
function FileUri($file_name, $forDocumentServer = NULL) {
|
||||
$uri = getVirtualPath($forDocumentServer) . rawurlencode($file_name);
|
||||
return $uri;
|
||||
|
||||
@ -4,8 +4,6 @@ $GLOBALS['FILE_SIZE_MAX'] = 5242880;
|
||||
$GLOBALS['STORAGE_PATH'] = "";
|
||||
$GLOBALS['ALONE'] = FALSE;
|
||||
|
||||
$GLOBALS['MODE'] = "";
|
||||
|
||||
$GLOBALS['DOC_SERV_VIEWD'] = array(".pdf", ".djvu", ".xps");
|
||||
$GLOBALS['DOC_SERV_EDITED'] = array(".docx", ".xlsx", ".csv", ".pptx", ".txt");
|
||||
$GLOBALS['DOC_SERV_CONVERT'] = array(".docm", ".doc", ".dotx", ".dotm", ".dot", ".odt", ".fodt", ".ott", ".xlsm", ".xls", ".xltx", ".xltm", ".xlt", ".ods", ".fods", ".ots", ".pptm", ".ppt", ".ppsx", ".ppsm", ".pps", ".potx", ".potm", ".pot", ".odp", ".fodp", ".otp", ".rtf", ".mht", ".html", ".htm", ".epub");
|
||||
@ -17,6 +15,8 @@ $GLOBALS['DOC_SERV_API_URL'] = "https://documentserver/web-apps/apps/api/documen
|
||||
|
||||
$GLOBALS['DOC_SERV_PRELOADER_URL'] = "https://documentserver/web-apps/apps/api/documents/cache-scripts.html";
|
||||
|
||||
$GLOBALS['DOC_SERV_JWT_SECRET'] = "";
|
||||
|
||||
$GLOBALS['EXAMPLE_URL'] = "";
|
||||
|
||||
$GLOBALS['MOBILE_REGEX'] = "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";
|
||||
|
||||
BIN
web/documentserver-example/php/css/images/block-content-24.png
Normal file
|
After Width: | Height: | Size: 452 B |