diff --git a/jero-boot/jero-boot-base/jero-boot-base-core/src/main/java/com/jero/config/shiro/ShiroConfig.java b/jero-boot/jero-boot-base/jero-boot-base-core/src/main/java/com/jero/config/shiro/ShiroConfig.java index ed55f5f39..6db7c1945 100644 --- a/jero-boot/jero-boot-base/jero-boot-base-core/src/main/java/com/jero/config/shiro/ShiroConfig.java +++ b/jero-boot/jero-boot-base/jero-boot-base-core/src/main/java/com/jero/config/shiro/ShiroConfig.java @@ -72,6 +72,8 @@ public class ShiroConfig { // 配置不会被拦截的链接 顺序判断 filterChainDefinitionMap.put("/sys/cas/client/validateLogin", "anon"); //cas验证登录 filterChainDefinitionMap.put("/ocr/OcrRestful/ocrHandleResult", "anon"); //ocr回调接口 + filterChainDefinitionMap.put("/ocr/ocrCheck/downFile", "anon"); //ocr校核下载文件 + filterChainDefinitionMap.put("/ocr/ocrCheck/saveFile", "anon"); //ocr校核回调 filterChainDefinitionMap.put("/sys/randomImage/**", "anon"); //登录验证码接口排除 filterChainDefinitionMap.put("/sys/checkCaptcha", "anon"); //登录验证码接口排除 filterChainDefinitionMap.put("/sys/getRSAPublicKey", "anon"); //获取RSA公钥接口排除 diff --git a/jero-boot/jero-boot-modules/pom.xml b/jero-boot/jero-boot-modules/pom.xml index 82f9ecf17..d1605c902 100644 --- a/jero-boot/jero-boot-modules/pom.xml +++ b/jero-boot/jero-boot-modules/pom.xml @@ -150,6 +150,17 @@ org.springframework.boot spring-boot-starter-websocket + + + com.googlecode.json-simple + json-simple + 1.1 + + + com.inversoft + prime-jwt + 1.3.1 + diff --git a/jero-boot/jero-boot-modules/src/main/java/com/jero/modules/ocr/controller/OcrCheckController.java b/jero-boot/jero-boot-modules/src/main/java/com/jero/modules/ocr/controller/OcrCheckController.java new file mode 100644 index 000000000..e1f35b555 --- /dev/null +++ b/jero-boot/jero-boot-modules/src/main/java/com/jero/modules/ocr/controller/OcrCheckController.java @@ -0,0 +1,229 @@ +package com.jero.modules.ocr.controller; + +import com.jero.common.exception.JeroBootException; +import com.jero.common.system.vo.LoginUser; +import com.jero.modules.ocr.helpers.ConfigManager; +import com.jero.modules.ocr.helpers.DocumentManager; +import com.jero.modules.ocr.helpers.FileUtility; +import com.jero.modules.ocr.helpers.ServiceConverter; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.io.IOUtils; +import org.apache.shiro.SecurityUtils; +import org.json.simple.JSONObject; +import org.json.simple.parser.JSONParser; +import org.json.simple.parser.ParseException; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.ui.Model; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.servlet.ModelAndView; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.*; +import java.net.URL; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Scanner; + +/** + * @Author: liyawei + * @Description: + * @Date: Created in 10:51 2022/4/11 + */ +@Api(tags="OCR识别在线校核") +@RestController +@RequestMapping("/ocr/ocrCheck") +@Slf4j +public class OcrCheckController { + + @Value("${OCR.ocrDownPath}") + private String ocrDownPath; + + @Value("${OCR.ocrSavePath}") + private String ocrSavePath; + + @Value("${OCR.serverUrl}") + private String serverUrl; + + @Value("${OCR.ocrPath}") + private String ocrPath; + + @ApiOperation(value = "下载word文件") + @GetMapping("/downFile") + public void downFile(String fileName, HttpServletResponse response, HttpServletRequest request) throws Exception { + InputStream is = null; + OutputStream os = null; + response.reset(); + try { + String downFileName = fileName.substring(fileName.indexOf("_") + 1); + response.setHeader("Content-Disposition", "attachment; filename=" + downFileName); + response.setContentType("application/octet-stream"); + + String fullPath = ocrPath + fileName; + is = new FileInputStream(fullPath); + os = response.getOutputStream(); + IOUtils.copy(is, os); + os.flush(); + } catch (FileNotFoundException var4) { + throw new JeroBootException("文件[" + ocrPath + fileName + "]不存在"); + } catch (IOException e) { + log.error(e.getMessage(), e); + } finally { + is.close(); + os.close(); + } + } + + @ApiOperation(value = "编辑文件") + @RequestMapping("/editorFile") + public ModelAndView index(HttpServletRequest request, HttpServletResponse response, Model model) throws Exception { + + String fileName = ""; + if (request.getParameterMap().containsKey("fileName")) { + fileName = request.getParameter("fileName"); + } +// String fileExt = null; +// if (request.getParameterMap().containsKey("fileExt")) { +// fileExt = request.getParameter("fileExt"); +// } + +// if (fileExt != null) { +// try { +// DocumentManager.Init(request, response); +// fileName = DocumentManager.CreateDemo(fileExt); +// } catch (Exception ex) { +// return new ModelAndView(new FastJsonJsonView(),"Error: " + ex.getMessage(), ex) ; +// } +// } + +// String mode = ""; +// if (request.getParameterMap().containsKey("mode")) +// { +// mode = request.getParameter("mode"); +// } +// Boolean desktopMode = !"embedded".equals(mode); + +// FileModel file = new FileModel(); +// file.SetTypeDesktop(desktopMode); +// file.SetFileName(fileName); + + log.info("==========EditorFile=========="); + DocumentManager.Init(request, response); + //要编辑的文件名 + model.addAttribute("fileName", fileName) ; + //要编辑的文件类型 + model.addAttribute("fileType", FileUtility.GetFileExtension(fileName).replace(".", "")) ; + //要编辑的文档类型 + model.addAttribute("documentType",FileUtility.GetFileType(fileName).toString().toLowerCase()) ; + //要编辑的文档访问url +// model.addAttribute("fileUri",DocumentManager.GetFileUri(fileName, true)) ; +// model.addAttribute("callbackUrl", DocumentManager.GetCallback(fileName)) ; +// model.addAttribute("serverUrl", DocumentManager.GetServerUrl(true)) ; + model.addAttribute("fileUri", ocrDownPath + "?fileName=" + fileName) ; + model.addAttribute("callbackUrl", ocrSavePath + "?fileName=" + fileName) ; + model.addAttribute("serverUrl", serverUrl) ; + model.addAttribute("fileKey", ServiceConverter.GenerateRevisionId(DocumentManager.CurUserHostAddress(null) + ocrDownPath + "?fileName=" + fileName)) ; + model.addAttribute("editorMode", DocumentManager.GetEditedExts().contains(FileUtility.GetFileExtension(fileName)) && !"view".equals(request.getAttribute("mode")) ? "edit" : "view") ; + model.addAttribute("editorUserId",DocumentManager.CurUserHostAddress(null)) ; + LoginUser loginUser = (LoginUser) SecurityUtils.getSubject().getPrincipal(); + model.addAttribute("editorUserName", loginUser.getUsername()) ; + +// model.addAttribute("type", desktopMode ? "desktop" : "embedded"); + model.addAttribute("type", true ? "desktop" : "embedded"); + model.addAttribute("docserviceApiUrl", ConfigManager.GetProperty("files.docservice.url.api")); + model.addAttribute("docServiceUrlPreloader", ConfigManager.GetProperty("files.docservice.url.preloader")) ; + model.addAttribute("currentYear", "2022") ; + model.addAttribute("convertExts", String.join(",", DocumentManager.GetConvertExts())) ; + model.addAttribute("editedExts", String.join(",", DocumentManager.GetEditedExts())) ; + model.addAttribute("documentCreated", new SimpleDateFormat("MM/dd/yyyy").format(new Date())) ; + model.addAttribute("permissionsEdit", Boolean.toString(DocumentManager.GetEditedExts().contains(FileUtility.GetFileExtension(fileName))).toLowerCase()) ; + return new ModelAndView("editor") ; + } + + /** + * 文档编辑服务使用JavaScript API通知callbackUrl,向文档存储服务通知文档编辑的状态。文档编辑服务使用具有正文中的信息的POST请求。 + * https://api.onlyoffice.com/editors/callback + * 参数示例: + { + "actions": [{"type": 0, "userid": "78e1e841"}], + "changesurl": "https://documentserver/url-to-changes.zip", + "history": { + "changes": changes, + "serverVersion": serverVersion + }, + "key": "Khirz6zTPdfd7", + "status": 2, + "url": "https://documentserver/url-to-edited-document.docx", + "users": ["6d5a81d0"] + } + */ + @ApiOperation(value = "保存文件") + @RequestMapping("/saveFile") + public void saveFile(HttpServletRequest request, HttpServletResponse response) { + String fileName = ""; + if (request.getParameterMap().containsKey("fileName")) { + fileName = request.getParameter("fileName"); + } + PrintWriter writer = null; + log.info("==========SaveEditedFile=========="); + try { + writer = response.getWriter(); + Scanner scanner = new Scanner(request.getInputStream()).useDelimiter("\\A"); + String body = scanner.hasNext() ? scanner.next() : ""; + JSONObject jsonObj = (JSONObject) new JSONParser().parse(body); + log.info("status:" + jsonObj.get("status")); + /* + 0 - no document with the key identifier could be found, + 1 - document is being edited, + 2 - document is ready for saving, + 3 - document saving error has occurred, + 4 - document is closed with no changes, + 6 - document is being edited, but the current document state is saved, + 7 - error has occurred while force saving the document. + * */ + if ((long) jsonObj.get("status") == 2) { + /* + * 当我们关闭编辑窗口后,十秒钟左右onlyoffice会将它存储的我们的编辑后的文件,,此时status = 2,通过request发给我们,我们需要做的就是接收到文件然后回写该文件。 + * */ + + /* + * 定义要与文档存储服务保存的编辑文档的链接。当状态值仅等于2或3时,存在链路。 + * */ + String downloadUri = (String) jsonObj.get("url"); + log.info("文档编辑完成,现在开始保存编辑后的文档,其下载地址为:" + downloadUri); + //解析得出文件名 +// String fileName = downloadUri.substring(downloadUri.lastIndexOf('/') + 1); + log.info("下载的文件名:" + fileName); + + URL url = new URL(downloadUri); + java.net.HttpURLConnection connection = (java.net.HttpURLConnection) url.openConnection(); + InputStream stream = connection.getInputStream(); + + File savedFile = new File(ocrPath + fileName); + 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(); + } + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (ParseException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + /* + * status = 1,我们给onlyoffice的服务返回{"error":"0"}的信息,这样onlyoffice会认为回调接口是没问题的,这样就可以在线编辑文档了,否则的话会弹出窗口说明 + * */ + writer.write("{\"error\":0}"); + } +} diff --git a/jero-boot/jero-boot-modules/src/main/java/com/jero/modules/ocr/entity/CommentGroups.java b/jero-boot/jero-boot-modules/src/main/java/com/jero/modules/ocr/entity/CommentGroups.java new file mode 100644 index 000000000..4a6629f7c --- /dev/null +++ b/jero-boot/jero-boot-modules/src/main/java/com/jero/modules/ocr/entity/CommentGroups.java @@ -0,0 +1,17 @@ +package com.jero.modules.ocr.entity; + +import java.util.List; + +public class CommentGroups { + public List view; + public List edit; + public List remove; + public CommentGroups(){ + + } + public CommentGroups(List view, List edit, List remove){ + this.view = view; + this.edit = edit; + this.remove = remove; + } +} diff --git a/jero-boot/jero-boot-modules/src/main/java/com/jero/modules/ocr/entity/FileModel.java b/jero-boot/jero-boot-modules/src/main/java/com/jero/modules/ocr/entity/FileModel.java new file mode 100644 index 000000000..d45af8a55 --- /dev/null +++ b/jero-boot/jero-boot-modules/src/main/java/com/jero/modules/ocr/entity/FileModel.java @@ -0,0 +1,370 @@ +/** + * + * (c) Copyright Ascensio System SIA 2021 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.jero.modules.ocr.entity; + +import com.google.gson.Gson; +import com.google.gson.reflect.TypeToken; +import com.jero.modules.ocr.helpers.DocumentManager; +import com.jero.modules.ocr.helpers.FileUtility; +import com.jero.modules.ocr.helpers.ServiceConverter; +import org.json.simple.JSONArray; +import org.json.simple.JSONObject; +import org.json.simple.parser.JSONParser; + +import java.io.File; +import java.io.FileInputStream; +import java.util.*; + +public class FileModel +{ + public String type = "desktop"; + public String mode = "edit"; + public String documentType; + public Document document; + public EditorConfig editorConfig; + public String token; + + // create file model + public FileModel(String fileName, String lang, String actionData, User user) + { + if (fileName == null) fileName = ""; + fileName = fileName.trim(); // remove extra spaces in the file name + + // get file type from the file name (word, cell or slide) + documentType = FileUtility.GetFileType(fileName).toString().toLowerCase(); + + // set the document parameters + document = new Document(); + document.title = fileName; + document.url = DocumentManager.GetDownloadUrl(fileName); // get file url + document.urlUser = DocumentManager.GetFileUri(fileName, false); + document.fileType = FileUtility.GetFileExtension(fileName).replace(".", ""); // get file extension from the file name + // generate document key + document.key = ServiceConverter.GenerateRevisionId(DocumentManager.CurUserHostAddress(null) + "/" + fileName + "/" + Long.toString(new File(DocumentManager.StoragePath(fileName, null)).lastModified())); + document.info = new Info(); + document.info.favorite = user.favorite; + + String templatesImageUrl = DocumentManager.GetTemplateImageUrl(FileUtility.GetFileType(fileName)); + List> templates = new ArrayList<>(); + String createUrl = DocumentManager.GetCreateUrl(FileUtility.GetFileType(fileName)); + + // add templates for the "Create New" from menu option + Map templateForBlankDocument = new HashMap<>(); + templateForBlankDocument.put("image", ""); + templateForBlankDocument.put("title", "Blank"); + templateForBlankDocument.put("url", createUrl); + templates.add(templateForBlankDocument); + Map templateForDocumentWithSampleContent = new HashMap<>(); + templateForDocumentWithSampleContent.put("image", templatesImageUrl); + templateForDocumentWithSampleContent.put("title", "With sample content"); + templateForDocumentWithSampleContent.put("url", createUrl + "&sample=true"); + templates.add(templateForDocumentWithSampleContent); + + // set the editor config parameters + editorConfig = new EditorConfig(actionData); + editorConfig.callbackUrl = DocumentManager.GetCallback(fileName); // get callback url + + if (lang != null) editorConfig.lang = lang; // write language parameter to the config + + editorConfig.createUrl = !user.id.equals("uid-0") ? createUrl : null; + editorConfig.templates = user.templates ? templates : null; + + // write user information to the config (id, name and group) + editorConfig.user.id = user.id; + editorConfig.user.name = user.name; + editorConfig.user.group = user.group; + + // write the absolute URL to the file location + editorConfig.customization.goback.url = DocumentManager.GetServerUrl(false) + "/IndexServlet"; + + changeType(mode, type, user); + } + + // change the document type + public void changeType(String _mode, String _type, User user) + { + if (_mode != null) mode = _mode; + if (_type != null) type = _type; + + // check if the file with such an extension can be edited + String fileExt = FileUtility.GetFileExtension(document.title); + Boolean canEdit = DocumentManager.GetEditedExts().contains(fileExt); + // check if the Submit form button is displayed or not + editorConfig.customization.submitForm = mode.equals("fillForms") && user.id.equals("uid-1") && false; + + if ((!canEdit && mode.equals("edit") || mode.equals("fillForms")) && DocumentManager.GetFillExts().contains(fileExt)) { + canEdit = true; + mode = "fillForms"; + } + // set the mode parameter: change it to view if the document can't be edited + editorConfig.mode = canEdit && !mode.equals("view") ? "edit" : "view"; + + // set document permissions + document.permissions = new Permissions(mode, type, canEdit, user); + + if (type.equals("embedded")) InitDesktop(); // set parameters for the embedded document + } + + public void InitDesktop() + { + editorConfig.InitDesktop(document.urlUser); + } + + // generate document token + public void BuildToken() + { + // write all the necessary document parameters to the map + Map map = new HashMap<>(); + map.put("type", type); + map.put("documentType", documentType); + map.put("document", document); + map.put("editorConfig", editorConfig); + + // and create token from them + token = DocumentManager.CreateToken(map); + } + + // get document history + public String[] GetHistory() + { + JSONParser parser = new JSONParser(); + String histDir = DocumentManager.HistoryDir(DocumentManager.StoragePath(document.title, null)); // get history directory + if (DocumentManager.GetFileVersion(histDir) > 0) { + Integer curVer = DocumentManager.GetFileVersion(histDir); // get current file version if it is greater than 0 + + List hist = new ArrayList<>(); + Map histData = new HashMap(); + + for (Integer i = 1; i <= curVer; i++) { // run through all the file versions + Map obj = new HashMap(); + Map dataObj = new HashMap(); + String verDir = DocumentManager.VersionDir(histDir, i); // get the path to the given file version + + try { + String key = null; + + // get document key + key = i == curVer ? document.key : readFileToEnd(new File(verDir + File.separator + "key.txt")); + + obj.put("key", key); + obj.put("version", i); + + if (i == 1) { // check if the version number is equal to 1 + String createdInfo = readFileToEnd(new File(histDir + File.separator + "createdInfo.json")); // get file with meta data + JSONObject json = (JSONObject) parser.parse(createdInfo); // and turn it into json object + + // write meta information to the object (user information and creation date) + obj.put("created", json.get("created")); + Map user = new HashMap(); + 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 > 1) { //check if the version number is greater than 1 + // if so, get the path to the changes.json file + JSONObject changes = (JSONObject) parser.parse(readFileToEnd(new File(DocumentManager.VersionDir(histDir, i - 1) + File.separator + "changes.json"))); + JSONObject change = (JSONObject) ((JSONArray) changes.get("changes")).get(0); + + // write information about changes to the object + obj.put("changes", !change.isEmpty() ? changes.get("changes") : null); + obj.put("serverVersion", changes.get("serverVersion")); + obj.put("created", !change.isEmpty() ? change.get("created") : null); + obj.put("user", !change.isEmpty() ? change.get("user") : null); + + Map prev = (Map) histData.get(Integer.toString(i - 2)); // get the history data from the previous file version + Map prevInfo = new HashMap(); + prevInfo.put("key", prev.get("key")); // write key and url information about previous file version + prevInfo.put("url", prev.get("url")); + dataObj.put("previous", prevInfo); // write information about previous file version to the data object + // write the path to the diff.zip archive with differences in this file version + dataObj.put("changesUrl", DocumentManager.GetPathUri(DocumentManager.VersionDir(histDir, i - 1) + File.separator + "diff.zip")); + } + + if (DocumentManager.TokenEnabled()) + { + dataObj.put("token", DocumentManager.CreateToken(dataObj)); + } + + hist.add(obj); + histData.put(Integer.toString(i - 1), dataObj); + + } catch (Exception ex) { } + } + + // write history information about the current file version to the history object + Map histObj = new HashMap(); + histObj.put("currentVersion", curVer); + histObj.put("history", hist); + + Gson gson = new Gson(); + return new String[] { gson.toJson(histObj), gson.toJson(histData) }; + } + return new String[] { "", "" }; + } + + // read a file + private String readFileToEnd(File file) { + String output = ""; + try { + try(FileInputStream is = new FileInputStream(file)) + { + Scanner scanner = new Scanner(is); // read data from the source + scanner.useDelimiter("\\A"); + while (scanner.hasNext()) { + output += scanner.next(); + } + scanner.close(); + } + } catch (Exception e) { } + return output; + } + + // the document parameters + public class Document + { + public String title; + public String url; + public String urlUser; + public String fileType; + public String key; + public Info info; + public Permissions permissions; + } + + // the permissions parameters + public class Permissions + { + public Boolean comment; + public Boolean сopy; + public Boolean download; + public Boolean edit; + public Boolean print; + public Boolean fillForms; + public Boolean modifyFilter; + public Boolean modifyContentControl; + public Boolean review; + public List reviewGroups; + public CommentGroups commentGroups; + + // defines what can be done with a document + public Permissions(String mode, String type, Boolean canEdit, User user) + { + comment = !mode.equals("view") && !mode.equals("fillForms") && !mode.equals("embedded") && !mode.equals("blockcontent"); + сopy = !user.deniedPermissions.contains("сopy"); + download = !user.deniedPermissions.contains("download"); + edit = canEdit && (mode.equals("edit") || mode.equals("view") || mode.equals("filter") || mode.equals("blockcontent")); + print = !user.deniedPermissions.contains("print"); + fillForms = !mode.equals("view") && !mode.equals("comment") && !mode.equals("embedded") && !mode.equals("blockcontent"); + modifyFilter = !mode.equals("filter"); + modifyContentControl = !mode.equals("blockcontent"); + review = canEdit && (mode.equals("edit") || mode.equals("review")); + reviewGroups = user.reviewGroups; + commentGroups = user.commentGroups; + } + } + + // the Favorite icon state + public class Info + { + public Boolean favorite; + } + // the editor config parameters + public class EditorConfig + { + public HashMap actionLink = null; + public String mode = "edit"; + public String callbackUrl; + public String lang = "en"; + public String createUrl; + public List> templates; + public User user; + public Customization customization; + public Embedded embedded; + + public EditorConfig(String actionData) + { + // get the action in the document that will be scrolled to (bookmark or comment) + if (actionData != null) { + Gson gson = new Gson(); + actionLink = gson.fromJson(actionData, new TypeToken>() { }.getType()); + } + user = new User(); + customization = new Customization(); + } + + // set parameters for the embedded document + public void InitDesktop(String url) + { + embedded = new Embedded(); + embedded.saveUrl = url; // the absolute URL that will allow the document to be saved onto the user personal computer + embedded.embedUrl = url; // the absolute URL to the document serving as a source file for the document embedded into the web page + embedded.shareUrl = url; // the absolute URL that will allow other users to share this document + embedded.toolbarDocked = "top"; // the place for the embedded viewer toolbar, can be either top or bottom + } + + // default user parameters (id, name and group) + public class User + { + public String id; + public String name; + public String group; + } + + // customization parameters + public class Customization + { + public Goback goback; + public Boolean forcesave; + public Boolean submitForm; + + public Customization() + { + forcesave = false; + goback = new Goback(); + } + + public class Goback + { + public String url; + } + } + + // parameters for embedded document + public class Embedded + { + public String saveUrl; + public String embedUrl; + public String shareUrl; + public String toolbarDocked; + } + } + + + // turn java objects into json strings + public static String Serialize(FileModel model) + { + Gson gson = new Gson(); + return gson.toJson(model); + } +} diff --git a/jero-boot/jero-boot-modules/src/main/java/com/jero/modules/ocr/entity/FileType.java b/jero-boot/jero-boot-modules/src/main/java/com/jero/modules/ocr/entity/FileType.java new file mode 100644 index 000000000..12f4162e4 --- /dev/null +++ b/jero-boot/jero-boot-modules/src/main/java/com/jero/modules/ocr/entity/FileType.java @@ -0,0 +1,26 @@ +/** + * + * (c) Copyright Ascensio System SIA 2021 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.jero.modules.ocr.entity; + +public enum FileType +{ + Word, + Cell, + Slide +} \ No newline at end of file diff --git a/jero-boot/jero-boot-modules/src/main/java/com/jero/modules/ocr/entity/User.java b/jero-boot/jero-boot-modules/src/main/java/com/jero/modules/ocr/entity/User.java new file mode 100644 index 000000000..bb1933fd2 --- /dev/null +++ b/jero-boot/jero-boot-modules/src/main/java/com/jero/modules/ocr/entity/User.java @@ -0,0 +1,48 @@ +/** + * + * (c) Copyright Ascensio System SIA 2021 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.jero.modules.ocr.entity; + +import java.util.List; + +public class User { + public String id; + public String name; + public String email; + public String group; + public List reviewGroups; + public CommentGroups commentGroups; + public Boolean favorite; + public List deniedPermissions; + public List descriptions; + public Boolean templates; + + public User(String id, String name, String email, String group, List reviewGroups, CommentGroups commentGroups, + Boolean favorite, List deniedPermissions, List descriptions, Boolean templates) { + this.id = id; + this.name = name; + this.email = email; + this.group = group; + this.reviewGroups = reviewGroups; + this.commentGroups = commentGroups; + this.favorite = favorite; + this.deniedPermissions = deniedPermissions; + this.descriptions = descriptions; + this.templates = templates; + } +} \ No newline at end of file diff --git a/jero-boot/jero-boot-modules/src/main/java/com/jero/modules/ocr/helpers/ConfigManager.java b/jero-boot/jero-boot-modules/src/main/java/com/jero/modules/ocr/helpers/ConfigManager.java new file mode 100644 index 000000000..efddcd5fa --- /dev/null +++ b/jero-boot/jero-boot-modules/src/main/java/com/jero/modules/ocr/helpers/ConfigManager.java @@ -0,0 +1,61 @@ +/** + * + * (c) Copyright Ascensio System SIA 2021 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.jero.modules.ocr.helpers; + +import java.io.InputStream; +import java.util.Properties; + +public class ConfigManager +{ + private static Properties properties; + + static + { + Init(); + } + + private static void Init() + { + try + { + // get stream from the settings.properties resource and load it + properties = new Properties(); + InputStream stream = Thread.currentThread().getContextClassLoader().getResourceAsStream("settings.properties"); + properties.load(stream); + } + catch (Exception ex) + { + properties = null; + } + } + + // get name from the settings.properties file + public static String GetProperty(String name) + { + if (properties == null) + { + return ""; + } + + // get property by its name + String property = properties.getProperty(name); + + return property == null ? "" : property; + } +} \ No newline at end of file diff --git a/jero-boot/jero-boot-modules/src/main/java/com/jero/modules/ocr/helpers/CookieManager.java b/jero-boot/jero-boot-modules/src/main/java/com/jero/modules/ocr/helpers/CookieManager.java new file mode 100644 index 000000000..39cd2eeb7 --- /dev/null +++ b/jero-boot/jero-boot-modules/src/main/java/com/jero/modules/ocr/helpers/CookieManager.java @@ -0,0 +1,45 @@ +/** + * + * (c) Copyright Ascensio System SIA 2021 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.jero.modules.ocr.helpers; + +import javax.servlet.http.Cookie; +import javax.servlet.http.HttpServletRequest; +import java.io.UnsupportedEncodingException; +import java.net.URLDecoder; +import java.util.HashMap; + +public class CookieManager { + private HashMap cookiesMap; + + public CookieManager(HttpServletRequest request) throws UnsupportedEncodingException { + cookiesMap = new HashMap(); + + Cookie[] cookies = request.getCookies(); // get all the cookies from the request + if (cookies != null) { + for (Cookie cookie : cookies) { // run through all the cookies + cookiesMap.putIfAbsent(cookie.getName(), URLDecoder.decode(cookie.getValue(), "UTF-8")); // add cookie to the cookies map if its name isn't in the map yet + } + } + } + + // get cookie by its name + public String getCookie(String name) { + return cookiesMap.get(name); + } +} \ No newline at end of file diff --git a/jero-boot/jero-boot-modules/src/main/java/com/jero/modules/ocr/helpers/DocumentManager.java b/jero-boot/jero-boot-modules/src/main/java/com/jero/modules/ocr/helpers/DocumentManager.java new file mode 100644 index 000000000..3f8433699 --- /dev/null +++ b/jero-boot/jero-boot-modules/src/main/java/com/jero/modules/ocr/helpers/DocumentManager.java @@ -0,0 +1,519 @@ +/** + * + * (c) Copyright Ascensio System SIA 2021 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.jero.modules.ocr.helpers; + +import com.jero.modules.ocr.entity.FileType; +import com.jero.modules.ocr.entity.User; +import org.json.simple.JSONObject; +import org.primeframework.jwt.Signer; +import org.primeframework.jwt.Verifier; +import org.primeframework.jwt.domain.JWT; +import org.primeframework.jwt.hmac.HMACSigner; +import org.primeframework.jwt.hmac.HMACVerifier; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.*; +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.net.InetAddress; +import java.net.URLEncoder; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.text.SimpleDateFormat; +import java.util.*; + +public class DocumentManager +{ + private static HttpServletRequest request; + + public static void Init(HttpServletRequest req, HttpServletResponse resp) + { + request = req; + } + + // get max file size + public static long GetMaxFileSize() + { + long size; + + try + { + size = Long.parseLong(ConfigManager.GetProperty("filesize-max")); + } + catch (Exception ex) + { + size = 0; + } + + return size > 0 ? size : 5 * 1024 * 1024; + } + + // get all the supported file extensions + public static List GetFileExts() + { + List res = new ArrayList<>(); + + res.addAll(GetViewedExts()); + res.addAll(GetEditedExts()); + res.addAll(GetConvertExts()); + res.addAll(GetFillExts()); + + return res; + } + + public static List GetFillExts() { + String exts = ConfigManager.GetProperty("files.docservice.fill-docs"); + return Arrays.asList(exts.split("\\|")); + } + + // get file extensions that can be viewed + public static List GetViewedExts() + { + String exts = ConfigManager.GetProperty("files.docservice.viewed-docs"); + return Arrays.asList(exts.split("\\|")); + } + + // get file extensions that can be edited + public static List GetEditedExts() + { + String exts = ConfigManager.GetProperty("files.docservice.edited-docs"); + return Arrays.asList(exts.split("\\|")); + } + + // get file extensions that can be converted + public static List GetConvertExts() + { + String exts = ConfigManager.GetProperty("files.docservice.convert-docs"); + return Arrays.asList(exts.split("\\|")); + } + + // get current user host address + public static String CurUserHostAddress(String userAddress) + { + if(userAddress == null) + { + try + { + // use InetAddress class to get the user address if it wasn't passed to the function + userAddress = InetAddress.getLocalHost().getHostAddress(); + } + catch (Exception ex) + { + userAddress = ""; + } + } + + return userAddress.replaceAll("[^0-9a-zA-Z.=]", "_"); + } + + // get the root directory of the user host + public static String FilesRootPath(String userAddress) + { + String hostAddress = CurUserHostAddress(userAddress); // get current user host address + String serverPath = request.getSession().getServletContext().getRealPath(""); // get the server url + String storagePath = ConfigManager.GetProperty("storage-folder"); // get the storage directory + String directory = serverPath + storagePath + File.separator + hostAddress + File.separator; + + File file = new File(directory); + + // if the root directory doesn't exist + if (!file.exists()) + { + // create it + file.mkdirs(); + } + + return directory; + } + + // get the storage path of the file + public static String StoragePath(String fileName, String userAddress) + { + String directory = FilesRootPath(userAddress); + return directory + FileUtility.GetFileName(fileName); + } + + // get the path to the forcesaved file version + public static String ForcesavePath(String fileName, String userAddress, Boolean create) + { + String hostAddress = CurUserHostAddress(userAddress); + String serverPath = request.getSession().getServletContext().getRealPath(""); + String storagePath = ConfigManager.GetProperty("storage-folder"); + + // create the directory to this file version + String directory = serverPath + storagePath + File.separator + hostAddress + File.separator; + + File file = new File(directory); + if (!file.exists()) return ""; + + // create the directory to the history of this file version + directory = directory + fileName + "-hist" + File.separator; + file = new File(directory); + if (!create && !file.exists()) return ""; + + file.mkdirs(); + + directory = directory + fileName; + file = new File(directory); + if (!create && !file.exists()) { + return ""; + } + + return directory; + } + + // get the history directory + public static String HistoryDir(String storagePath) + { + return storagePath += "-hist"; + } + + // get the path to the file version by the history path and file version + public static String VersionDir(String histPath, Integer version) + { + return histPath + File.separator + Integer.toString(version); + } + + // get the path to the file version by the file name, user address and file version + public static String VersionDir(String fileName, String userAddress, Integer version) + { + return VersionDir(HistoryDir(StoragePath(fileName, userAddress)), version); + } + + // get the file version by the history path + public static Integer GetFileVersion(String historyPath) + { + File dir = new File(historyPath); + + if (!dir.exists()) return 1; // if the history path doesn't exist, then the file version is 1 + + File[] dirs = dir.listFiles(new FileFilter() { // take only directories from the history folder + @Override + public boolean accept(File pathname) { + return pathname.isDirectory(); + } + }); + + return dirs.length + 1; // count the directories + } + + // get the file version by the file name and user address + public static int GetFileVersion(String fileName, String userAddress) + { + return GetFileVersion(HistoryDir(StoragePath(fileName, userAddress))); + } + + // get a file name with an index if the file with such a name already exists + public static String GetCorrectName(String fileName, String userAddress) + { + String baseName = FileUtility.GetFileNameWithoutExtension(fileName); + String ext = FileUtility.GetFileExtension(fileName); + String name = baseName + ext; + + File file = new File(StoragePath(name, userAddress)); + + for (int i = 1; file.exists(); i++) // run through all the files with such a name in the storage directory + { + name = baseName + " (" + i + ")" + ext; // and add an index to the base name + file = new File(StoragePath(name, userAddress)); + } + + return name; + } + + // create meta information + public static void CreateMeta(String fileName, String uid, String uname, String userAddress) throws Exception + { + String histDir = HistoryDir(StoragePath(fileName, userAddress)); + + File dir = new File(histDir); // create history directory + dir.mkdir(); + + // create json object and put there file information (creation time, user id and name) + JSONObject json = new JSONObject(); + json.put("created", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())); + json.put("id", uid); + json.put("name", uname); + + // create createdInfo.json file with meta information in the history directory + File meta = new File(histDir + File.separator + "createdInfo.json"); + try (FileWriter writer = new FileWriter(meta)) { + json.writeJSONString(writer); // write information from the json object into this file + } + } + + // get all the stored files from the user host address + public static File[] GetStoredFiles(String userAddress) + { + String directory = FilesRootPath(userAddress); + + File file = new File(directory); + return file.listFiles(new FileFilter() { // take only files from the root directory + @Override + public boolean accept(File pathname) { + return pathname.isFile(); + } + }); + } + + // create demo document + public static String CreateDemo(String fileExt, Boolean sample, User user) throws Exception + { + String demoName = (sample ? "sample." : "new.") + fileExt; // create sample or new template file with the necessary extension + String demoPath = "assets" + File.separator + (sample ? "sample" : "new") + File.separator; // get the path to the sample document + String fileName = GetCorrectName(demoName, null); // get a file name with an index if the file with such a name already exists + + InputStream stream = Thread.currentThread().getContextClassLoader().getResourceAsStream(demoPath + demoName); // get the input file stream + + CreateFile(Paths.get(StoragePath(fileName, null)), stream); + + // create meta information of the demo file + CreateMeta(fileName, user.id, user.name, null); + + return fileName; + } + + public static boolean CreateFile(Path path, InputStream stream) { + if (Files.exists(path)){ + return true; + } + try { + File file = Files.createFile(path).toFile(); + 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(); + } + } catch (IOException e) { + e.printStackTrace(); + } + return false; + } + + // get file url + public static String GetFileUri(String fileName, Boolean forDocumentServer) + { + try + { + String serverPath = GetServerUrl(forDocumentServer); + String storagePath = ConfigManager.GetProperty("storage-folder"); + String hostAddress = CurUserHostAddress(null); + + String filePath = serverPath + "/" + storagePath + "/" + hostAddress + "/" + URLEncoder.encode(fileName, java.nio.charset.StandardCharsets.UTF_8.toString()).replace("+", "%20"); +// String filePath = serverPath + "?fileName=" + URLEncoder.encode(fileName, java.nio.charset.StandardCharsets.UTF_8.toString()).replace("+", "%20") + "&useraddress=" + hostAddress; + + return filePath; + } + catch (UnsupportedEncodingException e) + { + return ""; + } + } + + // get file information + public static ArrayList> GetFilesInfo(){ + ArrayList> files = new ArrayList<>(); + + // run through all the stored files + for(File file : GetStoredFiles(null)){ + Map map = new LinkedHashMap<>(); // write all the parameters to the map + map.put("version", GetFileVersion(file.getName(), null)); + map.put("id", ServiceConverter.GenerateRevisionId(CurUserHostAddress(null) + "/" + file.getName() + "/" + Long.toString(new File(StoragePath(file.getName(), null)).lastModified()))); + map.put("contentLength", new BigDecimal(String.valueOf((file.length()/1024.0))).setScale(2, RoundingMode.HALF_UP) + " KB"); + map.put("pureContentLength", file.length()); + map.put("title", file.getName()); + map.put("updated", String.valueOf(new Date(file.lastModified()))); + files.add(map); + } + + return files; + } + + // get file information by its id + public static ArrayList> GetFilesInfo(String fileId){ + ArrayList> file = new ArrayList<>(); + + for (Map map : GetFilesInfo()){ + if (map.get("id").equals(fileId)){ + file.add(map); + break; + } + } + + return file; + } + + // get the path url + public static String GetPathUri(String path) + { + String serverPath = GetServerUrl(true); + 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; + } + + + // get the server url + public static String GetServerUrl(Boolean forDocumentServer) { + if (forDocumentServer && !ConfigManager.GetProperty("files.docservice.url.example").equals("")) { + return ConfigManager.GetProperty("files.docservice.url.example"); + } else { + return request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + request.getContextPath(); + } + } + + // get the callback url + public static String GetCallback(String fileName) + { + String serverPath = GetServerUrl(true); + String hostAddress = CurUserHostAddress(null); + try + { + String query = "?type=track&fileName=" + URLEncoder.encode(fileName, java.nio.charset.StandardCharsets.UTF_8.toString()) + "&userAddress=" + URLEncoder.encode(hostAddress, java.nio.charset.StandardCharsets.UTF_8.toString()); + + return serverPath + "/IndexServlet" + query; + } + catch (UnsupportedEncodingException e) + { + return ""; + } + } + + // get url to the created file + public static String GetCreateUrl (FileType fileType) { + String serverPath = GetServerUrl(false); + String fileExt = GetInternalExtension(fileType).replace(".", ""); + String query = "?fileExt=" + fileExt; + + return serverPath + "/EditorServlet" + query; + } + + // get url to download a file + public static String GetDownloadUrl(String fileName) { + String serverPath = GetServerUrl(true); + String hostAddress = CurUserHostAddress(null); + try + { + String query = "?type=download&fileName=" + URLEncoder.encode(fileName, java.nio.charset.StandardCharsets.UTF_8.toString()) + "&userAddress=" + URLEncoder.encode(hostAddress, java.nio.charset.StandardCharsets.UTF_8.toString()); + + return serverPath + "/IndexServlet" + query; + } + catch (UnsupportedEncodingException e) + { + return ""; + } + } + + // get an editor internal extension + public static String GetInternalExtension(FileType fileType) + { + // .docx for word file type + if (fileType.equals(FileType.Word)) + return ".docx"; + + // .xlsx for cell file type + if (fileType.equals(FileType.Cell)) + return ".xlsx"; + + // .pptx for slide file type + if (fileType.equals(FileType.Slide)) + return ".pptx"; + + // the default file type is .docx + return ".docx"; + } + + // get image url for templates + public static String GetTemplateImageUrl(FileType fileType) + { + String path = GetServerUrl(true) + "/css/img/"; + // for word file type + if (fileType.equals(FileType.Word)) + return path + "file_docx.svg"; + + // .xlsx for cell file type + if (fileType.equals(FileType.Cell)) + return path + "file_xlsx.svg"; + + // .pptx for slide file type + if (fileType.equals(FileType.Slide)) + return path + "file_pptx.svg"; + + // the default file type + return path + "file_docx.svg"; + } + + // create document token + public static String CreateToken(Map payloadClaims) + { + try + { + // build a HMAC signer using a SHA-256 hash + Signer signer = HMACSigner.newSHA256Signer(GetTokenSecret()); + JWT jwt = new JWT(); + for (String key : payloadClaims.keySet()) // run through all the keys from the payload + { + jwt.addClaim(key, payloadClaims.get(key)); // and write each claim to the jwt + } + return JWT.getEncoder().encode(jwt, signer); // sign and encode the JWT to a JSON string representation + } + catch (Exception e) + { + return ""; + } + } + + // read document token + public static JWT ReadToken(String token) + { + try + { + // build a HMAC verifier using the token secret + Verifier verifier = HMACVerifier.newVerifier(GetTokenSecret()); + return JWT.getDecoder().decode(token, verifier); // verify and decode the encoded string JWT to a rich object + } + catch (Exception exception) + { + return null; + } + } + + // check if the token is enabled + public static Boolean TokenEnabled() + { + String secret = GetTokenSecret(); + return secret != null && !secret.isEmpty(); + } + + // get token secret from the config parameters + public static String GetTokenSecret() + { + return ConfigManager.GetProperty("files.docservice.secret"); + } +} \ No newline at end of file diff --git a/jero-boot/jero-boot-modules/src/main/java/com/jero/modules/ocr/helpers/FileUtility.java b/jero-boot/jero-boot-modules/src/main/java/com/jero/modules/ocr/helpers/FileUtility.java new file mode 100644 index 000000000..46f1dd6bb --- /dev/null +++ b/jero-boot/jero-boot-modules/src/main/java/com/jero/modules/ocr/helpers/FileUtility.java @@ -0,0 +1,132 @@ +/** + * + * (c) Copyright Ascensio System SIA 2021 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.jero.modules.ocr.helpers; + +import com.jero.modules.ocr.entity.FileType; + +import java.net.URL; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class FileUtility +{ + static {} + + // get file type + public static FileType GetFileType(String fileName) + { + String ext = GetFileExtension(fileName).toLowerCase(); + + // word type for document extensions + if (ExtsDocument.contains(ext)) + return FileType.Word; + + // cell type for spreadsheet extensions + if (ExtsSpreadsheet.contains(ext)) + return FileType.Cell; + + // slide type for presentation extensions + if (ExtsPresentation.contains(ext)) + return FileType.Slide; + + // default file type is word + return FileType.Word; + } + + // document extensions + public static List ExtsDocument = Arrays.asList + ( + ".doc", ".docx", ".docm", + ".dot", ".dotx", ".dotm", + ".odt", ".fodt", ".ott", ".rtf", ".txt", + ".html", ".htm", ".mht", ".xml", + ".pdf", ".djvu", ".fb2", ".epub", ".xps", ".oxps", ".oform" + ); + + // spreadsheet extensions + public static List ExtsSpreadsheet = Arrays.asList + ( + ".xls", ".xlsx", ".xlsm", + ".xlt", ".xltx", ".xltm", + ".ods", ".fods", ".ots", ".csv" + ); + + // presentation extensions + public static List ExtsPresentation = Arrays.asList + ( + ".pps", ".ppsx", ".ppsm", + ".ppt", ".pptx", ".pptm", + ".pot", ".potx", ".potm", + ".odp", ".fodp", ".otp" + ); + + + // get file name from the url + public static String GetFileName(String url) + { + if (url == null) return ""; + + // get file name from the last part of url + String fileName = url.substring(url.lastIndexOf('/') + 1, url.length()); + fileName = fileName.split("\\?")[0]; + return fileName; + } + + // get file name without extension + public static String GetFileNameWithoutExtension(String url) + { + String fileName = GetFileName(url); + if (fileName == null) return null; + String fileNameWithoutExt = fileName.substring(0, fileName.lastIndexOf('.')); + return fileNameWithoutExt; + } + + // get file extension from url + public static String GetFileExtension(String url) + { + String fileName = GetFileName(url); + if (fileName == null) return null; + String fileExt = fileName.substring(fileName.lastIndexOf(".")); + return fileExt.toLowerCase(); + } + + // get url parameters + public static Map GetUrlParams(String url) + { + try + { + String query = new URL(url).getQuery(); // take all the parameters which are placed after ? sign in the file url + String[] params = query.split("&"); // parameters are separated by & sign + Map map = new HashMap<>(); + for (String param : params) // write parameters and their values to the map dictionary + { + String name = param.split("=")[0]; + String value = param.split("=")[1]; + map.put(name, value); + } + return map; + } + catch (Exception ex) + { + return null; + } + } +} diff --git a/jero-boot/jero-boot-modules/src/main/java/com/jero/modules/ocr/helpers/ServiceConverter.java b/jero-boot/jero-boot-modules/src/main/java/com/jero/modules/ocr/helpers/ServiceConverter.java new file mode 100644 index 000000000..352270fdf --- /dev/null +++ b/jero-boot/jero-boot-modules/src/main/java/com/jero/modules/ocr/helpers/ServiceConverter.java @@ -0,0 +1,269 @@ +/** + * + * (c) Copyright Ascensio System SIA 2021 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.jero.modules.ocr.helpers; + +import com.google.gson.Gson; +import com.jero.modules.ocr.util.UUIDUtils; +import org.json.simple.JSONObject; +import org.json.simple.parser.JSONParser; +import org.json.simple.parser.ParseException; + +import java.io.*; +import java.net.URL; +import java.nio.charset.StandardCharsets; +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + + +public class ServiceConverter +{ + private static int ConvertTimeout = 120000; + private static final String DocumentConverterUrl = ConfigManager.GetProperty("files.docservice.url.site") + ConfigManager.GetProperty("files.docservice.url.converter"); + private static final String DocumentJwtHeader = ConfigManager.GetProperty("files.docservice.header"); + + public static class ConvertBody + { + public String region; + public String url; + public String outputtype; + public String filetype; + public String title; + public String key; + public Boolean async; + public String token; + public String password; + } + + static + { + try + { + // get timeout value from the settings.properties + int timeout = Integer.parseInt(ConfigManager.GetProperty("files.docservice.timeout")); + if (timeout > 0) // if it's greater than 0 + { + ConvertTimeout = timeout; // assign this value to a convert timeout + } + } + catch (Exception ex) + { + } + } + + // get the url of the converted file + public static String GetConvertedUri(String documentUri, String fromExtension, String toExtension, String documentRevisionId, String filePass, Boolean isAsync, String lang) throws Exception + { + // check if the fromExtension parameter is defined; if not, get it from the document url + fromExtension = fromExtension == null || fromExtension.isEmpty() ? FileUtility.GetFileExtension(documentUri) : fromExtension; + + // check if the file name parameter is defined; if not, get random uuid for this file + String title = FileUtility.GetFileName(documentUri); + title = title == null || title.isEmpty() ? UUID.randomUUID().toString() : title; + + documentRevisionId = documentRevisionId == null || documentRevisionId.isEmpty() ? documentUri : documentRevisionId; + + documentRevisionId = GenerateRevisionId(documentRevisionId); // create document token + + // write all the necessary parameters to the body object + ConvertBody body = new ConvertBody(); + body.region = lang; + body.url = documentUri; + body.outputtype = toExtension.replace(".", ""); + body.filetype = fromExtension.replace(".", ""); + body.title = title; + body.key = documentRevisionId; + body.password = filePass; + if (isAsync) + body.async = true; + + String headerToken = ""; + if (DocumentManager.TokenEnabled()) + { + HashMap map = new HashMap(); + map.put("region", lang); + map.put("url", body.url); + map.put("outputtype", body.outputtype); + map.put("filetype", body.filetype); + map.put("title", body.title); + map.put("key", body.key); + map.put("password", body.password); + if (isAsync) + map.put("async", body.async); + + // add token to the body if it is enabled + String token = DocumentManager.CreateToken(map); + body.token = token; + + Map payloadMap = new HashMap(); + payloadMap.put("payload", map); // create payload object + headerToken = DocumentManager.CreateToken(payloadMap); // create header token + } + + Gson gson = new Gson(); + String bodyString = gson.toJson(body); + + byte[] bodyByte = bodyString.getBytes(StandardCharsets.UTF_8); + + // specify request parameters + URL url = new URL(DocumentConverterUrl); + java.net.HttpURLConnection connection = (java.net.HttpURLConnection) url.openConnection(); + connection.setRequestMethod("POST"); + connection.setDoOutput(true); + connection.setRequestProperty("Content-Type", "application/json; charset=UTF-8"); + connection.setFixedLengthStreamingMode(bodyByte.length); + connection.setRequestProperty("Accept", "application/json"); + connection.setConnectTimeout(ConvertTimeout); + + // write header token to the request + if (DocumentManager.TokenEnabled()) + { + connection.setRequestProperty(DocumentJwtHeader.equals("") ? "Authorization" : DocumentJwtHeader, "Bearer " + headerToken); + } + + connection.connect(); + try (OutputStream os = connection.getOutputStream()) { + os.write(bodyByte); + } + + InputStream stream = connection.getInputStream(); + + if (stream == null) + throw new Exception("Could not get an answer"); + + // convert string to json + String jsonString = ConvertStreamToString(stream); + + connection.disconnect(); + + return GetResponseUri(jsonString); + } + + // generate document key + public static String GenerateRevisionId(String expectedKey) + { + if (expectedKey.length() > 20) // if the expected key length is greater than 20 + expectedKey = Integer.toString(expectedKey.hashCode()); // the expected key is hashed and a fixed length value is stored in the string format + + String key = UUIDUtils.randomUUID(2) + expectedKey.replace("[^0-9-.a-zA-Z_=]", "_"); + + return key.substring(0, Math.min(key.length(), 20)); // the resulting key length is 20 or less + } + + // create an error message for an error code + private static void ProcessConvertServiceResponceError(int errorCode) throws Exception + { + String errorMessage = ""; + String errorMessageTemplate = "Error occurred in the ConvertService: "; + + // add the error message to the error message template depending on the error code + switch (errorCode) + { + case -8: + errorMessage = errorMessageTemplate + "Error document VKey"; + break; + case -7: + errorMessage = errorMessageTemplate + "Error document request"; + break; + case -6: + errorMessage = errorMessageTemplate + "Error database"; + break; + case -5: + errorMessage = errorMessageTemplate + "Incorrect password"; + break; + case -4: + errorMessage = errorMessageTemplate + "Error download error"; + break; + case -3: + errorMessage = errorMessageTemplate + "Error convertation error"; + break; + case -2: + errorMessage = errorMessageTemplate + "Error convertation timeout"; + break; + case -1: + errorMessage = errorMessageTemplate + "Error convertation unknown"; + break; + case 0: // if the error code is equal to 0, the error message is empty + break; + default: + errorMessage = "ErrorCode = " + errorCode; // default value for the error message + break; + } + + throw new Exception(errorMessage); + } + + // get the response url + private static String GetResponseUri(String jsonString) throws Exception + { + JSONObject jsonObj = ConvertStringToJSON(jsonString); + + Object error = jsonObj.get("error"); + if (error != null) // if an error occurs + ProcessConvertServiceResponceError(Math.toIntExact((long)error)); // then get an error message + + // check if the conversion is completed and save the result to a variable + Boolean isEndConvert = (Boolean) jsonObj.get("endConvert"); + + Long resultPercent = 0l; + String responseUri = null; + + if (isEndConvert) // if the conversion is completed + { + resultPercent = 100l; + responseUri = (String) jsonObj.get("fileUrl"); // get the file url + } + else // if the conversion isn't completed + { + resultPercent = (Long) jsonObj.get("percent"); + resultPercent = resultPercent >= 100l ? 99l : resultPercent; // get the percentage value + } + + return resultPercent >= 100l ? responseUri : ""; + } + + // convert stream to string + public static String ConvertStreamToString(InputStream stream) throws IOException + { + InputStreamReader inputStreamReader = new InputStreamReader(stream); // create an object to get incoming stream + StringBuilder stringBuilder = new StringBuilder(); // create a string builder object + BufferedReader bufferedReader = new BufferedReader(inputStreamReader); // create an object to read incoming streams + String line = bufferedReader.readLine(); // get incoming streams by lines + + while (line != null) + { + stringBuilder.append(line); // concatenate strings using the string builder + line = bufferedReader.readLine(); + } + + String result = stringBuilder.toString(); + + return result; + } + + // convert string to json + public static JSONObject ConvertStringToJSON(String jsonString) throws ParseException + { + JSONParser parser = new JSONParser(); + Object obj = parser.parse(jsonString); // parse json string + JSONObject jsonObj = (JSONObject) obj; // and turn it into a json object + + return jsonObj; + } +} \ No newline at end of file diff --git a/jero-boot/jero-boot-modules/src/main/java/com/jero/modules/ocr/helpers/TrackManager.java b/jero-boot/jero-boot-modules/src/main/java/com/jero/modules/ocr/helpers/TrackManager.java new file mode 100644 index 000000000..30f70155e --- /dev/null +++ b/jero-boot/jero-boot-modules/src/main/java/com/jero/modules/ocr/helpers/TrackManager.java @@ -0,0 +1,323 @@ +/** + * + * (c) Copyright Ascensio System SIA 2021 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.jero.modules.ocr.helpers; + +import com.google.gson.Gson; +import org.json.simple.JSONArray; +import org.json.simple.JSONObject; +import org.json.simple.parser.JSONParser; +import org.primeframework.jwt.domain.JWT; + +import javax.servlet.http.HttpServletRequest; +import java.io.*; +import java.net.URL; +import java.nio.charset.StandardCharsets; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Scanner; + +public class TrackManager { + private static final String DocumentJwtHeader = ConfigManager.GetProperty("files.docservice.header"); + + // read request body + public static JSONObject readBody(HttpServletRequest request, PrintWriter writer) throws Exception { + String bodyString = ""; + + try { + // read request body by streams + Scanner scanner = new Scanner(request.getInputStream()); + scanner.useDelimiter("\\A"); + bodyString = scanner.hasNext() ? scanner.next() : ""; + scanner.close(); + } + catch (Exception ex) { + writer.write("get request.getInputStream error:" + ex.getMessage()); + throw ex; + } + + // error when the bodyString object is empty + if (bodyString.isEmpty()) { + writer.write("empty request.getInputStream"); + throw new Exception("empty request.getInputStream"); + } + + JSONParser parser = new JSONParser(); + JSONObject body; + + try { + Object obj = parser.parse(bodyString); // parse bodyString object + body = (JSONObject) obj; + } catch (Exception ex) { + writer.write("JSONParser.parse error:" + ex.getMessage()); + throw ex; + } + + // if the secret key to generate token exists + if (DocumentManager.TokenEnabled()) { + String token = (String) body.get("token"); // get the document token + + if (token == null) { // if JSON web token is not received + String header = (String) request.getHeader(DocumentJwtHeader == null || DocumentJwtHeader.isEmpty() ? "Authorization" : DocumentJwtHeader); // get it from the Authorization header + if (header != null && !header.isEmpty()) { + token = header.startsWith("Bearer ") ? header.substring(7) : header; // and save it without Authorization prefix + } + } + + if (token == null || token.isEmpty()) { // if the token is not received + writer.write("{\"error\":1,\"message\":\"JWT expected\"}"); // an error occurs + throw new Exception("{\"error\":1,\"message\":\"JWT expected\"}"); + } + + JWT jwt = DocumentManager.ReadToken(token); // read token + if (jwt == null) { + writer.write("{\"error\":1,\"message\":\"JWT validation failed\"}"); // an error occurs + throw new Exception("{\"error\":1,\"message\":\"JWT validation failed\"}"); + } + + if (jwt.getObject("payload") != null) { // get the payload object from the request body + try { + @SuppressWarnings("unchecked") LinkedHashMap payload = + (LinkedHashMap)jwt.getObject("payload"); + + jwt.claims = payload; + } catch (Exception ex) { + writer.write("{\"error\":1,\"message\":\"Wrong payload\"}"); + throw ex; + } + } + + try { + Gson gson = new Gson(); + Object obj = parser.parse(gson.toJson(jwt.claims)); + body = (JSONObject) obj; + } catch (Exception ex) { + writer.write("JSONParser.parse error:" + ex.getMessage()); + throw ex; + } + } + + return body; + } + + // file saving process + public static void processSave(JSONObject body, String fileName, String userAddress) throws Exception { + if (body.get("url") == null) { + throw new Exception("DownloadUrl is null"); + } + String downloadUri = (String) body.get("url"); + String changesUri = (String) body.get("changesurl"); + String key = (String) body.get("key"); + String newFileName = fileName; + + String curExt = FileUtility.GetFileExtension(fileName); // get current file extension + String downloadExt = FileUtility.GetFileExtension(downloadUri); // get the extension of the downloaded file + + // convert downloaded file to the file with the current extension if these extensions aren't equal + if (!curExt.equals(downloadExt)) { + try { + String newFileUri = ServiceConverter.GetConvertedUri(downloadUri, downloadExt, curExt, ServiceConverter.GenerateRevisionId(downloadUri), null, false, null); // convert file and get url to a new file + if (newFileUri.isEmpty()) { + newFileName = DocumentManager.GetCorrectName(FileUtility.GetFileNameWithoutExtension(fileName) + downloadExt, userAddress); // get the correct file name if it already exists + } else { + downloadUri = newFileUri; + } + } catch (Exception e){ + newFileName = DocumentManager.GetCorrectName(FileUtility.GetFileNameWithoutExtension(fileName) + downloadExt, userAddress); + } + } + + String storagePath = DocumentManager.StoragePath(newFileName, userAddress); // get the file path + File histDir = new File(DocumentManager.HistoryDir(storagePath)); // get the path to the history direction + if (!histDir.exists()) histDir.mkdirs(); // if the path doesn't exist, create it + + String versionDir = DocumentManager.VersionDir(histDir.getAbsolutePath(), DocumentManager.GetFileVersion(histDir.getAbsolutePath())); // get the path to the file version + File ver = new File(versionDir); + File lastVersion = new File(DocumentManager.StoragePath(fileName, userAddress)); + File toSave = new File(storagePath); + + if (!ver.exists()) ver.mkdirs(); + + lastVersion.renameTo(new File(versionDir + File.separator + "prev" + curExt)); // get the path to the previous file version and rename the last file version with it + + downloadToFile(downloadUri, toSave); // save file to the storage path + downloadToFile(changesUri, new File(versionDir + File.separator + "diff.zip")); // save file changes to the diff.zip archive + + String history = (String) body.get("changeshistory"); + if (history == null && body.containsKey("history")) { + history = ((JSONObject) body.get("history")).toJSONString(); + } + if (history != null && !history.isEmpty()) { + FileWriter fw = new FileWriter(new File(versionDir + File.separator + "changes.json")); // write the history changes to the changes.json file + fw.write(history); + fw.close(); + } + + FileWriter fw = new FileWriter(new File(versionDir + File.separator + "key.txt")); // write the key value to the key.txt file + fw.write(key); + fw.close(); + + String forcesavePath = DocumentManager.ForcesavePath(newFileName, userAddress, false); // get the path to the forcesaved file version + if (!forcesavePath.equals("")) { // if the forcesaved file version exists + File forceSaveFile = new File(forcesavePath); + forceSaveFile.delete(); // remove it + } + } + + // file force saving process + public static void processForceSave(JSONObject body, String fileName, String userAddress) throws Exception { + if (body.get("url") == null) { + throw new Exception("DownloadUrl is null"); + } + String downloadUri = (String) body.get("url"); + + String curExt = FileUtility.GetFileExtension(fileName); // get current file extension + String downloadExt = FileUtility.GetFileExtension(downloadUri); // get the extension of the downloaded file + Boolean newFileName = false; + + // convert downloaded file to the file with the current extension if these extensions aren't equal + if (!curExt.equals(downloadExt)) { + try { + String newFileUri = ServiceConverter.GetConvertedUri(downloadUri, downloadExt, curExt, ServiceConverter.GenerateRevisionId(downloadUri), null, false, null); // convert file and get url to a new file + if (newFileUri.isEmpty()) { + newFileName = true; + } else { + downloadUri = newFileUri; + } + } catch (Exception e){ + newFileName = true; + } + } + + String forcesavePath = ""; + boolean isSubmitForm = body.get("forcesavetype").toString().equals("3"); // SubmitForm + + if (isSubmitForm) { // if the form is submitted + // new file + if (newFileName){ + fileName = DocumentManager.GetCorrectName(FileUtility.GetFileNameWithoutExtension(fileName) + "-form" + downloadExt, userAddress); // get the correct file name if it already exists + } else { + fileName = DocumentManager.GetCorrectName(FileUtility.GetFileNameWithoutExtension(fileName) + "-form" + curExt, userAddress); + } + forcesavePath = DocumentManager.StoragePath(fileName, userAddress); + } else { + if (newFileName){ + fileName = DocumentManager.GetCorrectName(FileUtility.GetFileNameWithoutExtension(fileName) + downloadExt, userAddress); + } + + // create forcesave path if it doesn't exist + forcesavePath = DocumentManager.ForcesavePath(fileName, userAddress, false); + if (forcesavePath == "") { + forcesavePath = DocumentManager.ForcesavePath(fileName, userAddress, true); + } + } + + File toSave = new File(forcesavePath); + downloadToFile(downloadUri, toSave); + + if (isSubmitForm) { + JSONArray actions = (JSONArray) body.get("actions"); + JSONObject action = (JSONObject) actions.get(0); + String user = (String) action.get("userid"); // get the user id + DocumentManager.CreateMeta(fileName, user, "Filling Form", userAddress); // create meta data for forcesaved file + } + } + + // save file information from the url to the file specified + private static void downloadToFile(String url, File file) throws Exception { + if (url == null || url.isEmpty()) throw new Exception("argument url"); // url isn't specified + if (file == null) throw new Exception("argument path"); // file isn't specified + + URL uri = new URL(url); + java.net.HttpURLConnection connection = (java.net.HttpURLConnection) uri.openConnection(); + InputStream stream = connection.getInputStream(); // get input stream of the file information from the url + + 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); // write bytes to the output stream + } + + // force write data to the output stream that can be cached in the current thread + out.flush(); + } + + connection.disconnect(); + } + + // create a command request + public static void commandRequest(String method, String key) throws Exception { + String DocumentCommandUrl = ConfigManager.GetProperty("files.docservice.url.site") + ConfigManager.GetProperty("files.docservice.url.command"); + + URL url = new URL(DocumentCommandUrl); + java.net.HttpURLConnection connection = (java.net.HttpURLConnection) url.openConnection(); + + HashMap params = new HashMap(); + params.put("c", method); + params.put("key", key); + + String headerToken = ""; + if (DocumentManager.TokenEnabled()) // check if a secret key to generate token exists or not + { + Map payloadMap = new HashMap(); + payloadMap.put("payload", params); + headerToken = DocumentManager.CreateToken(payloadMap); // encode a payload object into a header token + + // add a header Authorization with a header token and Authorization prefix in it + connection.setRequestProperty(DocumentJwtHeader.equals("") ? "Authorization" : DocumentJwtHeader, "Bearer " + headerToken); + + String token = DocumentManager.CreateToken(params); // encode a payload object into a body token + params.put("token", token); + } + + Gson gson = new Gson(); + String bodyString = gson.toJson(params); + + byte[] bodyByte = bodyString.getBytes(StandardCharsets.UTF_8); + + connection.setRequestMethod("POST"); // set the request method + connection.setRequestProperty("Content-Type", "application/json; charset=UTF-8"); // set the Content-Type header + connection.setDoOutput(true); // set the doOutput field to true + + connection.connect(); + try (OutputStream os = connection.getOutputStream()) { + os.write(bodyByte); // write bytes to the output stream + } + InputStream stream = connection.getInputStream();; // get input stream + + if (stream == null) + throw new Exception("Could not get an answer"); + + String jsonString = ServiceConverter.ConvertStreamToString(stream); // convert stream to json string + connection.disconnect(); + + JSONObject response = ServiceConverter.ConvertStringToJSON(jsonString); // convert json string to json object + if (!response.get("error").toString().equals("0")){ + throw new Exception(response.toJSONString()); + } + } +} diff --git a/jero-boot/jero-boot-modules/src/main/java/com/jero/modules/ocr/helpers/Users.java b/jero-boot/jero-boot-modules/src/main/java/com/jero/modules/ocr/helpers/Users.java new file mode 100644 index 000000000..2c74f0079 --- /dev/null +++ b/jero-boot/jero-boot-modules/src/main/java/com/jero/modules/ocr/helpers/Users.java @@ -0,0 +1,110 @@ +/** + * + * (c) Copyright Ascensio System SIA 2021 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.jero.modules.ocr.helpers; + +import com.jero.modules.ocr.entity.CommentGroups; +import com.jero.modules.ocr.entity.User; + +import java.util.*; + +public class Users { + + static List descr_user_1 = new ArrayList() {{ + add("File author by default"); + add("Doesn’t belong to any group"); + add("Can review all the changes"); + add("Can perform all actions with comments"); + add("The file favorite state is undefined"); + add("Can create files from templates using data from the editor"); + }}; + + static List descr_user_2 = new ArrayList() {{ + add("Belongs to Group2"); + add("Can review only his own changes or changes made by users with no group"); + add("Can view comments, edit his own comments and comments left by users with no group. Can remove his own comments only"); + add("This file is marked as favorite"); + add("Can create new files from the editor"); + }}; + + static List descr_user_3 = new ArrayList() {{ + add("Belongs to Group3"); + add("Can review changes made by Group2 users"); + add("Can view comments left by Group2 and Group3 users. Can edit comments left by Group2 users"); + add("This file isn’t marked as favorite"); + add("Can’t copy data from the file to clipboard"); + add("Can’t download the file"); + add("Can’t print the file"); + add("Can create new files from the editor"); + }}; + + static List descr_user_0 = new ArrayList() {{ + add("The name is requested when the editor is opened"); + add("Doesn’t belong to any group"); + add("Can review all the changes"); + add("Can perform all actions with comments"); + add("The file favorite state is undefined"); + add("Can't mention others in comments"); + add("Can't create new files from the editor"); + }}; + + private static List users = new ArrayList() {{ + add(new User("uid-1", "John Smith", "smith@example.com", + null, null, new CommentGroups(), + null, new ArrayList(), descr_user_1, true)); + add(new User("uid-2", "Mark Pottato", "pottato@example.com", + "group-2", Arrays.asList("group-2", ""), new CommentGroups(null, Arrays.asList("group-2", ""), Arrays.asList("group-2")), + true, new ArrayList(), descr_user_2, false)); + add(new User("uid-3", "Hamish Mitchell", "mitchell@example.com", + "group-3", Arrays.asList("group-2"), new CommentGroups(Arrays.asList("group-3", "group-2"), Arrays.asList("group-2"), new ArrayList()), + false, Arrays.asList("copy", "download", "print"), descr_user_3, false)); + add(new User("uid-0", null, null, + null, null, new CommentGroups(), + null, new ArrayList(), descr_user_0, false)); + }}; + + // get a user by id specified + public static User getUser (String id) { + for (User user : users) { + if (user.id.equals(id)) { + return user; + } + } + return users.get(0); + } + + // get a list of all the users + public static List getAllUsers () { + return users; + } + + // get a list of users with their names and emails for mentions + public static List> getUsersForMentions (String id) { + List> usersData = new ArrayList<>(); + for (User user : users) { + if (!user.id.equals(id) && user.name != null && user.email != null) { + Map data = new HashMap<>(); + data.put("name", user.name); + data.put("email", user.email); + usersData.add(data); + } + } + return usersData; + } +} + diff --git a/jero-boot/jero-boot-modules/src/main/resources/asstes/css/editor.css b/jero-boot/jero-boot-modules/src/main/resources/asstes/css/editor.css new file mode 100644 index 000000000..9b66db3c8 --- /dev/null +++ b/jero-boot/jero-boot-modules/src/main/resources/asstes/css/editor.css @@ -0,0 +1,44 @@ +/** + * + * (c) Copyright Ascensio System SIA 2021 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +html { + height: 100%; + width: 100%; +} + +body { + background: #fff; + color: #333; + font-family: Arial, Tahoma,sans-serif; + font-size: 12px; + font-weight: normal; + height: 100%; + margin: 0; + overflow-y: hidden; + padding: 0; + text-decoration: none; +} + +.form { + height: 100%; +} + +div { + margin: 0; + padding: 0; +} diff --git a/jero-boot/jero-boot-modules/src/main/resources/asstes/favicon.ico b/jero-boot/jero-boot-modules/src/main/resources/asstes/favicon.ico new file mode 100644 index 000000000..dc87d1a88 Binary files /dev/null and b/jero-boot/jero-boot-modules/src/main/resources/asstes/favicon.ico differ diff --git a/jero-boot/jero-boot-modules/src/main/resources/settings.properties b/jero-boot/jero-boot-modules/src/main/resources/settings.properties new file mode 100644 index 000000000..0e4b38478 --- /dev/null +++ b/jero-boot/jero-boot-modules/src/main/resources/settings.properties @@ -0,0 +1,24 @@ +version=1.1.0 + +filesize-max=5242880 +storage-folder=D:\\OOFILES + +files.docservice.fill-docs=.oform|.docx +files.docservice.viewed-docs=.pdf|.djvu|.xps|.oxps +files.docservice.edited-docs=.docx|.xlsx|.csv|.pptx|.txt|.docxf +files.docservice.convert-docs=.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|.xml|.epub|.fb2 +files.docservice.timeout=120000 + +files.docservice.url.site=http://172.29.96.1:9000/ +files.docservice.url.command=http://172.29.96.1:9000/coauthoring/CommandService.ashx + +files.docservice.url.converter= http://172.29.96.1:9000/ConvertService.ashx +files.docservice.url.tempstorage= http://172.29.96.1:9000/ResourceService.ashx +files.docservice.url.api= http://172.29.96.1:9000/web-apps/apps/api/documents/api.js +files.docservice.url.preloader= http://172.29.96.1:9000/web-apps/apps/api/documents/cache-scripts.html + +files.docservice.url.example= http://172.29.96.1:9000 + + +files.docservice.secret= +files.docservice.header=Authorization \ No newline at end of file diff --git a/jero-boot/jero-boot-modules/src/main/resources/templates/editor.html b/jero-boot/jero-boot-modules/src/main/resources/templates/editor.html new file mode 100644 index 000000000..1b16771cf --- /dev/null +++ b/jero-boot/jero-boot-modules/src/main/resources/templates/editor.html @@ -0,0 +1,127 @@ + + + + + ONLYOFFICE + + + + + + +
+
+
+ + \ No newline at end of file diff --git a/jero-boot/jero-boot-single-startup/src/main/resources/application-dev.yml b/jero-boot/jero-boot-single-startup/src/main/resources/application-dev.yml index 48ebeedd5..6878d07fb 100644 --- a/jero-boot/jero-boot-single-startup/src/main/resources/application-dev.yml +++ b/jero-boot/jero-boot-single-startup/src/main/resources/application-dev.yml @@ -195,7 +195,7 @@ jero : path : #文件上传根目录 设置 upload: D://opt//upFiles - img: D://opt//upFiles + img: D://opt//upFiles/ #webapp文件路径 webapp: D://opt//webapp shiro: @@ -324,9 +324,12 @@ OCR: # OCR文件存储路径 ocrPath: D:/APPSOFT/LAWSOCRDEMO/OCRFILE/ #ocrPath: /data/DeploymentPackage/laws-shanqi/APPSOFT/LAWSOCRDEMO/OCRFILE/ - # OCR文件下载地址 -# ocrDownPath: http://139.9.235.66:9020/downfile/ - ocrDownPath: http://127.0.0.1:9020/downfile/ + # OCR文件下载地址(onlyoffice专用) + ocrDownPath: http://10.0.1.25:8080/jero-boot/ocr/ocrCheck/downFile + # OCR文件保存地址(onlyoffice专用) + ocrSavePath: http://10.0.1.25:8080/jero-boot/ocr/ocrCheck/saveFile + # OCR文件编辑失败返回列表页(onlyoffice专用) + serverUrl: http://10.0.1.25:3000/docManage/ocr # OCR接口超时时间 times: 20 # OCR转换类型